diff --git a/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/EntityFrameworkTest.db b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/EntityFrameworkTest.db index 16c6f2b6..f1a5a1d2 100644 Binary files a/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/EntityFrameworkTest.db and b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/EntityFrameworkTest.db differ diff --git a/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SessionTest.cs b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SessionTest.cs new file mode 100644 index 00000000..7c9d7fa6 --- /dev/null +++ b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SessionTest.cs @@ -0,0 +1,672 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Newtonsoft.Json; +using Sif.Framework.EntityFramework.Tests.SetUp; +using Sif.Framework.Model.Sessions; +using Sif.Framework.Service.Sessions; +using Sif.Framework.Shared; +using System; +using System.Linq; +using Tardigrade.Framework.Exceptions; +using Tardigrade.Framework.Persistence; +using Xunit; +using Xunit.Abstractions; + +namespace Sif.Framework.EntityFramework.Tests +{ + public class SessionTest : IClassFixture + { + private readonly ITestOutputHelper output; + private readonly Session reference; + private readonly IRepository repository; + private readonly ISessionService service; + + public SessionTest(UnitTestFixture fixture, ITestOutputHelper output) + { + this.output = output; + repository = fixture.Container.GetService>(); + service = fixture.Container.GetService(); + reference = fixture.Reference; + } + + /// + /// Create a copy of the original Session, but with a new Id. + /// + /// Session to copy. + /// Copy of the original Session. + private static Session CopySession(Session original) + { + return new Session + { + ApplicationKey = original.ApplicationKey, + EnvironmentUrl = original.EnvironmentUrl, + Id = Guid.NewGuid(), + QueueId = original.QueueId, + SessionToken = original.SessionToken, + SolutionId = original.SolutionId, + SubscriptionId = original.SubscriptionId + }; + } + + [Fact] + public void Crud_NewObject_Success() + { + int originalCount = repository.Count(); + output.WriteLine($"Total number of sessions before executing CRUD operations is {originalCount}."); + + // Create. + Session original = DataFactory.CreateSession(); + Session created = repository.Create(original); + output.WriteLine($"Created new session:\n{JsonConvert.SerializeObject(created)}"); + Assert.Equal(original.Id, created.Id); + + // Retrieve single. + Session retrieved = repository.Retrieve(created.Id); + output.WriteLine($"Retrieved newly created session:\n{JsonConvert.SerializeObject(retrieved)}"); + Assert.Equal(created.Id, retrieved.Id); + + // Update. + const string updatedSolutionId = "Sif3Framework2"; + retrieved.SolutionId = updatedSolutionId; + repository.Update(retrieved); + Session updated = repository.Retrieve(retrieved.Id); + output.WriteLine( + $"Updated the SolutionId of the newly created session to {updatedSolutionId}:\n{JsonConvert.SerializeObject(updated)}"); + Assert.Equal(retrieved.Id, updated.Id); + Assert.Equal(updatedSolutionId, updated.SolutionId); + + // Delete. + repository.Delete(created); + Session deleted = repository.Retrieve(created.Id); + output.WriteLine($"Successfully deleted session {created.Id} - {deleted == null}."); + Assert.Null(deleted); + int currentCount = repository.Count(); + output.WriteLine($"Total number of sessions after executing CRUD operation is {currentCount}."); + Assert.Equal(originalCount, currentCount); + } + + [Fact] + public void HasSession_Exists_Success() + { + // Act. + bool exists = service.HasSession(reference.ApplicationKey, reference.SolutionId); + + // Assert. + Assert.True(exists); + } + + [Theory] + [InlineData("Sif3DemoConsumer")] + [InlineData("Sif3DemoConsumer", "Sif3Framework2")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah", "De Blah")] + public void HasSession_NotExists_Failure( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + // Act. + bool exists = service.HasSession(applicationKey, solutionId, userToken, instanceId); + + // Assert. + Assert.False(exists); + } + + [Fact] + public void HasSession_NullApplicationKey_ArgumentNullException() + { + // Assert. + Assert.Throws(() => service.HasSession(null)); + } + + [Fact] + public void HasSessionToken_Exists_Success() + { + // Act. + bool exists = service.HasSessionToken(reference.SessionToken); + + // Assert. + Assert.True(exists); + } + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData("Nonsense")] + public void HasSessionToken_NotExists_Failure(string sessionToken) + { + // Act. + bool exists = service.HasSessionToken(sessionToken); + + // Assert. + Assert.False(exists); + } + + [Fact] + public void HasSessionToken_NullApplicationKey_ArgumentNullException() + { + // Assert. + Assert.Throws(() => service.HasSessionToken(null)); + } + + [Fact] + public void RemoveSession_MultipleSessions_DuplicateFoundException() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session copy = CopySession(original); + _ = repository.Create(original); + _ = repository.Create(copy); + + // Assert. + Assert.Throws(() => service.RemoveSession(original.SessionToken)); + + // Restore. + repository.Delete(original); + repository.Delete(copy); + } + + [Fact] + public void RemoveSession_NewSession_Success() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session created = repository.Create(original); + + // Act. + service.RemoveSession(created.SessionToken); + + // Assert. + bool exists = repository.Exists(original.Id); + Assert.False(exists); + } + + [Fact] + public void RemoveSession_NoSession_NotFoundException() + { + // Assert. + Assert.Throws(() => service.RemoveSession("FakeSessionToken")); + } + + [Fact] + public void RemoveSession_NullApplicationKey_ArgumentNullException() + { + // Assert. + Assert.Throws(() => service.RemoveSession(null)); + } + + [Fact] + public void RetrieveEnvironmentUrl_Exists_Success() + { + // Act. + string url = service.RetrieveEnvironmentUrl( + reference.ApplicationKey, + reference.SolutionId, + reference.UserToken, + reference.InstanceId); + + // Assert. + Assert.Equal(reference.EnvironmentUrl, url); + } + + [Fact] + public void RetrieveEnvironmentUrl_MultipleSessions_DuplicateFoundException() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session copy = CopySession(original); + _ = repository.Create(original); + _ = repository.Create(copy); + + // Assert. + Assert.Throws( + () => service.RetrieveEnvironmentUrl( + original.ApplicationKey, + original.SolutionId, + original.UserToken, + original.InstanceId)); + + // Restore. + repository.Delete(original); + repository.Delete(copy); + } + + [Theory] + [InlineData("Sif3DemoConsumer")] + [InlineData("Sif3DemoConsumer", "Sif3Framework2")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah", "De Blah")] + public void RetrieveEnvironmentUrl_NotExists_Failure( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + // Act. + string url = service.RetrieveEnvironmentUrl(applicationKey, solutionId, userToken, instanceId); + + // Assert. + Assert.Null(url); + } + + [Fact] + public void RetrieveEnvironmentUrl_NullApplicationKey_ArgumentNullException() + { + // Assert. + Assert.Throws(() => service.RetrieveEnvironmentUrl(null)); + } + + [Fact] + public void RetrieveQueueId_Exists_Success() + { + // Act. + string queueId = service.RetrieveQueueId( + reference.ApplicationKey, + reference.SolutionId, + reference.UserToken, + reference.InstanceId); + + // Assert. + Assert.Equal(reference.QueueId, queueId); + } + + [Fact] + public void RetrieveQueueId_MultipleSessions_DuplicateFoundException() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session copy = CopySession(original); + _ = repository.Create(original); + _ = repository.Create(copy); + + // Assert. + Assert.Throws( + () => service.RetrieveQueueId( + original.ApplicationKey, + original.SolutionId, + original.UserToken, + original.InstanceId)); + + // Restore. + repository.Delete(original); + repository.Delete(copy); + } + + [Theory] + [InlineData("Sif3DemoConsumer")] + [InlineData("Sif3DemoConsumer", "Sif3Framework2")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah", "De Blah")] + public void RetrieveQueueId_NotExists_Failure( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + // Act. + string queueId = service.RetrieveQueueId(applicationKey, solutionId, userToken, instanceId); + + // Assert. + Assert.Null(queueId); + } + + [Fact] + public void RetrieveQueueId_NullApplicationKey_ArgumentNullException() + { + // Assert. + Assert.Throws(() => service.RetrieveQueueId(null)); + } + + [Fact] + public void RetrieveSessionToken_Exists_Success() + { + // Act. + string sessionToken = service.RetrieveSessionToken( + reference.ApplicationKey, + reference.SolutionId, + reference.UserToken, + reference.InstanceId); + + // Assert. + Assert.Equal(reference.SessionToken, sessionToken); + } + + [Fact] + public void RetrieveSessionToken_MultipleSessions_DuplicateFoundException() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session copy = CopySession(original); + _ = repository.Create(original); + _ = repository.Create(copy); + + // Assert. + Assert.Throws( + () => service.RetrieveSessionToken( + original.ApplicationKey, + original.SolutionId, + original.UserToken, + original.InstanceId)); + + // Restore. + repository.Delete(original); + repository.Delete(copy); + } + + [Theory] + [InlineData("Sif3DemoConsumer")] + [InlineData("Sif3DemoConsumer", "Sif3Framework2")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah", "De Blah")] + public void RetrieveSessionToken_NotExists_Failure( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + // Act. + string sessionToken = service.RetrieveSessionToken(applicationKey, solutionId, userToken, instanceId); + + // Assert. + Assert.Null(sessionToken); + } + + [Fact] + public void RetrieveSessionToken_NullApplicationKey_ArgumentNullException() + { + // Assert. + Assert.Throws(() => service.RetrieveSessionToken(null)); + } + + [Fact] + public void RetrieveSubscriptionId_Exists_Success() + { + // Act. + string subscriptionId = service.RetrieveSubscriptionId( + reference.ApplicationKey, + reference.SolutionId, + reference.UserToken, + reference.InstanceId); + + // Assert. + Assert.Equal(reference.SubscriptionId, subscriptionId); + } + + [Fact] + public void RetrieveSubscriptionId_MultipleSessions_DuplicateFoundException() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session copy = CopySession(original); + _ = repository.Create(original); + _ = repository.Create(copy); + + // Assert. + Assert.Throws( + () => service.RetrieveSubscriptionId( + original.ApplicationKey, + original.SolutionId, + original.UserToken, + original.InstanceId)); + + // Restore. + repository.Delete(original); + repository.Delete(copy); + } + + [Theory] + [InlineData("Sif3DemoConsumer")] + [InlineData("Sif3DemoConsumer", "Sif3Framework2")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", "Blah", "De Blah")] + public void RetrieveSubscriptionId_NotExists_Failure( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + // Act. + string subscriptionId = service.RetrieveSubscriptionId(applicationKey, solutionId, userToken, instanceId); + + // Assert. + Assert.Null(subscriptionId); + } + + [Fact] + public void RetrieveSubscriptionId_NullApplicationKey_ArgumentNullException() + { + // Assert. + Assert.Throws(() => service.RetrieveSubscriptionId(null)); + } + + [Fact] + public void StoreSession_Exists_AlreadyExistsException() + { + // Arrange. + Session original = DataFactory.CreateSession(); + + // Assert. + Assert.Throws( + () => service.StoreSession( + reference.ApplicationKey, + original.SessionToken, + original.EnvironmentUrl, + reference.SolutionId, + reference.UserToken, + reference.InstanceId)); + Assert.Throws( + () => service.StoreSession( + original.ApplicationKey, + reference.SessionToken, + original.EnvironmentUrl, + original.SolutionId, + original.UserToken, + original.InstanceId)); + } + + [Fact] + public void StoreSession_NewSession_Success() + { + // Arrange. + Session original = DataFactory.CreateSession(); + + // Act. + service.StoreSession( + original.ApplicationKey, + original.SessionToken, + original.EnvironmentUrl, + original.SolutionId, + original.UserToken, + original.InstanceId); + + // Assert. + Session retrieved = repository + .Retrieve(s => + s.ApplicationKey == original.ApplicationKey && + s.EnvironmentUrl == original.EnvironmentUrl && + s.InstanceId == original.InstanceId && + s.SessionToken == original.SessionToken && + s.SolutionId == original.SolutionId && + s.UserToken == original.UserToken) + .First(); + Assert.NotNull(retrieved); + + // Restore. + repository.Delete(retrieved); + } + + [Theory] + [InlineData(null, null, null)] + [InlineData("Sif3DemoConsumer", null, null)] + [InlineData(null, "Sif3Framework", null)] + [InlineData(null, null, "http://localhost:62921/api/environments/bca76787-48ae-4532-b851-fd7099a4098b")] + [InlineData("Sif3DemoConsumer", "Sif3Framework", null)] + [InlineData("Sif3DemoConsumer", null, "http://localhost:62921/api/environments")] + [InlineData(null, "Sif3Framework", "http://localhost:62921/api/environments")] + public void StoreSession_NullParameters_ArgumentNullException( + string applicationKey, + string sessionToken, + string environmentUrl) + { + // Arrange. + Session original = DataFactory.CreateSession(); + + // Assert. + Assert.Throws( + () => service.StoreSession( + applicationKey, + sessionToken, + environmentUrl, + original.SolutionId, + original.UserToken, + original.InstanceId)); + } + + [Fact] + public void UpdateQueueId_MultipleSessions_DuplicateFoundException() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session copy = CopySession(original); + _ = repository.Create(original); + _ = repository.Create(copy); + var newQueueId = Guid.NewGuid().ToString(); + + // Assert. + Assert.Throws( + () => service.UpdateQueueId( + newQueueId, + original.ApplicationKey, + original.SolutionId, + original.UserToken, + original.InstanceId)); + + // Restore. + repository.Delete(original); + repository.Delete(copy); + } + + [Fact] + public void UpdateQueueId_NewSession_Success() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session created = repository.Create(original); + var newQueueId = Guid.NewGuid().ToString(); + + // Act. + service.UpdateQueueId( + newQueueId, + created.ApplicationKey, + created.SolutionId, + created.UserToken, + created.InstanceId); + + // Assert. + Session retrieved = repository.Retrieve(created.Id); + Assert.Equal(newQueueId, retrieved.QueueId); + + // Restore. + repository.Delete(created); + } + + [Fact] + public void UpdateQueueId_NoSession_NotFoundException() + { + // Assert. + Assert.Throws(() => service.UpdateQueueId(Guid.NewGuid().ToString(), "FakeQueueId")); + } + + [Theory] + [InlineData(null, null)] + [InlineData("bca76787-48ae-4532-b851-fd7099a4098b", null)] + [InlineData(null, "Sif3DemoConsumer")] + public void UpdateQueueId_NullApplicationKey_ArgumentNullException(string queueId, string applicationKey) + { + // Assert. + Assert.Throws(() => service.UpdateQueueId(queueId, applicationKey)); + } + + [Fact] + public void UpdateSubscriptionId_MultipleSessions_DuplicateFoundException() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session copy = CopySession(original); + _ = repository.Create(original); + _ = repository.Create(copy); + var newSubscriptionId = Guid.NewGuid().ToString(); + + // Assert. + Assert.Throws( + () => service.UpdateSubscriptionId( + newSubscriptionId, + original.ApplicationKey, + original.SolutionId, + original.UserToken, + original.InstanceId)); + + // Restore. + repository.Delete(original); + repository.Delete(copy); + } + + [Fact] + public void UpdateSubscriptionId_NewSession_Success() + { + // Arrange. + Session original = DataFactory.CreateSession(); + Session created = repository.Create(original); + var newSubscriptionId = Guid.NewGuid().ToString(); + + // Act. + service.UpdateSubscriptionId( + newSubscriptionId, + created.ApplicationKey, + created.SolutionId, + created.UserToken, + created.InstanceId); + + // Assert. + Session retrieved = repository.Retrieve(created.Id); + Assert.Equal(newSubscriptionId, retrieved.SubscriptionId); + + // Restore. + repository.Delete(created); + } + + [Fact] + public void UpdateSubscriptionId_NoSession_NotFoundException() + { + // Assert. + Assert.Throws(() => + service.UpdateSubscriptionId(Guid.NewGuid().ToString(), "FakeSubscriptionId")); + } + + [Theory] + [InlineData(null, null)] + [InlineData("bca76787-48ae-4532-b851-fd7099a4098b", null)] + [InlineData(null, "Sif3DemoConsumer")] + public void UpdateSubscriptionId_NullApplicationKey_ArgumentNullException(string newSubscriptionId, + string applicationKey) + { + // Assert. + Assert.Throws(() => service.UpdateSubscriptionId(newSubscriptionId, applicationKey)); + } + } +} \ No newline at end of file diff --git a/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SetUp/UnitTestFixture.cs b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SetUp/UnitTestFixture.cs new file mode 100644 index 00000000..e635f5cc --- /dev/null +++ b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SetUp/UnitTestFixture.cs @@ -0,0 +1,61 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Sif.Framework.Model.Sessions; +using System; +using Tardigrade.Framework.Patterns.DependencyInjection; +using Tardigrade.Framework.Persistence; + +namespace Sif.Framework.EntityFramework.Tests.SetUp +{ + /// + /// Dependency injection in XUnit project + /// + public class UnitTestFixture : IDisposable + { + private readonly IRepository repository; + + public IServiceContainer Container { get; } + + public Session Reference { get; } + + public UnitTestFixture() + { + Container = new UnitTestServiceContainer(); + + // Create a reference session for testing. + Reference = new Session + { + ApplicationKey = "Sif3DemoConsumer", + EnvironmentUrl = "http://localhost:62921/api/environments/bca76787-48ae-4532-b851-fd7099a4098b", + Id = Guid.NewGuid(), + QueueId = Guid.NewGuid().ToString(), + SessionToken = "U2lmM0RlbW9Db25zdW1lcjo6OlNpZjNGcmFtZXdvcms=", + SolutionId = "Sif3Framework", + SubscriptionId = Guid.NewGuid().ToString() + }; + + repository = Container.GetService>(); + _ = repository.Create(Reference); + } + + public void Dispose() + { + // Delete the reference user. + repository.Delete(Reference); + } + } +} \ No newline at end of file diff --git a/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SetUp/UnitTestServiceContainer.cs b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SetUp/UnitTestServiceContainer.cs new file mode 100644 index 00000000..a97676b7 --- /dev/null +++ b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/SetUp/UnitTestServiceContainer.cs @@ -0,0 +1,42 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Microsoft.Extensions.DependencyInjection; +using Sif.Framework.EntityFramework.Data; +using Sif.Framework.EntityFramework.Services.Sessions; +using Sif.Framework.Model.Sessions; +using Sif.Framework.Service.Sessions; +using System; +using System.Data.Entity; +using Tardigrade.Framework.EntityFramework; +using Tardigrade.Framework.Patterns.DependencyInjection; +using Tardigrade.Framework.Persistence; +using Tardigrade.Framework.Services; + +namespace Sif.Framework.EntityFramework.Tests.SetUp +{ + internal class UnitTestServiceContainer : MicrosoftServiceContainer + { + public override void ConfigureServices(IServiceCollection services) + { + // Inject business services. + services.AddScoped(_ => new SessionDbContext("name=SettingsDb")); + services.AddScoped, Repository>(); + services.AddScoped, ObjectService>(); + services.AddScoped(); + } + } +} \ No newline at end of file diff --git a/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/Sif.Framework.EntityFramework.Tests.csproj b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/Sif.Framework.EntityFramework.Tests.csproj index 56d43b4a..cd65a389 100644 --- a/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/Sif.Framework.EntityFramework.Tests.csproj +++ b/Code/Sif.Framework.Tests/Sif.Framework.EntityFramework.Tests/Sif.Framework.EntityFramework.Tests.csproj @@ -43,6 +43,9 @@ + + + @@ -70,10 +73,19 @@ + + {983bb129-0fcf-4800-bc80-36da09706a9c} + Sif.Framework.EntityFramework + {2b13d050-aa2c-45a6-ba26-8b2706b7e227} Sif.Framework + + {76d0f674-1662-49b6-a2c2-e5a871562628} + Sif.Framework.Shared + + \ No newline at end of file diff --git a/Code/Sif.Framework.Tests/Sif.Framework.Shared/DataFactory.cs b/Code/Sif.Framework.Tests/Sif.Framework.Shared/DataFactory.cs new file mode 100644 index 00000000..f59d87cc --- /dev/null +++ b/Code/Sif.Framework.Tests/Sif.Framework.Shared/DataFactory.cs @@ -0,0 +1,48 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Bogus; +using Sif.Framework.Model.Sessions; +using System.Collections.Generic; +using System.Globalization; + +namespace Sif.Framework.Shared +{ + public class DataFactory + { + private const char LowercaseZ = '\x7a'; + private const char Zero = '\x30'; + + private static readonly string[] SifType = {"Consumer", "Provider"}; + + private static readonly Faker FakeSessions = new Faker() + .RuleFor( + u => u.ApplicationKey, + f => $"{CultureInfo.CurrentCulture.TextInfo.ToTitleCase(f.Lorem.Word())}{f.PickRandom(SifType)}") + .RuleFor( + u => u.EnvironmentUrl, + f => $"{f.Internet.Protocol()}://{f.Internet.DomainName()}/api/environments/{f.Random.Guid()}") + .RuleFor(u => u.Id, f => f.Random.Guid()) + .RuleFor(u => u.QueueId, f => f.Random.Guid().ToString()) + .RuleFor(u => u.SessionToken, f => f.Random.String(44, Zero, LowercaseZ)) + .RuleFor(u => u.SolutionId, f => f.Lorem.Word()) + .RuleFor(u => u.SubscriptionId, f => f.Random.Guid().ToString()); + + public static Session CreateSession() => FakeSessions.Generate(); + + public static IList CreateSessions(uint count) => FakeSessions.Generate((int) count); + } +} \ No newline at end of file diff --git a/Code/Sif.Framework.Tests/Sif.Framework.Shared/Sif.Framework.Shared.csproj b/Code/Sif.Framework.Tests/Sif.Framework.Shared/Sif.Framework.Shared.csproj new file mode 100644 index 00000000..2f6b2b6e --- /dev/null +++ b/Code/Sif.Framework.Tests/Sif.Framework.Shared/Sif.Framework.Shared.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + diff --git a/Code/Sif.Framework.Tests/Sif.Framework.Tests.sln b/Code/Sif.Framework.Tests/Sif.Framework.Tests.sln index 1c64ac8e..bf79ffb9 100644 --- a/Code/Sif.Framework.Tests/Sif.Framework.Tests.sln +++ b/Code/Sif.Framework.Tests/Sif.Framework.Tests.sln @@ -9,6 +9,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sif.Framework.Tests", "Sif. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sif.Framework", "..\Sif3Framework\Sif.Framework\Sif.Framework.csproj", "{2B13D050-AA2C-45A6-BA26-8B2706B7E227}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sif.Framework.EntityFramework", "..\Sif3Framework\Sif.Framework.EntityFramework\Sif.Framework.EntityFramework.csproj", "{983BB129-0FCF-4800-BC80-36DA09706A9C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sif.Framework.Shared", "Sif.Framework.Shared\Sif.Framework.Shared.csproj", "{76D0F674-1662-49B6-A2C2-E5A871562628}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +31,14 @@ Global {2B13D050-AA2C-45A6-BA26-8B2706B7E227}.Debug|Any CPU.Build.0 = Debug|Any CPU {2B13D050-AA2C-45A6-BA26-8B2706B7E227}.Release|Any CPU.ActiveCfg = Release|Any CPU {2B13D050-AA2C-45A6-BA26-8B2706B7E227}.Release|Any CPU.Build.0 = Release|Any CPU + {983BB129-0FCF-4800-BC80-36DA09706A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {983BB129-0FCF-4800-BC80-36DA09706A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {983BB129-0FCF-4800-BC80-36DA09706A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {983BB129-0FCF-4800-BC80-36DA09706A9C}.Release|Any CPU.Build.0 = Release|Any CPU + {76D0F674-1662-49B6-A2C2-E5A871562628}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76D0F674-1662-49B6-A2C2-E5A871562628}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76D0F674-1662-49B6-A2C2-E5A871562628}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76D0F674-1662-49B6-A2C2-E5A871562628}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Code/Sif3Framework/Sif.Framework.EntityFramework/Data/SessionDbContext.cs b/Code/Sif3Framework/Sif.Framework.EntityFramework/Data/SessionDbContext.cs new file mode 100644 index 00000000..82bd228a --- /dev/null +++ b/Code/Sif3Framework/Sif.Framework.EntityFramework/Data/SessionDbContext.cs @@ -0,0 +1,40 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Sif.Framework.Model.Sessions; +using System.Data.Entity; + +namespace Sif.Framework.EntityFramework.Data +{ + /// + /// Entity Framework database context for use with session data stored in a database. + /// + public class SessionDbContext : DbContext + { + /// + /// Create an instance of this class. + /// + /// Name of the database connection or database connection string. + public SessionDbContext(string nameOrConnectionString) : base(nameOrConnectionString) + { + } + + /// + /// Sessions. + /// + public DbSet Sessions { get; set; } + } +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework.EntityFramework/Services/Sessions/SessionService.cs b/Code/Sif3Framework/Sif.Framework.EntityFramework/Services/Sessions/SessionService.cs new file mode 100644 index 00000000..45c83ba6 --- /dev/null +++ b/Code/Sif3Framework/Sif.Framework.EntityFramework/Services/Sessions/SessionService.cs @@ -0,0 +1,277 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Sif.Framework.Model.Sessions; +using Sif.Framework.Service.Sessions; +using System; +using System.Collections.Generic; +using System.Linq; +using Tardigrade.Framework.Exceptions; +using Tardigrade.Framework.Services; + +namespace Sif.Framework.EntityFramework.Services.Sessions +{ + /// + public class SessionService : ISessionService + { + private readonly IObjectService service; + + /// + /// Create an instance of this class. + /// + /// Object service associated with this facade service. + public SessionService(IObjectService service) + { + this.service = service; + } + + /// + public bool HasSession( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + if (applicationKey == null) throw new ArgumentNullException(nameof(applicationKey)); + + return service + .Retrieve(s => + s.ApplicationKey == applicationKey && + s.SolutionId == solutionId && + s.InstanceId == instanceId && + s.UserToken == userToken) + .Any(); + } + + /// + public bool HasSessionToken(string sessionToken) + { + if (sessionToken == null) throw new ArgumentNullException(nameof(sessionToken)); + + return service.Retrieve(s => s.SessionToken == sessionToken).Any(); + } + + /// + public void RemoveSession(string sessionToken) + { + if (sessionToken == null) throw new ArgumentNullException(nameof(sessionToken)); + + if (!HasSessionToken(sessionToken)) + { + throw new NotFoundException($"Session with token of {sessionToken} does not exist."); + } + + try + { + Session session = service.Retrieve(s => s.SessionToken == sessionToken).Single(); + service.Delete(session); + } + catch (InvalidOperationException e) + { + throw new DuplicateFoundException($"Multiple sessions with the token {sessionToken} found.", e); + } + } + + /// + /// Retrieve a session based upon the passed criteria parameters. + /// + /// Application key. + /// Solution ID. + /// User token. + /// Instance ID. + /// applicationKey is null. + /// Multiple session entries exist for the passed criteria parameters. + /// No session entry exists for the passed criteria parameters. + /// The matched session entry. + private Session Retrieve( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + if (applicationKey == null) throw new ArgumentNullException(nameof(applicationKey)); + + IEnumerable sessions = service + .Retrieve(s => + s.ApplicationKey == applicationKey && + s.SolutionId == solutionId && + s.InstanceId == instanceId && + s.UserToken == userToken) + .ToList(); + + if (!sessions.Any()) + { + throw new NotFoundException( + $"Session does not exist for [applicationKey:{applicationKey}|solutionId:{solutionId}|userToken:{userToken}|instanceId:{instanceId}]."); + } + + if (sessions.Count() > 1) + { + throw new DuplicateFoundException( + $"Multiple sessions found for [applicationKey:{applicationKey}|solutionId:{solutionId}|userToken:{userToken}|instanceId:{instanceId}]."); + } + + return sessions.First(); + } + + /// + /// Retrieve the session property (based upon the defined property selector) of a session entry that matches + /// the passed criteria parameters. + /// + /// Property selector. + /// Application key. + /// Solution ID. + /// User token. + /// Instance ID. + /// Value of the property for the matched session entry; null if no match found. + /// selector and/or applicationKey are null. + /// Multiple session entries exist for the passed criteria parameters. + private string RetrieveBySelector( + Func selector, + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + if (selector == null) throw new ArgumentNullException(nameof(selector)); + + if (applicationKey == null) throw new ArgumentNullException(nameof(applicationKey)); + + IEnumerable sessionValues = service + .Retrieve(s => + s.ApplicationKey == applicationKey && + s.SolutionId == solutionId && + s.InstanceId == instanceId && + s.UserToken == userToken) + .Select(selector) + .ToList(); + + if (sessionValues.Count() > 1) + { + throw new DuplicateFoundException( + $"Multiple sessions found for [applicationKey:{applicationKey}|solutionId:{solutionId}|userToken:{userToken}|instanceId:{instanceId}]."); + } + + return sessionValues.FirstOrDefault(); + } + + /// + public string RetrieveEnvironmentUrl( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + return RetrieveBySelector(s => s.EnvironmentUrl, applicationKey, solutionId, userToken, instanceId); + } + + /// + public string RetrieveQueueId( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + return RetrieveBySelector(s => s.QueueId, applicationKey, solutionId, userToken, instanceId); + } + + /// + public string RetrieveSessionToken( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + return RetrieveBySelector(s => s.SessionToken, applicationKey, solutionId, userToken, instanceId); + } + + /// + public string RetrieveSubscriptionId( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + return RetrieveBySelector(s => s.SubscriptionId, applicationKey, solutionId, userToken, instanceId); + } + + /// + public void StoreSession( + string applicationKey, + string sessionToken, + string environmentUrl, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + if (applicationKey == null) throw new ArgumentNullException(nameof(applicationKey)); + + if (sessionToken == null) throw new ArgumentNullException(nameof(sessionToken)); + + if (environmentUrl == null) throw new ArgumentNullException(nameof(environmentUrl)); + + if (HasSession(applicationKey, solutionId, userToken, instanceId)) + throw new AlreadyExistsException( + $"Session already exists for [applicationKey:{applicationKey}|solutionId:{solutionId}|userToken:{userToken}|instanceId:{instanceId}]."); + + if (HasSessionToken(sessionToken)) + throw new AlreadyExistsException($"Session already exists for session token {sessionToken}."); + + var session = new Session + { + ApplicationKey = applicationKey, + EnvironmentUrl = environmentUrl, + Id = Guid.NewGuid(), + InstanceId = instanceId, + SessionToken = sessionToken, + SolutionId = solutionId, + UserToken = userToken + }; + + _ = service.Create(session); + } + + /// + public void UpdateQueueId( + string queueId, + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + if (queueId == null) throw new ArgumentNullException(nameof(queueId)); + + Session session = Retrieve(applicationKey, solutionId, userToken, instanceId); + session.QueueId = queueId; + service.Update(session); + } + + /// + public void UpdateSubscriptionId( + string subscriptionId, + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) + { + if (subscriptionId == null) throw new ArgumentNullException(nameof(subscriptionId)); + + Session session = Retrieve(applicationKey, solutionId, userToken, instanceId); + session.SubscriptionId = subscriptionId; + service.Update(session); + } + } +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework.EntityFramework/Sif.Framework.EntityFramework.csproj b/Code/Sif3Framework/Sif.Framework.EntityFramework/Sif.Framework.EntityFramework.csproj new file mode 100644 index 00000000..8a000655 --- /dev/null +++ b/Code/Sif3Framework/Sif.Framework.EntityFramework/Sif.Framework.EntityFramework.csproj @@ -0,0 +1,26 @@ + + + + net472;net461 + true + Rafidzal Rafiq + Systemic Pty Ltd + SIF Framework library (Entity Framework Integration) + Core library of the SIF Framework based on SIF Infrastructure 3.2.1. + Copyright © Systemic Pty Ltd 2021 + Apache-2.0 + https://github.com/nsip/sif3-framework-dotnet + https://github.com/nsip/sif3-framework-dotnet + Git + SIF framework + + + + + + + + + + + diff --git a/Code/Sif3Framework/Sif.Framework.EnvironmentProvider/Properties/AssemblyInfo.cs b/Code/Sif3Framework/Sif.Framework.EnvironmentProvider/Properties/AssemblyInfo.cs index f7e1f90b..23bf268c 100644 --- a/Code/Sif3Framework/Sif.Framework.EnvironmentProvider/Properties/AssemblyInfo.cs +++ b/Code/Sif3Framework/Sif.Framework.EnvironmentProvider/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.EnvironmentProvider")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2020")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.2.1.13")] -[assembly: AssemblyFileVersion("3.2.1.13")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3Framework/Sif.Framework.Tests/Properties/AssemblyInfo.cs b/Code/Sif3Framework/Sif.Framework.Tests/Properties/AssemblyInfo.cs index e4007019..c5f88bbe 100644 --- a/Code/Sif3Framework/Sif.Framework.Tests/Properties/AssemblyInfo.cs +++ b/Code/Sif3Framework/Sif.Framework.Tests/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Test")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2020")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.2.1.13")] -[assembly: AssemblyFileVersion("3.2.1.13")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3Framework/Sif.Framework.Tests/Utils/SettingsManagerTest.cs b/Code/Sif3Framework/Sif.Framework.Tests/Utils/SettingsManagerTest.cs index 8f690488..43e10ffa 100644 --- a/Code/Sif3Framework/Sif.Framework.Tests/Utils/SettingsManagerTest.cs +++ b/Code/Sif3Framework/Sif.Framework.Tests/Utils/SettingsManagerTest.cs @@ -1,12 +1,12 @@ /* - * Copyright 2017 Systemic Pty Ltd - * + * Copyright 2021 Systemic Pty Ltd + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,20 +21,19 @@ namespace Sif.Framework.Utils { - /// /// Unit tests for SIF Framework settings. /// [TestClass] public class SettingsManagerTest { - private const string applicationKey = "Sif3DemoApp"; + private const string ApplicationKey = "Sif3DemoApp"; [TestMethod] public void TestRetrieveAppSettings() { IFrameworkSettings settings = SettingsManager.ConsumerSettings; - Assert.AreEqual(settings.ApplicationKey, applicationKey); + Assert.AreEqual(settings.ApplicationKey, ApplicationKey); Assert.AreEqual(settings.AuthenticationMethod, "Basic"); Assert.AreEqual(settings.ConsumerName, "DemoConsumer"); Assert.AreEqual(settings.DataModelNamespace, "http://www.sifassociation.org/au/datamodel/1.4"); @@ -50,32 +49,29 @@ public void TestRetrieveAppSettings() [TestMethod] public void TestSessionTokens() { - string queueId = Guid.NewGuid().ToString(); - string sessionToken = Guid.NewGuid().ToString(); - string subscriptionId = Guid.NewGuid().ToString(); + var queueId = Guid.NewGuid().ToString(); + var sessionToken = Guid.NewGuid().ToString(); ISessionService sessionService = SessionsManager.ConsumerSessionService; // Check session. - Assert.IsFalse(sessionService.HasSession(sessionToken: "NonExistantSessionToken")); - Assert.IsFalse(sessionService.HasSession(applicationKey: applicationKey)); + Assert.IsFalse(sessionService.HasSessionToken("NonExistentSessionToken")); + Assert.IsFalse(sessionService.HasSession(ApplicationKey)); // Create session. - sessionService.StoreSession(applicationKey, sessionToken, "http://www.news.com.au"); - Assert.IsTrue(sessionService.HasSession(sessionToken: sessionToken)); - Assert.IsTrue(sessionService.HasSession(applicationKey: applicationKey)); - Assert.AreEqual(sessionService.RetrieveSessionToken(applicationKey), sessionToken); + sessionService.StoreSession(ApplicationKey, sessionToken, "http://www.news.com.au"); + Assert.IsTrue(sessionService.HasSessionToken(sessionToken)); + Assert.IsTrue(sessionService.HasSession(ApplicationKey)); + Assert.AreEqual(sessionService.RetrieveSessionToken(ApplicationKey), sessionToken); // Update session with a Queue ID. - Assert.IsNull(sessionService.RetrieveQueueId(applicationKey)); - sessionService.UpdateQueueId(queueId, applicationKey); - Assert.AreEqual(queueId, sessionService.RetrieveQueueId(applicationKey)); + Assert.IsNull(sessionService.RetrieveQueueId(ApplicationKey)); + sessionService.UpdateQueueId(queueId, ApplicationKey); + Assert.AreEqual(queueId, sessionService.RetrieveQueueId(ApplicationKey)); // Delete session. sessionService.RemoveSession(sessionToken); - Assert.IsFalse(sessionService.HasSession(sessionToken: sessionToken)); - Assert.IsFalse(sessionService.HasSession(applicationKey: applicationKey)); + Assert.IsFalse(sessionService.HasSessionToken(sessionToken)); + Assert.IsFalse(sessionService.HasSession(ApplicationKey)); } - } - -} +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework/Consumers/BasicConsumer.cs b/Code/Sif3Framework/Sif.Framework/Consumers/BasicConsumer.cs index 984146e8..5ee89691 100644 --- a/Code/Sif3Framework/Sif.Framework/Consumers/BasicConsumer.cs +++ b/Code/Sif3Framework/Sif.Framework/Consumers/BasicConsumer.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ using Sif.Framework.Model.Infrastructure; using Sif.Framework.Model.Settings; using Sif.Framework.Service.Serialisation; +using Sif.Framework.Service.Sessions; using System.Collections.Generic; using System.Xml.Serialization; @@ -30,23 +31,24 @@ namespace Sif.Framework.Consumers /// Type that defines a SIF data model object. public class BasicConsumer : Consumer, string>, IBasicConsumer where T : ISifRefId { - /// - /// Consumer - /// - protected BasicConsumer(Environment environment, IFrameworkSettings settings = null) : base(environment, settings) + /// + protected BasicConsumer( + Environment environment, + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(environment, settings, sessionService) { } - /// - /// Consumer - /// + /// public BasicConsumer( string applicationKey, string instanceId = null, string userToken = null, string solutionId = null, - IFrameworkSettings settings = null) - : base(applicationKey, instanceId, userToken, solutionId, settings) + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(applicationKey, instanceId, userToken, solutionId, settings, sessionService) { } diff --git a/Code/Sif3Framework/Sif.Framework/Consumers/BasicEventConsumer.cs b/Code/Sif3Framework/Sif.Framework/Consumers/BasicEventConsumer.cs index f8c08048..072de076 100644 --- a/Code/Sif3Framework/Sif.Framework/Consumers/BasicEventConsumer.cs +++ b/Code/Sif3Framework/Sif.Framework/Consumers/BasicEventConsumer.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ using Sif.Framework.Model.DataModels; using Sif.Framework.Model.Settings; +using Sif.Framework.Service.Sessions; using System.Collections.Generic; namespace Sif.Framework.Consumers @@ -27,24 +28,24 @@ namespace Sif.Framework.Consumers /// Type that defines a SIF data model object. public abstract class BasicEventConsumer : EventConsumer, string> where T : ISifRefId { - /// - /// EventConsumer - /// - protected BasicEventConsumer(Model.Infrastructure.Environment environment, IFrameworkSettings settings = null) - : base(environment, settings) + /// + protected BasicEventConsumer( + Model.Infrastructure.Environment environment, + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(environment, settings, sessionService) { } - /// - /// EventConsumer - /// + /// protected BasicEventConsumer( string applicationKey, string instanceId = null, string userToken = null, string solutionId = null, - IFrameworkSettings settings = null) - : base(applicationKey, instanceId, userToken, solutionId, settings) + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(applicationKey, instanceId, userToken, solutionId, settings, sessionService) { } } diff --git a/Code/Sif3Framework/Sif.Framework/Consumers/Consumer.cs b/Code/Sif3Framework/Sif.Framework/Consumers/Consumer.cs index b51283ae..e5f440a4 100644 --- a/Code/Sif3Framework/Sif.Framework/Consumers/Consumer.cs +++ b/Code/Sif3Framework/Sif.Framework/Consumers/Consumer.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ using Sif.Framework.Service.Mapper; using Sif.Framework.Service.Registration; using Sif.Framework.Service.Serialisation; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Specification.Infrastructure; using System; @@ -32,6 +33,7 @@ using System.Linq; using System.Net; using System.Text; +using Environment = Sif.Framework.Model.Infrastructure.Environment; namespace Sif.Framework.Consumers { @@ -47,7 +49,7 @@ public class Consumer : IConsumer /// Accepted content type (XML or JSON) for a message payload. @@ -67,7 +69,7 @@ public class Consumer : IConsumer /// Consumer environment. /// - protected Model.Infrastructure.Environment EnvironmentTemplate => environmentTemplate; + protected Environment EnvironmentTemplate => environmentTemplate; /// /// Service for Consumer registration. @@ -84,12 +86,16 @@ public class Consumer : IConsumer /// Environment object. /// Consumer settings. If null, Consumer settings will be read from the SifFramework.config file. - protected Consumer(Model.Infrastructure.Environment environment, IFrameworkSettings settings = null) + /// Consumer session service. If null, the Consumer session will be stored in the SifFramework.config file. + protected Consumer( + Environment environment, + IFrameworkSettings settings = null, + ISessionService sessionService = null) { ConsumerSettings = settings ?? SettingsManager.ConsumerSettings; - environmentTemplate = EnvironmentUtils.MergeWithSettings(environment, ConsumerSettings); - RegistrationService = new RegistrationService(ConsumerSettings, SessionsManager.ConsumerSessionService); + RegistrationService = + new RegistrationService(ConsumerSettings, sessionService ?? SessionsManager.ConsumerSessionService); } /// @@ -100,13 +106,15 @@ protected Consumer(Model.Infrastructure.Environment environment, IFrameworkSetti /// User token. /// Solution ID. /// Consumer settings. If null, Consumer settings will be read from the SifFramework.config file. + /// Consumer session service. If null, the Consumer session will be stored in the SifFramework.config file. public Consumer( string applicationKey, string instanceId = null, string userToken = null, string solutionId = null, - IFrameworkSettings settings = null) - : this(new Model.Infrastructure.Environment(applicationKey, instanceId, userToken, solutionId), settings) + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : this(new Environment(applicationKey, instanceId, userToken, solutionId), settings, sessionService) { } @@ -199,7 +207,7 @@ public virtual string GetChangesSinceMarker( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate)) @@ -225,7 +233,7 @@ public virtual TSingle Create( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate)) @@ -262,7 +270,7 @@ public virtual MultipleCreateResponse Create( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate)) @@ -302,7 +310,7 @@ public virtual TSingle Query( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } TSingle obj = default; @@ -359,7 +367,7 @@ public virtual TMultiple Query( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate)) @@ -406,7 +414,7 @@ public virtual TMultiple QueryByExample( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate)) @@ -444,7 +452,7 @@ public virtual TMultiple QueryByServicePath( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var servicePath = new StringBuilder(); @@ -507,7 +515,7 @@ public virtual TMultiple QueryChangesSince( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } RequestParameter[] messageParameters = (requestParameters ?? (new RequestParameter[0])); @@ -565,7 +573,7 @@ public TMultiple DynamicQuery( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } RequestParameter[] messageParameters = (requestParameters ?? (new RequestParameter[0])); @@ -614,7 +622,7 @@ public virtual void Update( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate)) @@ -647,7 +655,7 @@ public virtual MultipleUpdateResponse Update( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate)) @@ -686,7 +694,7 @@ public virtual void Delete( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate)) @@ -717,7 +725,7 @@ public virtual MultipleDeleteResponse Delete( { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } var request = diff --git a/Code/Sif3Framework/Sif.Framework/Consumers/EventConsumer.cs b/Code/Sif3Framework/Sif.Framework/Consumers/EventConsumer.cs index bdbeb85a..e5e8fda7 100644 --- a/Code/Sif3Framework/Sif.Framework/Consumers/EventConsumer.cs +++ b/Code/Sif3Framework/Sif.Framework/Consumers/EventConsumer.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ using Sif.Framework.Model.Settings; using Sif.Framework.Service.Registration; using Sif.Framework.Service.Serialisation; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Specification.Infrastructure; using System; @@ -33,6 +34,7 @@ using System.Threading; using System.Threading.Tasks; using System.Xml.Serialization; +using Environment = Sif.Framework.Model.Infrastructure.Environment; namespace Sif.Framework.Consumers { @@ -48,8 +50,10 @@ public abstract class EventConsumer private readonly slf4net.ILogger log = slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private readonly ISessionService sessionService; + private CancellationTokenSource cancellationTokenSource; - private Model.Infrastructure.Environment _environment; + private Environment _environment; private Task task; /// @@ -70,7 +74,7 @@ public abstract class EventConsumer /// /// Consumer environment. /// - protected Model.Infrastructure.Environment Environment + protected Environment Environment { get => _environment; private set => _environment = value; @@ -101,12 +105,16 @@ protected Model.Infrastructure.Environment Environment /// /// Environment object. /// Consumer settings. If null, Consumer settings will be read from the SifFramework.config file. - protected EventConsumer(Model.Infrastructure.Environment environment, IFrameworkSettings settings = null) + /// Consumer session service. If null, the Consumer session will be stored in the SifFramework.config file. + protected EventConsumer( + Environment environment, + IFrameworkSettings settings = null, + ISessionService sessionService = null) { ConsumerSettings = settings ?? SettingsManager.ConsumerSettings; - + this.sessionService = sessionService ?? SessionsManager.ConsumerSessionService; Environment = EnvironmentUtils.MergeWithSettings(environment, ConsumerSettings); - RegistrationService = new RegistrationService(ConsumerSettings, SessionsManager.ConsumerSessionService); + RegistrationService = new RegistrationService(ConsumerSettings, this.sessionService); } /// @@ -117,13 +125,15 @@ protected EventConsumer(Model.Infrastructure.Environment environment, IFramework /// User token. /// Solution ID. /// Consumer settings. If null, Consumer settings will be read from the SifFramework.config file. + /// Consumer session service. If null, the Consumer session will be stored in the SifFramework.config file. protected EventConsumer( string applicationKey, string instanceId = null, string userToken = null, string solutionId = null, - IFrameworkSettings settings = null) - : this(new Model.Infrastructure.Environment(applicationKey, instanceId, userToken, solutionId), settings) + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : this(new Environment(applicationKey, instanceId, userToken, solutionId), settings, sessionService) { } @@ -188,7 +198,11 @@ protected virtual TMultiple DeserialiseMultiple(string payload) try { var xmlRootAttribute = new XmlRootAttribute(TypeName + "s") - { Namespace = ConsumerSettings.DataModelNamespace, IsNullable = false }; + { + Namespace = ConsumerSettings.DataModelNamespace, + IsNullable = false + }; + obj = SerialiserFactory.GetSerialiser(Accept, xmlRootAttribute).Deserialise(payload); } catch (Exception e) @@ -473,7 +487,7 @@ public void Start(string zoneId = null, string contextId = null) RegistrationService.Register(ref _environment); // Retrieve the Subscription identifier (if exist). - string subscriptionId = SessionsManager.ConsumerSessionService.RetrieveSubscriptionId( + string subscriptionId = sessionService.RetrieveSubscriptionId( Environment.ApplicationInfo.ApplicationKey, Environment.SolutionId, Environment.UserToken, @@ -504,14 +518,14 @@ public void Start(string zoneId = null, string contextId = null) Subscription = CreateSubscription(subscription); // Store Queue and Subscription identifiers. - SessionsManager.ConsumerSessionService.UpdateQueueId( + sessionService.UpdateQueueId( Queue.id, Environment.ApplicationInfo.ApplicationKey, Environment.SolutionId, Environment.UserToken, Environment.InstanceId); - SessionsManager.ConsumerSessionService.UpdateSubscriptionId( + sessionService.UpdateSubscriptionId( Subscription.id, Environment.ApplicationInfo.ApplicationKey, Environment.SolutionId, @@ -523,7 +537,7 @@ public void Start(string zoneId = null, string contextId = null) { try { - string queueId = SessionsManager.ConsumerSessionService.RetrieveQueueId( + string queueId = sessionService.RetrieveQueueId( Environment.ApplicationInfo.ApplicationKey, Environment.SolutionId, Environment.UserToken, diff --git a/Code/Sif3Framework/Sif.Framework/Consumers/FunctionalServiceConsumer.cs b/Code/Sif3Framework/Sif.Framework/Consumers/FunctionalServiceConsumer.cs index b9bce5b7..f14ad916 100644 --- a/Code/Sif3Framework/Sif.Framework/Consumers/FunctionalServiceConsumer.cs +++ b/Code/Sif3Framework/Sif.Framework/Consumers/FunctionalServiceConsumer.cs @@ -1,13 +1,13 @@ /* * Crown Copyright © Department for Education (UK) 2016 - * Copyright 2020 Systemic Pty Ltd - * + * Copyright 2021 Systemic Pty Ltd + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,6 +21,7 @@ using Sif.Framework.Service.Mapper; using Sif.Framework.Service.Registration; using Sif.Framework.Service.Serialisation; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Specification.Infrastructure; using System; @@ -32,16 +33,17 @@ namespace Sif.Framework.Consumers { - /// /// The base class for all Functional Service consumers /// public class FunctionalServiceConsumer { - private static readonly slf4net.ILogger log = slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly slf4net.ILogger Log = + slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private readonly RegistrationService registrationService; private Environment environmentTemplate; - private RegistrationService registrationService; /// /// Application settings associated with the Consumer. @@ -51,30 +53,28 @@ public class FunctionalServiceConsumer /// /// Consumer environment template /// - protected Environment EnvironmentTemplate - { - get { return environmentTemplate; } - } + protected Environment EnvironmentTemplate => environmentTemplate; /// /// Service for Consumer registration. /// - protected IRegistrationService RegistrationService - { - get { return registrationService; } - } + protected IRegistrationService RegistrationService => registrationService; /// /// Create a Consumer instance based upon the Environment passed. /// /// Environment object. /// Consumer settings. If null, Consumer settings will be read from the SifFramework.config file. - public FunctionalServiceConsumer(Environment environment, IFrameworkSettings settings = null) + /// Consumer session service. If null, the Consumer session will be stored in the SifFramework.config file. + protected FunctionalServiceConsumer( + Environment environment, + IFrameworkSettings settings = null, + ISessionService sessionService = null) { ConsumerSettings = settings ?? SettingsManager.ConsumerSettings; - environmentTemplate = EnvironmentUtils.MergeWithSettings(environment, ConsumerSettings); - registrationService = new RegistrationService(ConsumerSettings, SessionsManager.ConsumerSessionService); + registrationService = + new RegistrationService(ConsumerSettings, sessionService ?? SessionsManager.ConsumerSessionService); } /// @@ -85,25 +85,28 @@ public FunctionalServiceConsumer(Environment environment, IFrameworkSettings set /// User token. /// Solution ID. /// Consumer settings. If null, Consumer settings will be read from the SifFramework.config file. + /// Consumer session service. If null, the Consumer session will be stored in the SifFramework.config file. public FunctionalServiceConsumer( string applicationKey, string instanceId = null, string userToken = null, string solutionId = null, - IFrameworkSettings settings = null) - : this(new Environment(applicationKey, instanceId, userToken, solutionId), settings) + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : this(new Environment(applicationKey, instanceId, userToken, solutionId), settings, sessionService) { } /// - /// Convenience method to check if the Consumer is registered, throwing a standardised invalid operation exception if not. + /// Convenience method to check if the Consumer is registered, throwing a standardised invalid operation + /// exception if not. /// /// - protected virtual void checkRegistered() + protected virtual void CheckRegistered() { if (!RegistrationService.Registered) { - throw new InvalidOperationException("Consumer has not registered."); + throw new InvalidOperationException("Consumer has not been registered."); } } @@ -112,10 +115,11 @@ protected virtual void checkRegistered() /// /// Payload of a single entity. /// XML string representation of the single entity. - public virtual string SerialiseSingle(DB item) + public virtual string SerialiseSingle(TSource item) { - UI data = MapperFactory.CreateInstance(item); - return SerialiserFactory.GetXmlSerialiser().Serialise(data); + TDestination data = MapperFactory.CreateInstance(item); + + return SerialiserFactory.GetXmlSerialiser().Serialise(data); } /// @@ -126,10 +130,8 @@ public virtual string SerialiseSingle(DB item) public virtual string SerialiseMultiple(IEnumerable items) { List data = MapperFactory.CreateInstances(items).ToList(); - jobCollectionType collection = new jobCollectionType() - { - job = data.ToArray() - }; + var collection = new jobCollectionType() { job = data.ToArray() }; + return SerialiserFactory.GetXmlSerialiser().Serialise(collection); } @@ -137,11 +139,12 @@ public virtual string SerialiseMultiple(IEnumerable items) /// Deserialise a single entity. /// /// Payload of a single entity. - /// The deserialised single entity. - public virtual DB DeserialiseSingle(string payload) + /// The deserialized single entity. + public virtual TDestination DeserialiseSingle(string payload) { - UI data = SerialiserFactory.GetXmlSerialiser().Deserialise(payload); - return MapperFactory.CreateInstance(data); + TSource data = SerialiserFactory.GetXmlSerialiser().Deserialise(payload); + + return MapperFactory.CreateInstance(data); } /// @@ -149,10 +152,11 @@ public virtual DB DeserialiseSingle(string payload) /// /// Payload of multiple jobs. /// Entity representing multiple jobs. - public virtual List DeserialiseMultiple(string payload) + public virtual List DeserialiseMultiple(string payload) { - List data = SerialiserFactory.GetXmlSerialiser>().Deserialise(payload); - return MapperFactory.CreateInstances(data).ToList(); + List data = SerialiserFactory.GetXmlSerialiser>().Deserialise(payload); + + return MapperFactory.CreateInstances(data).ToList(); } /// @@ -177,7 +181,7 @@ public void Unregister(bool? deleteOnUnregister = null) /// /// The jon name to build a URL for. /// A string in the form {http/https}://{domain:port}/{servicesConnectorPath}/{jobName}s. - protected virtual string GetURLPrefix(string jobName) + protected virtual string GetUrlPrefix(string jobName) { return EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate, ServiceType.FUNCTIONAL) + "/" + jobName + "s"; } @@ -191,11 +195,9 @@ protected virtual string GetURLPrefix(string jobName) /// The created Job object public virtual Job Create(Job job, string zoneId = null, string contextId = null) { - checkRegistered(); - - checkJob(job, RightType.CREATE, zoneId); - - string url = GetURLPrefix(job.Name) + "/" + job.Name + HttpUtils.MatrixParameters(zoneId, contextId); + CheckRegistered(); + CheckJob(job, RightType.CREATE, zoneId); + string url = GetUrlPrefix(job.Name) + "/" + job.Name + HttpUtils.MatrixParameters(zoneId, contextId); string body = SerialiseSingle(job); string xml = HttpUtils.PostRequest( url, @@ -203,8 +205,8 @@ public virtual Job Create(Job job, string zoneId = null, string contextId = null body, ConsumerSettings.CompressPayload, ServiceType.FUNCTIONAL); - if (log.IsDebugEnabled) log.Debug("XML from POST request ..."); - if (log.IsDebugEnabled) log.Debug(xml); + + if (Log.IsDebugEnabled) Log.Debug($"XML from POST request ...\n{xml}"); return DeserialiseSingle(xml); } @@ -218,11 +220,9 @@ public virtual Job Create(Job job, string zoneId = null, string contextId = null /// A MultipleCreateResponse object public virtual MultipleCreateResponse Create(List jobs, string zoneId = null, string contextId = null) { - checkRegistered(); - - string jobName = checkJobs(jobs, RightType.CREATE, zoneId); - - string url = GetURLPrefix(jobName) + HttpUtils.MatrixParameters(zoneId, contextId); + CheckRegistered(); + string jobName = CheckJobs(jobs, RightType.CREATE, zoneId); + string url = GetUrlPrefix(jobName) + HttpUtils.MatrixParameters(zoneId, contextId); string body = SerialiseMultiple(jobs); string xml = HttpUtils.PostRequest( url, @@ -230,27 +230,36 @@ public virtual MultipleCreateResponse Create(List jobs, string zoneId = nul body, ConsumerSettings.CompressPayload, ServiceType.FUNCTIONAL); - if (log.IsDebugEnabled) log.Debug("XML from POST request ..."); - if (log.IsDebugEnabled) log.Debug(xml); - createResponseType createResponseType = SerialiserFactory.GetXmlSerialiser().Deserialise(xml); - MultipleCreateResponse createResponse = MapperFactory.CreateInstance(createResponseType); + + if (Log.IsDebugEnabled) Log.Debug($"XML from POST request ...\n{xml}"); + + createResponseType createResponseType = + SerialiserFactory.GetXmlSerialiser().Deserialise(xml); + MultipleCreateResponse createResponse = + MapperFactory.CreateInstance(createResponseType); return createResponse; } /// - /// Convenience method that processes a MultipleCreateResponse message and fetches all successfully created jobs. It does this by issuing multiple individual query requests for any create status codes that start with a "2" (OK, Created, etc.). + /// Convenience method that processes a MultipleCreateResponse message and fetches all successfully created + /// jobs. It does this by issuing multiple individual query requests for any create status codes that start + /// with a "2" (OK, Created, etc.). /// - /// A MutilpleCreateResponse object to parse + /// A MultipleCreateResponse object to parse /// The job name (singular) that the MultipleCreateResponse refers to /// The zone in which to fetch the Jobs /// The context in which to fetch the Jobs /// The created Job objects - public virtual IList GetCreated(MultipleCreateResponse creates, string jobName, string zoneId = null, string contextId = null) + public virtual IList GetCreated( + MultipleCreateResponse creates, + string jobName, + string zoneId = null, + string contextId = null) { - if(creates == null) + if (creates == null) { - throw new ArgumentNullException("creates"); + throw new ArgumentNullException(nameof(creates)); } IList fetched = new List(); @@ -262,7 +271,7 @@ where s.StatusCode.StartsWith("2") Name = jobName }).ToList(); - foreach(Job job in toFetch) + foreach (Job job in toFetch) { fetched.Add(Query(job, zoneId, contextId)); } @@ -279,20 +288,20 @@ where s.StatusCode.StartsWith("2") /// The Job object public virtual Job Query(Job job, string zoneId = null, string contextId = null) { - checkRegistered(); - - checkJob(job, RightType.QUERY, zoneId); + CheckRegistered(); + CheckJob(job, RightType.QUERY, zoneId); try { - string url = GetURLPrefix(job.Name) + "/" + job.Id + HttpUtils.MatrixParameters(zoneId, contextId); + string url = GetUrlPrefix(job.Name) + "/" + job.Id + HttpUtils.MatrixParameters(zoneId, contextId); string xml = HttpUtils.GetRequest( url, RegistrationService.AuthorisationToken, ConsumerSettings.CompressPayload, ServiceType.FUNCTIONAL); - if (log.IsDebugEnabled) log.Debug("XML from GET request ..."); - if (log.IsDebugEnabled) log.Debug(xml); + + if (Log.IsDebugEnabled) Log.Debug($"XML from GET request ...\n{xml}"); + return DeserialiseSingle(xml); } catch (WebException ex) @@ -300,6 +309,7 @@ public virtual Job Query(Job job, string zoneId = null, string contextId = null) if (WebExceptionStatus.ProtocolError.Equals(ex.Status) && ex.Response != null) { HttpStatusCode statusCode = ((HttpWebResponse)ex.Response).StatusCode; + if (!HttpStatusCode.NotFound.Equals(statusCode)) { throw; @@ -310,10 +320,6 @@ public virtual Job Query(Job job, string zoneId = null, string contextId = null) throw; } } - catch (Exception) - { - throw; - } return null; } @@ -327,13 +333,16 @@ public virtual Job Query(Job job, string zoneId = null, string contextId = null) /// The zone in which to operate /// The context in which to operate /// A page of Job objects - public virtual List Query(string jobName, uint? navigationPage = null, uint? navigationPageSize = null, string zoneId = null, string contextId = null) + public virtual List Query( + string jobName, + uint? navigationPage = null, + uint? navigationPageSize = null, + string zoneId = null, + string contextId = null) { - checkRegistered(); - - checkJob(new Job(jobName), RightType.QUERY, zoneId, true); - - string url = GetURLPrefix(jobName) + HttpUtils.MatrixParameters(zoneId, contextId); + CheckRegistered(); + CheckJob(new Job(jobName), RightType.QUERY, zoneId, true); + string url = GetUrlPrefix(jobName) + HttpUtils.MatrixParameters(zoneId, contextId); string xml; if (navigationPage.HasValue && navigationPageSize.HasValue) @@ -367,13 +376,16 @@ public virtual List Query(string jobName, uint? navigationPage = null, uint /// The zone in which to operate /// The context in which to operate /// A page of Job objects - public virtual List QueryByExample(Job job, uint? navigationPage = null, uint? navigationPageSize = null, string zoneId = null, string contextId = null) + public virtual List QueryByExample( + Job job, + uint? navigationPage = null, + uint? navigationPageSize = null, + string zoneId = null, + string contextId = null) { - checkRegistered(); - - checkJob(job, RightType.QUERY, zoneId); - - string url = GetURLPrefix(job.Name) + HttpUtils.MatrixParameters(zoneId, contextId); + CheckRegistered(); + CheckJob(job, RightType.QUERY, zoneId); + string url = GetUrlPrefix(job.Name) + HttpUtils.MatrixParameters(zoneId, contextId); string body = SerialiseSingle(job); // TODO: Update PostRequest to accept paging parameters. string xml = HttpUtils.PostRequest( @@ -383,39 +395,38 @@ public virtual List QueryByExample(Job job, uint? navigationPage = null, ui ConsumerSettings.CompressPayload, ServiceType.FUNCTIONAL, "GET"); - if (log.IsDebugEnabled) log.Debug("XML from POST (Query by Example) request ..."); - if (log.IsDebugEnabled) log.Debug(xml); + + if (Log.IsDebugEnabled) Log.Debug($"XML from POST (Query by Example) request ...\n{xml}"); return DeserialiseMultiple(xml); } - /// - /// Update single job object is not supported for Functional Services. Throws a HttpResponseException with Forbidden status code. + /// Update single job object is not supported for Functional Services. Throws a HttpResponseException with + /// Forbidden status code. /// /// Job object to update /// The zone in which to update the Job /// The context in which to update the Job public virtual void Update(Job job, string zoneId = null, string contextId = null) { - checkRegistered(); - - checkJob(job, RightType.UPDATE, zoneId); + CheckRegistered(); + CheckJob(job, RightType.UPDATE, zoneId); throw new HttpResponseException(HttpStatusCode.Forbidden); } /// - /// Update multiple job objects is not supported for Functional Services. Throws a HttpResponseException with Forbidden status code. + /// Update multiple job objects is not supported for Functional Services. Throws a HttpResponseException with + /// Forbidden status code. /// /// Job objects to update /// The zone in which to update the Jobs /// The context in which to update the Jobs public virtual MultipleUpdateResponse Update(List jobs, string zoneId = null, string contextId = null) { - checkRegistered(); - - checkJobs(jobs, RightType.UPDATE, zoneId); + CheckRegistered(); + CheckJobs(jobs, RightType.UPDATE, zoneId); throw new HttpResponseException(HttpStatusCode.Forbidden); } @@ -428,42 +439,38 @@ public virtual MultipleUpdateResponse Update(List jobs, string zoneId = nul /// The context in which to perform the request. public virtual void Delete(Job job, string zoneId = null, string contextId = null) { - checkRegistered(); - - checkJob(job, RightType.DELETE, zoneId); - - string url = GetURLPrefix(job.Name) + "/" + job.Id + HttpUtils.MatrixParameters(zoneId, contextId); + CheckRegistered(); + CheckJob(job, RightType.DELETE, zoneId); + string url = GetUrlPrefix(job.Name) + "/" + job.Id + HttpUtils.MatrixParameters(zoneId, contextId); string xml = HttpUtils.DeleteRequest( url, RegistrationService.AuthorisationToken, ConsumerSettings.CompressPayload, ServiceType.FUNCTIONAL); - if (log.IsDebugEnabled) log.Debug("XML from DELETE request ..."); - if (log.IsDebugEnabled) log.Debug(xml); + + if (Log.IsDebugEnabled) Log.Debug($"XML from DELETE request ...\n{xml}"); } /// /// Delete a series of Job objects /// - /// The job objtect templates of the Jobs to delete, each must have name and id populated. tHe name of all jobs must be the same. + /// The job object templates of the Jobs to delete, each must have name and id populated. tHe name of all jobs must be the same. /// The zone in which to perform the request. /// The context in which to perform the request. /// A response public virtual MultipleDeleteResponse Delete(List jobs, string zoneId = null, string contextId = null) { - checkRegistered(); - - string jobName = checkJobs(jobs, RightType.DELETE, zoneId); - - List deleteIds = new List(); + CheckRegistered(); + string jobName = CheckJobs(jobs, RightType.DELETE, zoneId); + var deleteIds = new List(); foreach (Job job in jobs) { deleteIds.Add(new deleteIdType { id = job.Id.ToString() }); } - deleteRequestType request = new deleteRequestType { deletes = deleteIds.ToArray() }; - string url = GetURLPrefix(jobName) + HttpUtils.MatrixParameters(zoneId, contextId); + var request = new deleteRequestType { deletes = deleteIds.ToArray() }; + string url = GetUrlPrefix(jobName) + HttpUtils.MatrixParameters(zoneId, contextId); string body = SerialiserFactory.GetXmlSerialiser().Serialise(request); string xml = HttpUtils.PutRequest( url, @@ -472,10 +479,13 @@ public virtual MultipleDeleteResponse Delete(List jobs, string zoneId = nul ConsumerSettings.CompressPayload, ServiceType.FUNCTIONAL, "DELETE"); - if (log.IsDebugEnabled) log.Debug("XML from PUT (DELETE) request ..."); - if (log.IsDebugEnabled) log.Debug(xml); - deleteResponseType updateResponseType = SerialiserFactory.GetXmlSerialiser().Deserialise(xml); - MultipleDeleteResponse updateResponse = MapperFactory.CreateInstance(updateResponseType); + + if (Log.IsDebugEnabled) Log.Debug($"XML from PUT (DELETE) request ...\n{xml}"); + + deleteResponseType updateResponseType = + SerialiserFactory.GetXmlSerialiser().Deserialise(xml); + MultipleDeleteResponse updateResponse = + MapperFactory.CreateInstance(updateResponseType); return updateResponse; } @@ -491,15 +501,20 @@ public virtual MultipleDeleteResponse Delete(List jobs, string zoneId = nul /// The mime type of the data to be sent /// The expected mime type of the result /// A string, possibly containing a serialized object, returned from the functional service - public virtual string CreateToPhase(Job job, string phaseName, string body = null, string zoneId = null, string contextId = null, string contentTypeOverride = null, string acceptOverride = null) + public virtual string CreateToPhase( + Job job, + string phaseName, + string body = null, + string zoneId = null, + string contextId = null, + string contentTypeOverride = null, + string acceptOverride = null) { - checkRegistered(); - - checkJob(job, zoneId); - - string response = null; - string url = GetURLPrefix(job.Name) + "/" + job.Id + "/" + phaseName + HttpUtils.MatrixParameters(zoneId, contextId); - response = HttpUtils.PostRequest( + CheckRegistered(); + CheckJob(job, zoneId); + string url = GetUrlPrefix(job.Name) + "/" + job.Id + "/" + phaseName + + HttpUtils.MatrixParameters(zoneId, contextId); + string response = HttpUtils.PostRequest( url, RegistrationService.AuthorisationToken, body, @@ -507,8 +522,9 @@ public virtual string CreateToPhase(Job job, string phaseName, string body = nul ServiceType.FUNCTIONAL, contentTypeOverride: contentTypeOverride, acceptOverride: acceptOverride); - if (log.IsDebugEnabled) log.Debug("String from CREATE request to phase ..."); - if (log.IsDebugEnabled) log.Debug(response); + + if (Log.IsDebugEnabled) Log.Debug($"String from CREATE request to phase ...\n{response}"); + return response; } @@ -523,15 +539,20 @@ public virtual string CreateToPhase(Job job, string phaseName, string body = nul /// The mime type of the data to be sent /// The expected mime type of the result /// A string, possibly containing a serialized object, returned from the functional service - public virtual string RetrieveToPhase(Job job, string phaseName, string body = null, string zoneId = null, string contextId = null, string contentTypeOverride = null, string acceptOverride = null) + public virtual string RetrieveToPhase( + Job job, + string phaseName, + string body = null, + string zoneId = null, + string contextId = null, + string contentTypeOverride = null, + string acceptOverride = null) { - checkRegistered(); - - checkJob(job, zoneId); - - string response = null; - string url = GetURLPrefix(job.Name) + "/" + job.Id + "/" + phaseName + HttpUtils.MatrixParameters(zoneId, contextId); - response = HttpUtils.PostRequest( + CheckRegistered(); + CheckJob(job, zoneId); + string url = GetUrlPrefix(job.Name) + "/" + job.Id + "/" + phaseName + + HttpUtils.MatrixParameters(zoneId, contextId); + string response = HttpUtils.PostRequest( url, RegistrationService.AuthorisationToken, body, @@ -539,8 +560,9 @@ public virtual string RetrieveToPhase(Job job, string phaseName, string body = n ServiceType.FUNCTIONAL, "GET", contentTypeOverride, acceptOverride); - if (log.IsDebugEnabled) log.Debug("String from GET request to phase ..."); - if (log.IsDebugEnabled) log.Debug(response); + + if (Log.IsDebugEnabled) Log.Debug($"String from GET request to phase ...\n{response}"); + return response; } @@ -555,15 +577,20 @@ public virtual string RetrieveToPhase(Job job, string phaseName, string body = n /// The mime type of the data to be sent /// The expected mime type of the result /// A string, possibly containing a serialized object, returned from the functional service - public virtual string UpdateToPhase(Job job, string phaseName, string body, string zoneId = null, string contextId = null, string contentTypeOverride = null, string acceptOverride = null) + public virtual string UpdateToPhase( + Job job, + string phaseName, + string body, + string zoneId = null, + string contextId = null, + string contentTypeOverride = null, + string acceptOverride = null) { - checkRegistered(); - - checkJob(job, zoneId); - - string response = null; - string url = GetURLPrefix(job.Name) + "/" + job.Id + "/" + phaseName + HttpUtils.MatrixParameters(zoneId, contextId); - response = HttpUtils.PutRequest( + CheckRegistered(); + CheckJob(job, zoneId); + string url = GetUrlPrefix(job.Name) + "/" + job.Id + "/" + phaseName + + HttpUtils.MatrixParameters(zoneId, contextId); + string response = HttpUtils.PutRequest( url, RegistrationService.AuthorisationToken, body, @@ -571,8 +598,9 @@ public virtual string UpdateToPhase(Job job, string phaseName, string body, stri ServiceType.FUNCTIONAL, contentTypeOverride: contentTypeOverride, acceptOverride: acceptOverride); - if (log.IsDebugEnabled) log.Debug("String from PUT request to phase ..."); - if (log.IsDebugEnabled) log.Debug(response); + + if (Log.IsDebugEnabled) Log.Debug($"String from PUT request to phase ...{response}"); + return response; } @@ -587,15 +615,20 @@ public virtual string UpdateToPhase(Job job, string phaseName, string body, stri /// The mime type of the data to be sent /// The expected mime type of the result /// A string, possibly containing a serialized object, returned from the functional service - public virtual string DeleteToPhase(Job job, string phaseName, string body, string zoneId = null, string contextId = null, string contentTypeOverride = null, string acceptOverride = null) + public virtual string DeleteToPhase( + Job job, + string phaseName, + string body, + string zoneId = null, + string contextId = null, + string contentTypeOverride = null, + string acceptOverride = null) { - checkRegistered(); - - checkJob(job, zoneId); - - string response = null; - string url = GetURLPrefix(job.Name) + "/" + job.Id + "/" + phaseName + HttpUtils.MatrixParameters(zoneId, contextId); - response = HttpUtils.DeleteRequest( + CheckRegistered(); + CheckJob(job, zoneId); + string url = GetUrlPrefix(job.Name) + "/" + job.Id + "/" + phaseName + + HttpUtils.MatrixParameters(zoneId, contextId); + string response = HttpUtils.DeleteRequest( url, RegistrationService.AuthorisationToken, body, @@ -603,8 +636,9 @@ public virtual string DeleteToPhase(Job job, string phaseName, string body, stri ServiceType.FUNCTIONAL, contentTypeOverride, acceptOverride); - if (log.IsDebugEnabled) log.Debug("String from DELETE request to phase ..."); - if (log.IsDebugEnabled) log.Debug(response); + + if (Log.IsDebugEnabled) Log.Debug($"String from DELETE request to phase ...\n{response}"); + return response; } @@ -617,13 +651,17 @@ public virtual string DeleteToPhase(Job job, string phaseName, string body, stri /// The zone in which to perform the request. /// The context in which to perform the request. /// The current state of the phase. - public virtual PhaseState CreateToState(Job job, string phaseName, PhaseState item, string zoneId = null, string contextId = null) + public virtual PhaseState CreateToState( + Job job, + string phaseName, + PhaseState item, + string zoneId = null, + string contextId = null) { - checkRegistered(); - - checkJob(job, zoneId); - - string url = GetURLPrefix(job.Name) + "/" + job.Id + "/" + phaseName + "/states/state" + HttpUtils.MatrixParameters(zoneId, contextId); + CheckRegistered(); + CheckJob(job, zoneId); + string url = GetUrlPrefix(job.Name) + "/" + job.Id + "/" + phaseName + "/states/state" + + HttpUtils.MatrixParameters(zoneId, contextId); string body = SerialiseSingle(item); string xml = HttpUtils.PostRequest( url, @@ -631,12 +669,13 @@ public virtual PhaseState CreateToState(Job job, string phaseName, PhaseState it body, ConsumerSettings.CompressPayload, ServiceType.FUNCTIONAL); - if (log.IsDebugEnabled) log.Debug("Guid from CREATE request to state on phase ..."); - if (log.IsDebugEnabled) log.Debug(xml); + + if (Log.IsDebugEnabled) Log.Debug($"Guid from CREATE request to state on phase ...\n{xml}"); + return DeserialiseSingle(xml); } - private Model.Infrastructure.Service checkJob(Job job, string zoneId = null) + private Model.Infrastructure.Service CheckJob(Job job, string zoneId = null) { if (job == null) { @@ -647,33 +686,38 @@ private Model.Infrastructure.Service checkJob(Job job, string zoneId = null) { throw new ArgumentException("Job name must be specified."); } - - Model.Infrastructure.Service service = ZoneUtils.GetService(EnvironmentUtils.GetTargetZone(registrationService.CurrentEnvironment, zoneId), job.Name + "s", ServiceType.FUNCTIONAL); + + Model.Infrastructure.Service service = ZoneUtils.GetService( + EnvironmentUtils.GetTargetZone(registrationService.CurrentEnvironment, zoneId), + job.Name + "s", + ServiceType.FUNCTIONAL); if (service == null) { - throw new ArgumentException("A FUNCTIONAL service with the name " + job.Name + "s cannot be found in the current environment"); + throw new ArgumentException( + $"A FUNCTIONAL service with the name {job.Name}s cannot be found in the current environment"); } return service; } - private void checkJob(Job job, RightType right, string zoneId = null, Boolean ignoreId= false) + private void CheckJob(Job job, RightType right, string zoneId = null, bool ignoreId = false) { - Model.Infrastructure.Service service = checkJob(job, zoneId); + Model.Infrastructure.Service service = CheckJob(job, zoneId); - if(!ignoreId && !right.Equals(RightType.CREATE) && job.Id == null) + if (!ignoreId && !right.Equals(RightType.CREATE) && job.Id == null) { throw new ArgumentException("Job must have an Id for any non-creation operation"); } - - if(service.Rights[right.ToString()].Value.Equals(RightValue.REJECTED.ToString())) + + if (service.Rights[right.ToString()].Value.Equals(RightValue.REJECTED.ToString())) { - throw new ArgumentException("The attempted operation is not permitted in the ACL of the current environment"); + throw new ArgumentException( + "The attempted operation is not permitted in the ACL of the current environment"); } } - private string checkJobs(IList jobs, RightType right, string zoneId = null) + private string CheckJobs(IList jobs, RightType right, string zoneId = null) { if (jobs == null || jobs.Count == 0) { @@ -681,23 +725,22 @@ private string checkJobs(IList jobs, RightType right, string zoneId = null) } string name = null; + foreach (Job job in jobs) { - checkJob(job, right, zoneId); + CheckJob(job, right, zoneId); if (StringUtils.IsEmpty(name)) { name = job.Name; } - if (!name.Equals(job.Name)) + if (name == null || !name.Equals(job.Name)) { throw new ArgumentException("All job objects must have the same name"); } } return name; } - } - -} +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework/Consumers/IConsumer.cs b/Code/Sif3Framework/Sif.Framework/Consumers/IConsumer.cs index b6e96f34..77550a2b 100644 --- a/Code/Sif3Framework/Sif.Framework/Consumers/IConsumer.cs +++ b/Code/Sif3Framework/Sif.Framework/Consumers/IConsumer.cs @@ -1,5 +1,5 @@ /* - * Copyright 2018 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ namespace Sif.Framework.Consumers /// Type that defines a single object entity. /// Type that defines a multiple objects entity. /// Primary key type of the SIF data model object. - public interface IConsumer + public interface IConsumer { /// /// This method must be called before any other. diff --git a/Code/Sif3Framework/Sif.Framework/Controllers/EnvironmentsController.cs b/Code/Sif3Framework/Sif.Framework/Controllers/EnvironmentsController.cs index e0cc9181..f4033a40 100644 --- a/Code/Sif3Framework/Sif.Framework/Controllers/EnvironmentsController.cs +++ b/Code/Sif3Framework/Sif.Framework/Controllers/EnvironmentsController.cs @@ -1,12 +1,12 @@ /* - * Copyright 2017 Systemic Pty Ltd - * + * Copyright 2021 Systemic Pty Ltd + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,7 +14,6 @@ * limitations under the License. */ -using Sif.Framework.Model.Exceptions; using Sif.Framework.Service.Infrastructure; using Sif.Framework.Utils; using Sif.Framework.WebApi.ModelBinders; @@ -24,34 +23,33 @@ using System.Net; using System.Net.Http; using System.Web.Http; +using Tardigrade.Framework.Exceptions; using Environment = Sif.Framework.Model.Infrastructure.Environment; namespace Sif.Framework.Controllers { - /// /// This class defines a Controller for the Environment object. - /// + /// /// Valid single operations: POST, GET, DELETE. /// Valid multiple operations: none. /// public abstract class EnvironmentsController : SifController { - /// /// Default value for the authentication method. /// - protected static readonly string defaultAuthenticationMethod = "Basic"; + protected static readonly string DefaultAuthenticationMethod = "Basic"; /// /// Default value for the Consumer name. /// - protected static readonly string defaultConsumerName = "Sif3FrameworkConsumer"; + protected static readonly string DefaultConsumerName = "Sif3FrameworkConsumer"; /// /// Default value for the supported infrastructure version. /// - protected static readonly string defaultSupportedInfrastructureVersion = "3.0.1"; + protected static readonly string DefaultSupportedInfrastructureVersion = "3.0.1"; /// /// Create an Environment, using default values where applicable. @@ -65,32 +63,27 @@ public abstract class EnvironmentsController : SifControllerTransport. /// Product name. /// An Environment. - private environmentType CreateDefaultEnvironmentType - (string applicationKey, - string authenticationMethod = null, - string consumerName = null, - string solutionId = null, - string dataModelNamespace = null, - string supportedInfrastructureVersion = null, - string transport = null, - string productName = null) + private static environmentType CreateDefaultEnvironmentType( + string applicationKey, + string authenticationMethod = null, + string consumerName = null, + string solutionId = null, + string dataModelNamespace = null, + string supportedInfrastructureVersion = null, + string transport = null, + string productName = null) { - applicationInfoType applicationInfo = new applicationInfoType(); - applicationInfo.applicationKey = applicationKey; + var applicationInfo = new applicationInfoType { applicationKey = applicationKey }; if (!string.IsNullOrWhiteSpace(dataModelNamespace)) { applicationInfo.dataModelNamespace = dataModelNamespace; } - if (string.IsNullOrWhiteSpace(supportedInfrastructureVersion)) - { - applicationInfo.supportedInfrastructureVersion = defaultSupportedInfrastructureVersion; - } - else - { - applicationInfo.supportedInfrastructureVersion = supportedInfrastructureVersion; - } + applicationInfo.supportedInfrastructureVersion = + string.IsNullOrWhiteSpace(supportedInfrastructureVersion) + ? DefaultSupportedInfrastructureVersion + : supportedInfrastructureVersion; if (!string.IsNullOrWhiteSpace(transport)) { @@ -99,31 +92,18 @@ private environmentType CreateDefaultEnvironmentType if (!string.IsNullOrWhiteSpace(productName)) { - productIdentityType productIdentity = new productIdentityType(); - productIdentity.productName = productName; + var productIdentity = new productIdentityType { productName = productName }; applicationInfo.applicationProduct = productIdentity; } - environmentType environmentType = new environmentType(); - environmentType.applicationInfo = applicationInfo; - - if (string.IsNullOrWhiteSpace(authenticationMethod)) - { - environmentType.authenticationMethod = defaultAuthenticationMethod; - } - else - { - environmentType.authenticationMethod = authenticationMethod; - } - - if (string.IsNullOrWhiteSpace(consumerName)) - { - environmentType.consumerName = defaultConsumerName; - } - else + var environmentType = new environmentType { - environmentType.consumerName = consumerName; - } + applicationInfo = applicationInfo, + authenticationMethod = string.IsNullOrWhiteSpace(authenticationMethod) + ? DefaultAuthenticationMethod + : authenticationMethod, + consumerName = string.IsNullOrWhiteSpace(consumerName) ? DefaultConsumerName : consumerName + }; if (!string.IsNullOrWhiteSpace(solutionId)) { @@ -136,8 +116,7 @@ private environmentType CreateDefaultEnvironmentType /// /// Create an instance. /// - public EnvironmentsController() - : base(new EnvironmentService()) + protected EnvironmentsController() : base(new EnvironmentService()) { } @@ -148,7 +127,9 @@ public EnvironmentsController() /// The zone in which to perform the request. /// The context in which to perform the request. /// HTTP status 403. - public override ICollection Get([MatrixParameter] string[] zoneId = null, [MatrixParameter] string[] contextId = null) + public override ICollection Get( + [MatrixParameter] string[] zoneId = null, + [MatrixParameter] string[] contextId = null) { throw new HttpResponseException(HttpStatusCode.Forbidden); } @@ -162,7 +143,10 @@ public override ICollection Get([MatrixParameter] string[] zone /// Environment. [Route("{id}")] [HttpGet] - public override environmentType Get(Guid id, [MatrixParameter] string[] zoneId = null, [MatrixParameter] string[] contextId = null) + public override environmentType Get( + Guid id, + [MatrixParameter] string[] zoneId = null, + [MatrixParameter] string[] contextId = null) { return base.Get(id, zoneId, contextId); } @@ -175,7 +159,10 @@ public override environmentType Get(Guid id, [MatrixParameter] string[] zoneId = /// The zone in which to perform the request. /// The context in which to perform the request. /// HTTP status 403. - public override HttpResponseMessage Post(environmentType item, [MatrixParameter] string[] zoneId = null, [MatrixParameter] string[] contextId = null) + public override HttpResponseMessage Post( + environmentType item, + [MatrixParameter] string[] zoneId = null, + [MatrixParameter] string[] contextId = null) { throw new HttpResponseException(HttpStatusCode.Forbidden); } @@ -194,30 +181,37 @@ public override HttpResponseMessage Post(environmentType item, [MatrixParameter] /// HTTP response message indicating success or failure. [HttpPost] [Route("api/environments/environment")] - public virtual HttpResponseMessage Create - (environmentType item, - string authenticationMethod = null, - string consumerName = null, - string solutionId = null, - string dataModelNamespace = null, - string supportedInfrastructureVersion = null, - string transport = null, - string productName = null) + public virtual HttpResponseMessage Create( + environmentType item, + string authenticationMethod = null, + string consumerName = null, + string solutionId = null, + string dataModelNamespace = null, + string supportedInfrastructureVersion = null, + string transport = null, + string productName = null) { - HttpResponseMessage responseMessage = null; - string initialToken; + HttpResponseMessage responseMessage; - if (!authService.VerifyInitialAuthenticationHeader(Request.Headers, out initialToken)) + if (!authService.VerifyInitialAuthenticationHeader(Request.Headers, out string initialToken)) { - string errorMessage = "The POST request failed for Environment creation due to invalid authentication credentials."; + const string errorMessage = + "The POST request failed for Environment creation due to invalid authentication credentials."; responseMessage = HttpUtils.CreateErrorResponse(Request, HttpStatusCode.Unauthorized, errorMessage); } else { - if (item == null) { - item = CreateDefaultEnvironmentType(initialToken, authenticationMethod, consumerName, solutionId, dataModelNamespace, supportedInfrastructureVersion, transport, productName); + item = CreateDefaultEnvironmentType( + initialToken, + authenticationMethod, + consumerName, + solutionId, + dataModelNamespace, + supportedInfrastructureVersion, + transport, + productName); } try @@ -232,7 +226,6 @@ public virtual HttpResponseMessage Create { responseMessage = HttpUtils.CreateErrorResponse(Request, HttpStatusCode.Conflict, e); } - } return responseMessage; @@ -247,7 +240,11 @@ public virtual HttpResponseMessage Create /// The zone in which to perform the request. /// The context in which to perform the request. /// Exception representing HTTP status 403 Forbidden. - public override void Put(Guid id, environmentType item, [MatrixParameter] string[] zoneId = null, [MatrixParameter] string[] contextId = null) + public override void Put( + Guid id, + environmentType item, + [MatrixParameter] string[] zoneId = null, + [MatrixParameter] string[] contextId = null) { throw new HttpResponseException(HttpStatusCode.Forbidden); } @@ -260,11 +257,12 @@ public override void Put(Guid id, environmentType item, [MatrixParameter] string /// The context in which to perform the request. [Route("{id}")] [HttpDelete] - public override void Delete(Guid id, [MatrixParameter] string[] zoneId = null, [MatrixParameter] string[] contextId = null) + public override void Delete( + Guid id, + [MatrixParameter] string[] zoneId = null, + [MatrixParameter] string[] contextId = null) { base.Delete(id, zoneId, contextId); } - } - -} +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework/Model/Exceptions/AlreadyExistsException.cs b/Code/Sif3Framework/Sif.Framework/Model/Exceptions/AlreadyExistsException.cs deleted file mode 100644 index f51af468..00000000 --- a/Code/Sif3Framework/Sif.Framework/Model/Exceptions/AlreadyExistsException.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2016 Systemic Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.Serialization; - -namespace Sif.Framework.Model.Exceptions -{ - - /// - /// This exception represents the situation where an item already exists. - /// - [Serializable] - public class AlreadyExistsException : BaseException - { - - /// - /// - /// - public AlreadyExistsException() - : base() - { - - } - - /// - /// - /// - public AlreadyExistsException(string message) - : base(message) - { - - } - - /// - /// - /// - public AlreadyExistsException(string message, Exception innerException) - : base(message, innerException) - { - - } - - /// - /// - /// - protected AlreadyExistsException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - - } - - } - -} diff --git a/Code/Sif3Framework/Sif.Framework/Model/Exceptions/NotFoundException.cs b/Code/Sif3Framework/Sif.Framework/Model/Exceptions/NotFoundException.cs deleted file mode 100644 index a6b4e314..00000000 --- a/Code/Sif3Framework/Sif.Framework/Model/Exceptions/NotFoundException.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 Systemic Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Runtime.Serialization; - -namespace Sif.Framework.Model.Exceptions -{ - - /// - /// This exception represents the situation where an item cannot be found. - /// - [Serializable] - public class NotFoundException : BaseException - { - - /// - /// - /// - public NotFoundException() - : base() - { - } - - /// - /// - /// - public NotFoundException(string message) - : base(message) - { - } - - /// - /// - /// - public NotFoundException(string message, Exception innerException) - : base(message, innerException) - { - } - - /// - /// - /// - protected NotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - } - -} diff --git a/Code/Sif3Framework/Sif.Framework/Model/Sessions/Session.cs b/Code/Sif3Framework/Sif.Framework/Model/Sessions/Session.cs new file mode 100644 index 00000000..adcb37fc --- /dev/null +++ b/Code/Sif3Framework/Sif.Framework/Model/Sessions/Session.cs @@ -0,0 +1,77 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.ComponentModel.DataAnnotations; +using Tardigrade.Framework.Models.Domain; + +namespace Sif.Framework.Model.Sessions +{ + /// + /// Session data associated with Consumer/Provider interaction with an Environment Provider or Broker. + /// + public class Session : IHasUniqueIdentifier + { + /// + /// Application key. + /// + [Required] + public string ApplicationKey { get; set; } + + /// + /// Environment URL. + /// + [Required] + public string EnvironmentUrl { get; set; } + + /// + /// Unique identifier for the session. + /// + [Required] + public Guid Id { get; set; } + + /// + /// Instance identifier. + /// + public string InstanceId { get; set; } + + /// + /// Queue identifier. + /// + public string QueueId { get; set; } + + /// + /// Session token. + /// + [Required] + public string SessionToken { get; set; } + + /// + /// Solution identifier. + /// + public string SolutionId { get; set; } + + /// + /// Subscription identifier. + /// + public string SubscriptionId { get; set; } + + /// + /// User token. + /// + public string UserToken { get; set; } + } +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework/Providers/BasicProvider.cs b/Code/Sif3Framework/Sif.Framework/Providers/BasicProvider.cs index 66a0160b..654ef12b 100644 --- a/Code/Sif3Framework/Sif.Framework/Providers/BasicProvider.cs +++ b/Code/Sif3Framework/Sif.Framework/Providers/BasicProvider.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ using Sif.Framework.Model.Settings; using Sif.Framework.Service.Providers; using Sif.Framework.Service.Serialisation; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Framework.WebApi.ModelBinders; using Sif.Specification.Infrastructure; @@ -29,6 +30,7 @@ using System.Net; using System.Web.Http; using System.Xml.Serialization; +using Tardigrade.Framework.Exceptions; namespace Sif.Framework.Providers { @@ -39,13 +41,12 @@ namespace Sif.Framework.Providers /// Type of object associated with the Service Provider. public abstract class BasicProvider : Provider> where T : ISifRefId { - /// - /// Create an instance based on the specified service. - /// - /// Service used for managing the object type. - /// Provider settings. If null, Provider settings will be read from the SifFramework.config file. - protected BasicProvider(IBasicProviderService service, IFrameworkSettings settings = null) - : base(service, settings) + /// + protected BasicProvider( + IBasicProviderService service, + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(service, settings, sessionService) { } @@ -53,7 +54,7 @@ protected BasicProvider(IBasicProviderService service, IFrameworkSettings set /// Post /// public override IHttpActionResult Post( - List objs, + List items, [MatrixParameter] string[] zoneId = null, [MatrixParameter] string[] contextId = null) { @@ -79,12 +80,12 @@ public override IHttpActionResult Post( { bool? mustUseAdvisory = HttpUtils.GetMustUseAdvisory(Request.Headers); - foreach (T obj in objs) + foreach (T item in items) { - bool hasAdvisoryId = !string.IsNullOrWhiteSpace(obj.RefId); + bool hasAdvisoryId = !string.IsNullOrWhiteSpace(item.RefId); var status = new createType { - advisoryId = (hasAdvisoryId ? obj.RefId : null) + advisoryId = (hasAdvisoryId ? item.RefId : null) }; try @@ -101,13 +102,13 @@ public override IHttpActionResult Post( } else { - status.id = Service.Create(obj, mustUseAdvisory, zoneId?[0], contextId?[0]).RefId; + status.id = Service.Create(item, mustUseAdvisory, zoneId?[0], contextId?[0]).RefId; status.statusCode = ((int)HttpStatusCode.Created).ToString(); } } else { - status.id = Service.Create(obj, null, zoneId?[0], contextId?[0]).RefId; + status.id = Service.Create(item, null, zoneId?[0], contextId?[0]).RefId; status.statusCode = ((int)HttpStatusCode.Created).ToString(); } } @@ -116,7 +117,7 @@ public override IHttpActionResult Post( status.error = ProviderUtils.CreateError( HttpStatusCode.Conflict, TypeName, - $"Object {TypeName} with ID of {obj.RefId} already exists.\n{e.Message}"); + $"Object {TypeName} with ID of {item.RefId} already exists.\n{e.Message}"); status.statusCode = ((int)HttpStatusCode.Conflict).ToString(); } catch (ArgumentException e) @@ -124,7 +125,7 @@ public override IHttpActionResult Post( status.error = ProviderUtils.CreateError( HttpStatusCode.BadRequest, TypeName, - $"Object to create of type {TypeName}" + (hasAdvisoryId ? $" with ID of {obj.RefId}" : "") + $" is invalid.\n {e.Message}"); + $"Object to create of type {TypeName}" + (hasAdvisoryId ? $" with ID of {item.RefId}" : "") + $" is invalid.\n {e.Message}"); status.statusCode = ((int)HttpStatusCode.BadRequest).ToString(); } catch (CreateException e) @@ -132,7 +133,7 @@ public override IHttpActionResult Post( status.error = ProviderUtils.CreateError( HttpStatusCode.BadRequest, TypeName, - $"Request failed for object {TypeName}" + (hasAdvisoryId ? $" with ID of {obj.RefId}" : "") + $".\n{e.Message}"); + $"Request failed for object {TypeName}" + (hasAdvisoryId ? $" with ID of {item.RefId}" : "") + $".\n{e.Message}"); status.statusCode = ((int)HttpStatusCode.BadRequest).ToString(); } catch (RejectedException e) @@ -140,7 +141,7 @@ public override IHttpActionResult Post( status.error = ProviderUtils.CreateError( HttpStatusCode.NotFound, TypeName, - $"Create request rejected for object {TypeName} with ID of {obj.RefId}.\n{e.Message}"); + $"Create request rejected for object {TypeName} with ID of {item.RefId}.\n{e.Message}"); status.statusCode = ((int)HttpStatusCode.Conflict).ToString(); } catch (Exception e) @@ -148,7 +149,7 @@ public override IHttpActionResult Post( status.error = ProviderUtils.CreateError( HttpStatusCode.InternalServerError, TypeName, - $"Request failed for object {TypeName}" + (hasAdvisoryId ? $" with ID of {obj.RefId}" : "") + $".\n{e.Message}"); + $"Request failed for object {TypeName}" + (hasAdvisoryId ? $" with ID of {item.RefId}" : "") + $".\n{e.Message}"); status.statusCode = ((int)HttpStatusCode.InternalServerError).ToString(); } @@ -169,7 +170,7 @@ public override IHttpActionResult Post( /// Put /// public override IHttpActionResult Put( - List objs, + List items, [MatrixParameter] string[] zoneId = null, [MatrixParameter] string[] contextId = null) { @@ -193,16 +194,16 @@ public override IHttpActionResult Put( try { - foreach (T obj in objs) + foreach (T item in items) { var status = new updateType { - id = obj.RefId + id = item.RefId }; try { - Service.Update(obj, (zoneId?[0]), (contextId?[0])); + Service.Update(item, (zoneId?[0]), (contextId?[0])); status.statusCode = ((int)HttpStatusCode.NoContent).ToString(); } catch (ArgumentException e) @@ -218,7 +219,7 @@ public override IHttpActionResult Put( status.error = ProviderUtils.CreateError( HttpStatusCode.NotFound, TypeName, - $"Object {TypeName} with ID of {obj.RefId} not found.\n{e.Message}"); + $"Object {TypeName} with ID of {item.RefId} not found.\n{e.Message}"); status.statusCode = ((int)HttpStatusCode.NotFound).ToString(); } catch (UpdateException e) @@ -226,7 +227,7 @@ public override IHttpActionResult Put( status.error = ProviderUtils.CreateError( HttpStatusCode.BadRequest, TypeName, - $"Request failed for object {TypeName} with ID of {obj.RefId}.\n{e.Message}"); + $"Request failed for object {TypeName} with ID of {item.RefId}.\n{e.Message}"); status.statusCode = ((int)HttpStatusCode.BadRequest).ToString(); } catch (Exception e) @@ -234,7 +235,7 @@ public override IHttpActionResult Put( status.error = ProviderUtils.CreateError( HttpStatusCode.InternalServerError, TypeName, - $"Request failed for object {TypeName} with ID of {obj.RefId}.\n{e.Message}"); + $"Request failed for object {TypeName} with ID of {item.RefId}.\n{e.Message}"); status.statusCode = ((int)HttpStatusCode.InternalServerError).ToString(); } diff --git a/Code/Sif3Framework/Sif.Framework/Providers/FunctionalServiceProvider.cs b/Code/Sif3Framework/Sif.Framework/Providers/FunctionalServiceProvider.cs index 1c97567b..546b2fc6 100644 --- a/Code/Sif3Framework/Sif.Framework/Providers/FunctionalServiceProvider.cs +++ b/Code/Sif3Framework/Sif.Framework/Providers/FunctionalServiceProvider.cs @@ -1,6 +1,6 @@ /* * Crown Copyright © Department for Education (UK) 2016 - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ using Sif.Framework.Service.Authentication; using Sif.Framework.Service.Functional; using Sif.Framework.Service.Infrastructure; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Framework.WebApi.ModelBinders; using Sif.Specification.Infrastructure; @@ -32,6 +33,7 @@ using System.Net.Http; using System.Text; using System.Web.Http; +using Tardigrade.Framework.Exceptions; using Environment = Sif.Framework.Model.Infrastructure.Environment; namespace Sif.Framework.Providers @@ -66,7 +68,8 @@ public FunctionalServiceProvider() : this(null) /// Create an instance. /// /// Provider settings. If null, Provider settings will be read from the SifFramework.config file. - protected FunctionalServiceProvider(IFrameworkSettings settings = null) + /// Provider session service. If null, the Provider session will be stored in the SifFramework.config file. + protected FunctionalServiceProvider(IFrameworkSettings settings = null, ISessionService sessionService = null) { ProviderSettings = settings ?? SettingsManager.ProviderSettings; @@ -80,8 +83,8 @@ protected FunctionalServiceProvider(IFrameworkSettings settings = null) authService = new BrokeredAuthenticationService( new ApplicationRegisterService(), new EnvironmentService(), - settings, - SessionsManager.ProviderSessionService); + ProviderSettings, + sessionService ?? SessionsManager.ProviderSessionService); } } @@ -110,7 +113,6 @@ public virtual HttpResponseMessage Post( bool hasAdvisoryId = ProviderUtils.IsAdvisoryId(item.id); bool? _mustUseAdvisory = HttpUtils.GetMustUseAdvisory(Request.Headers); bool mustUseAdvisory = _mustUseAdvisory.HasValue && _mustUseAdvisory.Value; - IFunctionalService service = GetService(serviceName); if (!service.AcceptJob(serviceName, jobName)) @@ -135,9 +137,7 @@ public virtual HttpResponseMessage Post( } jobType job = service.Retrieve(id, zoneId?[0], contextId?[0]); - string uri = Url.Link("ServicesRoute", new { controller = serviceName, id }); - result = Request.CreateResponse(HttpStatusCode.Created, job); result.Headers.Location = new Uri(uri); } @@ -918,7 +918,7 @@ protected virtual IFunctionalService GetService(string serviceName) $"No functional service found to support messages to {serviceName}."); } - if (!ProviderUtils.isFunctionalService(service.GetType())) + if (!ProviderUtils.IsFunctionalService(service.GetType())) { throw new InvalidOperationException( $"Service ({service.GetType().Name}) found for {serviceName} is not a functional service implementation"); @@ -1007,8 +1007,8 @@ private IDictionary GetRights(string serviceName, ProvisionedZone { Model.Infrastructure.Service service = (from Model.Infrastructure.Service s in zone.Services - where s.Type.Equals(ServiceType.FUNCTIONAL.ToString()) && s.Name.Equals(serviceName) - select s) + where s.Type.Equals(ServiceType.FUNCTIONAL.ToString()) && s.Name.Equals(serviceName) + select s) .FirstOrDefault(); if (service == null) diff --git a/Code/Sif3Framework/Sif.Framework/Providers/FunctionalServiceProviderFactory.cs b/Code/Sif3Framework/Sif.Framework/Providers/FunctionalServiceProviderFactory.cs index 39d9f44e..0ea07047 100644 --- a/Code/Sif3Framework/Sif.Framework/Providers/FunctionalServiceProviderFactory.cs +++ b/Code/Sif3Framework/Sif.Framework/Providers/FunctionalServiceProviderFactory.cs @@ -1,6 +1,6 @@ /* * Crown Copyright © Department for Education (UK) 2016 - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,7 +78,7 @@ private Type[] Classes { classes = (from assembly in AppDomain.CurrentDomain.GetAssemblies() from type in assembly.GetTypes() - where ProviderUtils.isFunctionalService(type) + where ProviderUtils.IsFunctionalService(type) select type).ToArray(); foreach (Type t in classes) diff --git a/Code/Sif3Framework/Sif.Framework/Providers/ObjectProvider.cs b/Code/Sif3Framework/Sif.Framework/Providers/ObjectProvider.cs index 5ddac0ec..2d6046dd 100644 --- a/Code/Sif3Framework/Sif.Framework/Providers/ObjectProvider.cs +++ b/Code/Sif3Framework/Sif.Framework/Providers/ObjectProvider.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ using Sif.Framework.Service.Mapper; using Sif.Framework.Service.Providers; using Sif.Framework.Service.Serialisation; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Framework.WebApi.ModelBinders; using Sif.Specification.Infrastructure; @@ -30,18 +31,22 @@ namespace Sif.Framework.Providers { + /// + /// This class defines a Provider of SIF data model objects whereby the primary key is of type System.String. + /// + /// Type that defines a single object entity. + /// Type that defines a multiple objects entity. public abstract class ObjectProvider : Provider where TSingle : ISifRefId { private readonly IObjectProviderService service; - /// - /// Create an instance based on the specified service. - /// - /// Service used for managing the object type. - /// Provider settings. If null, Provider settings will be read from the SifFramework.config file. - protected ObjectProvider(IObjectProviderService service, IFrameworkSettings settings = null) - : base(service, settings) + /// + protected ObjectProvider( + IObjectProviderService service, + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(service, settings, sessionService) { this.service = service; } diff --git a/Code/Sif3Framework/Sif.Framework/Providers/Provider.cs b/Code/Sif3Framework/Sif.Framework/Providers/Provider.cs index 97be3b08..6191cb52 100644 --- a/Code/Sif3Framework/Sif.Framework/Providers/Provider.cs +++ b/Code/Sif3Framework/Sif.Framework/Providers/Provider.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ using Sif.Framework.Service.Infrastructure; using Sif.Framework.Service.Providers; using Sif.Framework.Service.Registration; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Framework.WebApi.ModelBinders; using Sif.Specification.Infrastructure; @@ -39,6 +40,7 @@ using System.Net; using System.Net.Http; using System.Web.Http; +using Tardigrade.Framework.Exceptions; namespace Sif.Framework.Providers { @@ -51,6 +53,8 @@ public abstract class Provider : ApiController, IProvider, IEventPayloadSerialisable where TSingle : ISifRefId { + private readonly ISessionService sessionService; + /// /// Accepted content type (XML or JSON) for a message payload. /// @@ -91,10 +95,16 @@ public abstract class Provider /// /// Service used for managing the object type. /// Provider settings. If null, Provider settings will be read from the SifFramework.config file. - protected Provider(IProviderService service, IFrameworkSettings settings = null) + /// Provider session service. If null, the Provider session will be stored in the SifFramework.config file. + /// service is null. + protected Provider( + IProviderService service, + IFrameworkSettings settings = null, + ISessionService sessionService = null) { - Service = service; + Service = service ?? throw new ArgumentNullException(nameof(service)); ProviderSettings = settings ?? SettingsManager.ProviderSettings; + this.sessionService = sessionService ?? SessionsManager.ProviderSessionService; if (EnvironmentType.DIRECT.Equals(ProviderSettings.EnvironmentType)) { @@ -106,8 +116,8 @@ protected Provider(IProviderService service, IFrameworkSetti AuthenticationService = new BrokeredAuthenticationService( new ApplicationRegisterService(), new EnvironmentService(), - settings, - SessionsManager.ProviderSessionService); + ProviderSettings, + this.sessionService); } AuthorisationService = new AuthorisationService(AuthenticationService); @@ -301,17 +311,17 @@ private IHttpActionResult GetAll(string zoneId, string contextId) uint? navigationPage = HttpUtils.GetNavigationPage(Request.Headers); uint? navigationPageSize = HttpUtils.GetNavigationPageSize(Request.Headers); RequestParameter[] requestParameters = GetQueryParameters(Request); - TMultiple objs = + TMultiple items = Service.Retrieve(navigationPage, navigationPageSize, zoneId, contextId, requestParameters); IHttpActionResult result; - if (objs == null) + if (items == null) { result = StatusCode(HttpStatusCode.NoContent); } else { - result = Ok(objs); + result = Ok(items); } return result; @@ -347,7 +357,7 @@ private IHttpActionResult GetChangesSince(string changesSinceMarker, string zone uint? navigationPage = HttpUtils.GetNavigationPage(Request.Headers); uint? navigationPageSize = HttpUtils.GetNavigationPageSize(Request.Headers); RequestParameter[] requestParameters = GetQueryParameters(Request); - TMultiple objs = changesSinceService.RetrieveChangesSince( + TMultiple items = changesSinceService.RetrieveChangesSince( changesSinceMarker, navigationPage, navigationPageSize, @@ -356,13 +366,13 @@ private IHttpActionResult GetChangesSince(string changesSinceMarker, string zone requestParameters); IHttpActionResult result; - if (objs == null) + if (items == null) { result = StatusCode(HttpStatusCode.NoContent); } else { - result = Ok(objs); + result = Ok(items); } bool pagedRequest = navigationPage.HasValue && navigationPageSize.HasValue; @@ -408,17 +418,17 @@ private IHttpActionResult GetQueryByExample(TSingle obj, string zoneId, string c uint? navigationPage = HttpUtils.GetNavigationPage(Request.Headers); uint? navigationPageSize = HttpUtils.GetNavigationPageSize(Request.Headers); RequestParameter[] requestParameters = GetQueryParameters(Request); - TMultiple objs = + TMultiple items = Service.Retrieve(obj, navigationPage, navigationPageSize, zoneId, contextId, requestParameters); IHttpActionResult result; - if (objs == null) + if (items == null) { result = StatusCode(HttpStatusCode.NoContent); } else { - result = Ok(objs); + result = Ok(items); } return result; @@ -558,7 +568,7 @@ public virtual IHttpActionResult Get( uint? navigationPage = HttpUtils.GetNavigationPage(Request.Headers); uint? navigationPageSize = HttpUtils.GetNavigationPageSize(Request.Headers); RequestParameter[] requestParameters = GetQueryParameters(Request); - TMultiple objs = Service.Retrieve( + TMultiple items = Service.Retrieve( conditions, navigationPage, navigationPageSize, @@ -566,13 +576,13 @@ public virtual IHttpActionResult Get( contextId?[0], requestParameters); - if (objs == null) + if (items == null) { result = StatusCode(HttpStatusCode.NoContent); } else { - result = Ok(objs); + result = Ok(items); } } catch (ArgumentException e) @@ -881,7 +891,7 @@ public virtual IHttpActionResult BroadcastEvents(string zoneId = null, string co { IRegistrationService registrationService = RegistrationManager.GetProviderRegistrationService( ProviderSettings, - SessionsManager.ProviderSessionService); + sessionService); if (registrationService is NoRegistrationService) { @@ -941,9 +951,9 @@ public virtual IHttpActionResult BroadcastEvents(string zoneId = null, string co acceptOverride: Accept.ToDescription(), requestHeaders: requestHeaders); } - } - result = Ok(); + result = Ok(); + } } } catch (Exception e) diff --git a/Code/Sif3Framework/Sif.Framework/Service/Authentication/BrokeredAuthenticationService.cs b/Code/Sif3Framework/Sif.Framework/Service/Authentication/BrokeredAuthenticationService.cs index 4504a5c1..b0e126c3 100644 --- a/Code/Sif3Framework/Sif.Framework/Service/Authentication/BrokeredAuthenticationService.cs +++ b/Code/Sif3Framework/Sif.Framework/Service/Authentication/BrokeredAuthenticationService.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,9 @@ using Sif.Framework.Service.Mapper; using Sif.Framework.Service.Sessions; using Sif.Specification.Infrastructure; +using System; using System.Net.Http.Headers; +using Environment = Sif.Framework.Model.Infrastructure.Environment; namespace Sif.Framework.Service.Authentication { @@ -35,16 +37,24 @@ internal class BrokeredAuthenticationService : AuthenticationService private readonly IFrameworkSettings settings; private readonly ISessionService sessionService; + /// + /// Create an instance of this service. + /// + /// Application register service. + /// Environment service. + /// Framework settings service. + /// Session service. + /// A passed parameter is null. public BrokeredAuthenticationService( IApplicationRegisterService applicationRegisterService, IEnvironmentService environmentService, IFrameworkSettings settings, ISessionService sessionService) { - this.applicationRegisterService = applicationRegisterService; - this.environmentService = environmentService; - this.settings = settings; - this.sessionService = sessionService; + this.applicationRegisterService = applicationRegisterService ?? throw new ArgumentNullException(nameof(applicationRegisterService)); + this.environmentService = environmentService ?? throw new ArgumentNullException(nameof(environmentService)); + this.settings = settings ?? throw new ArgumentNullException(nameof(settings)); + this.sessionService = sessionService ?? throw new ArgumentNullException(nameof(sessionService)); } /// diff --git a/Code/Sif3Framework/Sif.Framework/Service/Infrastructure/EnvironmentService.cs b/Code/Sif3Framework/Sif.Framework/Service/Infrastructure/EnvironmentService.cs index 0de565ec..6b778568 100644 --- a/Code/Sif3Framework/Sif.Framework/Service/Infrastructure/EnvironmentService.cs +++ b/Code/Sif3Framework/Sif.Framework/Service/Infrastructure/EnvironmentService.cs @@ -1,12 +1,12 @@ /* - * Copyright 2017 Systemic Pty Ltd - * + * Copyright 2021 Systemic Pty Ltd + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,7 +14,6 @@ * limitations under the License. */ -using Sif.Framework.Model.Exceptions; using Sif.Framework.Model.Infrastructure; using Sif.Framework.Persistence.NHibernate; using Sif.Framework.Service.Mapper; @@ -22,35 +21,30 @@ using Sif.Specification.Infrastructure; using System; using System.Collections.Generic; +using Tardigrade.Framework.Exceptions; using Environment = Sif.Framework.Model.Infrastructure.Environment; namespace Sif.Framework.Service.Infrastructure { - /// /// Service class for Environment objects. /// public class EnvironmentService : SifService, IEnvironmentService { - /// /// Create a copy of a Zone object. /// /// Zone object to copy. /// New copy of the Zone object. - private Zone CopyDefaultZone(Zone sourceZone) + private static Zone CopyDefaultZone(Zone sourceZone) { - Zone destinationZone = null; - - if (sourceZone != null) - { - destinationZone = new Zone { Description = sourceZone.Description, SifId = sourceZone.SifId }; + if (sourceZone == null) return null; - if (sourceZone.Properties != null) - { - destinationZone.Properties = CopyProperties(sourceZone.Properties); - } + var destinationZone = new Zone { Description = sourceZone.Description, SifId = sourceZone.SifId }; + if (sourceZone.Properties != null) + { + destinationZone.Properties = CopyProperties(sourceZone.Properties); } return destinationZone; @@ -59,50 +53,47 @@ private Zone CopyDefaultZone(Zone sourceZone) /// /// Create a copy of a dictionary of InfrastructureService objects. /// - /// Dictionary of InfrastructureService objects to copy. - /// New copy of the dictionary of InfrastructureService objects. - private IDictionary CopyInfrastructureServices(IDictionary sourceInfrastructureServices) + /// Dictionary of InfrastructureService objects to copy. + /// New copy of the dictionary of InfrastructureService objects if not null; null otherwise. + private static IDictionary CopyInfrastructureServices( + IDictionary sourceServices) { - IDictionary destinationInfrastructureServices = null; + if (sourceServices == null) return null; - if (sourceInfrastructureServices != null) - { - destinationInfrastructureServices = new Dictionary(); + var destinationServices = new Dictionary(); - foreach (InfrastructureServiceNames key in sourceInfrastructureServices.Keys) + foreach (InfrastructureServiceNames key in sourceServices.Keys) + { + if (sourceServices.TryGetValue(key, out InfrastructureService sourceService)) { - InfrastructureService sourceInfrastructureService; - sourceInfrastructureServices.TryGetValue(key, out sourceInfrastructureService); - InfrastructureService destinationInfrastructureService = new InfrastructureService { Name = sourceInfrastructureService.Name, Value = sourceInfrastructureService.Value }; - destinationInfrastructureServices.Add(key, destinationInfrastructureService); + var destinationService = + new InfrastructureService { Name = sourceService.Name, Value = sourceService.Value }; + destinationServices.Add(key, destinationService); } - } - return destinationInfrastructureServices; + return destinationServices; } /// /// Create a copy of a dictionary of Property objects. /// /// Dictionary of Property objects to copy. - /// New copy of the dictionary of Property objects. - private IDictionary CopyProperties(IDictionary sourceProperties) + /// New copy of the dictionary of Property objects if not null; null otherwise. + private static IDictionary CopyProperties(IDictionary sourceProperties) { - IDictionary destinationProperties = null; + if (sourceProperties == null) return null; - if (sourceProperties != null) - { - destinationProperties = new Dictionary(); + var destinationProperties = new Dictionary(); - foreach (string key in sourceProperties.Keys) + foreach (string key in sourceProperties.Keys) + { + if (sourceProperties.TryGetValue(key, out Property sourceProperty)) { - Property sourceProperty; - sourceProperties.TryGetValue(key, out sourceProperty); - Property destinationProperty = new Property { Name = sourceProperty.Name, Value = sourceProperty.Value }; + var destinationProperty = + new Property { Name = sourceProperty.Name, Value = sourceProperty.Value }; destinationProperties.Add(key, destinationProperty); } - } return destinationProperties; @@ -111,56 +102,51 @@ private IDictionary CopyProperties(IDictionary /// Create a copy of a dictionary of ProvisionedZone objects. /// - /// Dictionary of ProvisionedZone objects to copy. - /// New copy of the dictionary of ProvisionedZone objects. - private IDictionary CopyProvisionedZones(IDictionary sourceProvisionedZones) + /// Dictionary of ProvisionedZone objects to copy. + /// New copy of the dictionary of ProvisionedZone objects if not null; null otherwise. + private static IDictionary CopyProvisionedZones( + IDictionary sourceZones) { - IDictionary destinationProvisionedZones = null; + if (sourceZones == null) return null; - if (sourceProvisionedZones != null) - { - destinationProvisionedZones = new Dictionary(); + var destinationZones = new Dictionary(); - foreach (string key in sourceProvisionedZones.Keys) + foreach (string key in sourceZones.Keys) + { + if (sourceZones.TryGetValue(key, out ProvisionedZone sourceZone)) { - ProvisionedZone sourceProvisionedZone; - sourceProvisionedZones.TryGetValue(key, out sourceProvisionedZone); - ProvisionedZone destinationProvisionedZone = new ProvisionedZone { SifId = sourceProvisionedZone.SifId }; + var destinationZone = new ProvisionedZone { SifId = sourceZone.SifId }; - if (sourceProvisionedZone.Services != null) + if (sourceZone.Services != null) { - destinationProvisionedZone.Services = CopyServices(sourceProvisionedZone.Services); + destinationZone.Services = CopyServices(sourceZone.Services); } - destinationProvisionedZones.Add(key, destinationProvisionedZone); + destinationZones.Add(key, destinationZone); } - } - return destinationProvisionedZones; + return destinationZones; } /// /// Create a copy of a dictionary of Right objects. /// /// Dictionary of Right objects to copy. - /// New copy of the dictionary of Right objects. - private IDictionary CopyRights(IDictionary sourceRights) + /// New copy of the dictionary of Right objects if not null; null otherwise. + private static IDictionary CopyRights(IDictionary sourceRights) { - IDictionary destinationRights = null; + if (sourceRights == null) return null; - if (sourceRights != null) - { - destinationRights = new Dictionary(); + var destinationRights = new Dictionary(); - foreach (string key in sourceRights.Keys) + foreach (string key in sourceRights.Keys) + { + if (sourceRights.TryGetValue(key, out Right sourceRight)) { - Right sourceRight; - sourceRights.TryGetValue(key, out sourceRight); - Right destinationRight = new Right { Type = sourceRight.Type, Value = sourceRight.Value }; + var destinationRight = new Right { Type = sourceRight.Type, Value = sourceRight.Value }; destinationRights.Add(key, destinationRight); } - } return destinationRights; @@ -170,27 +156,29 @@ private IDictionary CopyRights(IDictionary sourceR /// Create a copy of a collection of Service objects. /// /// Collection of Service objects to copy. - /// New copy of the collection of Service objects. - private ICollection CopyServices(ICollection sourceServices) + /// New copy of the collection of Service objects if not null; null otherwise. + private static ICollection CopyServices( + ICollection sourceServices) { - ICollection destinationServices = null; + if (sourceServices == null) return null; - if (sourceServices != null) - { - destinationServices = new List(); + var destinationServices = new List(); - foreach (Model.Infrastructure.Service sourceService in sourceServices) + foreach (Model.Infrastructure.Service sourceService in sourceServices) + { + var destinationService = new Model.Infrastructure.Service { - Model.Infrastructure.Service destinationService = new Model.Infrastructure.Service { ContextId = sourceService.ContextId, Name = sourceService.Name, Type = sourceService.Type }; + ContextId = sourceService.ContextId, + Name = sourceService.Name, + Type = sourceService.Type + }; - if (sourceService.Rights != null) - { - destinationService.Rights = CopyRights(sourceService.Rights); - } - - destinationServices.Add(destinationService); + if (sourceService.Rights != null) + { + destinationService.Rights = CopyRights(sourceService.Rights); } + destinationServices.Add(destinationService); } return destinationServices; @@ -199,8 +187,7 @@ private IDictionary CopyRights(IDictionary sourceR /// /// Create a default instance. /// - public EnvironmentService() - : base(new EnvironmentRepository()) + public EnvironmentService() : base(new EnvironmentRepository()) { } @@ -209,30 +196,39 @@ public EnvironmentService() /// public override Guid Create(environmentType item, string zoneId = null, string contextId = null) { - EnvironmentRegister environmentRegister = - (new EnvironmentRegisterService()).RetrieveByUniqueIdentifiers - (item.applicationInfo.applicationKey, item.instanceId, item.userToken, item.solutionId); + var environmentRegisterService = new EnvironmentRegisterService(); + EnvironmentRegister environmentRegister = environmentRegisterService.RetrieveByUniqueIdentifiers( + item.applicationInfo.applicationKey, + item.instanceId, + item.userToken, + item.solutionId); if (environmentRegister == null) { - string errorMessage = string.Format("Environment with application key of {0}, solution ID of {1}, instance ID of {2} and user token of {3} does NOT exist.", - item.applicationInfo.applicationKey, (item.solutionId == null ? "[null]" : item.solutionId), (item.instanceId == null ? "[null]" : item.instanceId), (item.userToken == null ? "[null]" : item.userToken)); + var errorMessage = + $"Environment with [applicationKey:{item.applicationInfo.applicationKey}|solutionId:{item.solutionId ?? ""}|instanceId:{item.instanceId ?? ""}|userToken:{item.userToken ?? ""}] does NOT exist."; throw new AlreadyExistsException(errorMessage); } - string sessionToken = AuthenticationUtils.GenerateSessionToken(item.applicationInfo.applicationKey, item.instanceId, item.userToken, item.solutionId); + string sessionToken = AuthenticationUtils.GenerateSessionToken( + item.applicationInfo.applicationKey, + item.instanceId, + item.userToken, + item.solutionId); environmentType environmentType = RetrieveBySessionToken(sessionToken); if (environmentType != null) { - string errorMessage = string.Format("A session token already exists for environment with application key of {0}, solution ID of {1}, instance ID of {2} and user token of {3}.", - item.applicationInfo.applicationKey, (item.solutionId == null ? "[null]" : item.solutionId), (item.instanceId == null ? "[null]" : item.instanceId), (item.userToken == null ? "[null]" : item.userToken)); + var errorMessage = + $"A session token already exists for environment with [applicationKey:{item.applicationInfo.applicationKey}|solutionId:{item.solutionId ?? ""}|instanceId:{item.instanceId ?? ""}|userToken:{item.userToken ?? ""}]."; throw new AlreadyExistsException(errorMessage); } - IDictionary infrastructureServices = CopyInfrastructureServices(environmentRegister.InfrastructureServices); - IDictionary provisionedZones = CopyProvisionedZones(environmentRegister.ProvisionedZones); + IDictionary infrastructureServices = + CopyInfrastructureServices(environmentRegister.InfrastructureServices); + IDictionary provisionedZones = + CopyProvisionedZones(environmentRegister.ProvisionedZones); Environment repoItem = MapperFactory.CreateInstance(item); if (environmentRegister.DefaultZone != null) @@ -242,7 +238,8 @@ public override Guid Create(environmentType item, string zoneId = null, string c if (infrastructureServices.Count > 0) { - repoItem.InfrastructureServices = CopyInfrastructureServices(environmentRegister.InfrastructureServices); + repoItem.InfrastructureServices = + CopyInfrastructureServices(environmentRegister.InfrastructureServices); } if (provisionedZones.Count > 0) @@ -253,16 +250,16 @@ public override Guid Create(environmentType item, string zoneId = null, string c repoItem.SessionToken = sessionToken; Guid environmentId = repository.Save(repoItem); - if (repoItem.InfrastructureServices.Count > 0) + if (repoItem.InfrastructureServices != null && repoItem.InfrastructureServices.Count > 0) { - InfrastructureService infrastructureService = repoItem.InfrastructureServices[InfrastructureServiceNames.environment]; + InfrastructureService infrastructureService = + repoItem.InfrastructureServices[InfrastructureServiceNames.environment]; if (infrastructureService != null) { infrastructureService.Value = infrastructureService.Value + "/" + environmentId; repository.Save(repoItem); } - } return environmentId; @@ -274,9 +271,8 @@ public override Guid Create(environmentType item, string zoneId = null, string c public virtual environmentType RetrieveBySessionToken(string sessionToken) { Environment environment = ((EnvironmentRepository)repository).RetrieveBySessionToken(sessionToken); + return MapperFactory.CreateInstance(environment); } - } - -} +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework/Service/Registration/RegistrationService.cs b/Code/Sif3Framework/Sif.Framework/Service/Registration/RegistrationService.cs index b0c7cd04..02da915e 100644 --- a/Code/Sif3Framework/Sif.Framework/Service/Registration/RegistrationService.cs +++ b/Code/Sif3Framework/Sif.Framework/Service/Registration/RegistrationService.cs @@ -127,10 +127,11 @@ private string TryParseEnvironmentUrl(string environmentXml) /// /// Framework settings. /// Service used for managing sessions. + /// Either settings and/or sessionService are null. public RegistrationService(IFrameworkSettings settings, ISessionService sessionService) { - this.settings = settings; - this.sessionService = sessionService; + this.settings = settings ?? throw new ArgumentNullException(nameof(settings)); + this.sessionService = sessionService ?? throw new ArgumentNullException(nameof(sessionService)); if (AuthenticationMethod.Basic.ToString() .Equals(settings.AuthenticationMethod, StringComparison.OrdinalIgnoreCase)) diff --git a/Code/Sif3Framework/Sif.Framework/Service/Sessions/ConfigFileBasedSessionService.cs b/Code/Sif3Framework/Sif.Framework/Service/Sessions/ConfigFileBasedSessionService.cs index c00ad4ca..d4b650e9 100644 --- a/Code/Sif3Framework/Sif.Framework/Service/Sessions/ConfigFileBasedSessionService.cs +++ b/Code/Sif3Framework/Sif.Framework/Service/Sessions/ConfigFileBasedSessionService.cs @@ -1,5 +1,5 @@ /* - * Copyright 2018 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ internal abstract class ConfigFileBasedSessionService : ISessionService /// /// Reference to the SifFramework.config custom configuration file. /// - protected Configuration Configuration { get; private set; } + protected Configuration Configuration { get; } /// /// Section of the configuration file containing the session information. @@ -40,42 +40,47 @@ internal abstract class ConfigFileBasedSessionService : ISessionService /// /// Create an instance of this class based upon the SifFramework.config file. /// - public ConfigFileBasedSessionService() + protected ConfigFileBasedSessionService() { - string configurationFilePath = null; #if NETFULL - configurationFilePath = System.Web.Hosting.HostingEnvironment.MapPath("~/SifFramework.config"); + string configurationFilePath = + System.Web.Hosting.HostingEnvironment.MapPath("~/SifFramework.config") ?? "SifFramework.config"; + #else + string configurationFilePath = null; Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); if (config.HasFile && !string.IsNullOrWhiteSpace(config.FilePath)) { configurationFilePath = $"{Path.GetDirectoryName(config.FilePath)}/SifFramework.config"; } -#endif if (configurationFilePath == null) { configurationFilePath = "SifFramework.config"; } +#endif - ExeConfigurationFileMap exeConfigurationFileMap = new ExeConfigurationFileMap + var exeConfigurationFileMap = new ExeConfigurationFileMap { ExeConfigFilename = configurationFilePath }; - Configuration = ConfigurationManager.OpenMappedExeConfiguration(exeConfigurationFileMap, ConfigurationUserLevel.None); + Configuration = + ConfigurationManager.OpenMappedExeConfiguration(exeConfigurationFileMap, ConfigurationUserLevel.None); if (!Configuration.HasFile) { string fullPath = Assembly.GetExecutingAssembly().Location; exeConfigurationFileMap.ExeConfigFilename = Path.GetDirectoryName(fullPath) + "\\SifFramework.config"; - Configuration = ConfigurationManager.OpenMappedExeConfiguration(exeConfigurationFileMap, ConfigurationUserLevel.None); + Configuration = ConfigurationManager.OpenMappedExeConfiguration( + exeConfigurationFileMap, + ConfigurationUserLevel.None); } if (!Configuration.HasFile) { - string message = $"Missing configuration file {configurationFilePath}."; + var message = $"Missing configuration file {configurationFilePath}."; throw new ConfigurationErrorsException(message); } } @@ -83,17 +88,21 @@ public ConfigFileBasedSessionService() /// /// /// - public bool HasSession(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null) + public bool HasSession( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) { - return (RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId) == null ? false : true); + return RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId) != null; } /// - /// + /// /// - public bool HasSession(string sessionToken) + public bool HasSessionToken(string sessionToken) { - return (SessionsSection.Sessions[sessionToken] == null ? false : true); + return SessionsSection.Sessions[sessionToken] != null; } /// @@ -101,7 +110,7 @@ public bool HasSession(string sessionToken) /// public void RemoveSession(string sessionToken) { - if (HasSession(sessionToken)) + if (HasSessionToken(sessionToken)) { SessionsSection.Sessions.Remove(sessionToken); Configuration.Save(ConfigurationSaveMode.Modified); @@ -112,21 +121,29 @@ public void RemoveSession(string sessionToken) /// /// /// - public string RetrieveEnvironmentUrl(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null) + public string RetrieveEnvironmentUrl( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) { - string environmentUrl = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId)?.EnvironmentUrl; + string url = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId)?.EnvironmentUrl; - return (string.IsNullOrWhiteSpace(environmentUrl) ? null : environmentUrl); + return (string.IsNullOrWhiteSpace(url) ? null : url); } /// /// /// - public string RetrieveQueueId(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null) + public string RetrieveQueueId( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) { - string queueId = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId)?.QueueId; + string id = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId)?.QueueId; - return (string.IsNullOrWhiteSpace(queueId) ? null : queueId); + return (string.IsNullOrWhiteSpace(id) ? null : id); } /// @@ -137,16 +154,20 @@ public string RetrieveQueueId(string applicationKey, string solutionId = null, s /// User token. /// Instance ID. /// Session entry if found; null otherwise. - private SessionElement RetrieveSessionEntry(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null) + private SessionElement RetrieveSessionEntry( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) { SessionElement sessionElement = null; foreach (SessionElement session in SessionsSection.Sessions) { if (string.Equals(applicationKey, session.ApplicationKey) && - (solutionId == null ? string.IsNullOrWhiteSpace(session.SolutionId) : solutionId.Equals(session.SolutionId)) && - (userToken == null ? string.IsNullOrWhiteSpace(session.UserToken) : userToken.Equals(session.UserToken)) && - (instanceId == null ? string.IsNullOrWhiteSpace(session.InstanceId) : instanceId.Equals(session.InstanceId))) + (solutionId?.Equals(session.SolutionId) ?? string.IsNullOrWhiteSpace(session.SolutionId)) && + (userToken?.Equals(session.UserToken) ?? string.IsNullOrWhiteSpace(session.UserToken)) && + (instanceId?.Equals(session.InstanceId) ?? string.IsNullOrWhiteSpace(session.InstanceId))) { sessionElement = session; break; @@ -159,7 +180,11 @@ private SessionElement RetrieveSessionEntry(string applicationKey, string soluti /// /// /// - public string RetrieveSessionToken(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null) + public string RetrieveSessionToken( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) { string sessionToken = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId)?.SessionToken; @@ -169,35 +194,48 @@ public string RetrieveSessionToken(string applicationKey, string solutionId = nu /// /// /// - public string RetrieveSubscriptionId(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null) + public string RetrieveSubscriptionId( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) { - string subscriptionId = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId)?.SubscriptionId; + string id = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId)?.SubscriptionId; - return (string.IsNullOrWhiteSpace(subscriptionId) ? null : subscriptionId); + return (string.IsNullOrWhiteSpace(id) ? null : id); } /// /// /// - public void StoreSession(string applicationKey, string sessionToken, string environmentUrl, string solutionId = null, string userToken = null, string instanceId = null) + public void StoreSession( + string applicationKey, + string sessionToken, + string environmentUrl, + string solutionId = null, + string userToken = null, + string instanceId = null) { if (HasSession(applicationKey, solutionId, userToken, instanceId)) { - string message = string.Format("Session with the following credentials already exists - [applicationKey={0}]{1}{2}{3}.", - applicationKey, - (solutionId == null ? "" : "[solutionId=" + solutionId + "]"), - (userToken == null ? "" : "[userToken=" + userToken + "]"), - (instanceId == null ? "" : "[instanceId=" + instanceId + "]")); + string solutionIdText = solutionId == null ? "" : "[solutionId=" + solutionId + "]"; + string userTokenText = userToken == null ? "" : "[userToken=" + userToken + "]"; + string instanceIdText = instanceId == null ? "" : "[instanceId=" + instanceId + "]"; + var message = + $"Session with the following credentials already exists - [applicationKey={applicationKey}]{solutionIdText}{userTokenText}{instanceIdText}."; + throw new ConfigurationErrorsException(message); } - if (HasSession(sessionToken)) + if (HasSessionToken(sessionToken)) { - string message = string.Format("Session already exists with a session token of {0}.", sessionToken); + var message = $"Session already exists with a session token of {sessionToken}."; + throw new ConfigurationErrorsException(message); } - SessionElement sessionElement = new SessionElement(applicationKey, sessionToken, environmentUrl, solutionId, userToken, instanceId); + var sessionElement = + new SessionElement(applicationKey, sessionToken, environmentUrl, solutionId, userToken, instanceId); SessionsSection.Sessions.Add(sessionElement); Configuration.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection(SifFrameworkSectionGroup.SectionGroupReference); @@ -206,7 +244,12 @@ public void StoreSession(string applicationKey, string sessionToken, string envi /// /// /// - public void UpdateQueueId(string queueId, string applicationKey, string solutionId = null, string userToken = null, string instanceId = null) + public void UpdateQueueId( + string queueId, + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) { SessionElement sessionElement = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId); @@ -221,7 +264,12 @@ public void UpdateQueueId(string queueId, string applicationKey, string solution /// /// /// - public void UpdateSubscriptionId(string subscriptionId, string applicationKey, string solutionId = null, string userToken = null, string instanceId = null) + public void UpdateSubscriptionId( + string subscriptionId, + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null) { SessionElement sessionElement = RetrieveSessionEntry(applicationKey, solutionId, userToken, instanceId); diff --git a/Code/Sif3Framework/Sif.Framework/Service/Sessions/ISessionService.cs b/Code/Sif3Framework/Sif.Framework/Service/Sessions/ISessionService.cs index 53bfcdc2..89755e30 100644 --- a/Code/Sif3Framework/Sif.Framework/Service/Sessions/ISessionService.cs +++ b/Code/Sif3Framework/Sif.Framework/Service/Sessions/ISessionService.cs @@ -1,12 +1,12 @@ /* - * Copyright 2018 Systemic Pty Ltd - * + * Copyright 2021 Systemic Pty Ltd + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,34 +16,41 @@ namespace Sif.Framework.Service.Sessions { - /// /// This interface represents operations associated with SIF Framework sessions. /// public interface ISessionService { - /// - /// Check whether a session entry already exists (based on the passed citeria parameters). + /// Check whether a session entry already exists (based on the passed criteria parameters). /// /// Application key. /// Solution ID. /// User token. /// Instance ID. /// True if a session entry already exists; false otherwise. - bool HasSession(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null); + /// applicationKey is null. + bool HasSession( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null); /// /// Check whether a session entry already exists (based on the passed session token). /// /// Session token. /// True if a session entry already exists; false otherwise. - bool HasSession(string sessionToken); + /// sessionToken is null. + bool HasSessionToken(string sessionToken); /// - /// Remove a session entry. If no entry exists, this method does nothing. + /// Remove a session entry. /// /// Session token associated with the session entry. + /// sessionToken is null. + /// Multiple session entries exist for the session token. + /// No session entry exists for the session token. void RemoveSession(string sessionToken); /// @@ -54,7 +61,13 @@ public interface ISessionService /// User token. /// Instance ID. /// Environment URL of the matched session entry; null if no match found. - string RetrieveEnvironmentUrl(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null); + /// applicationKey is null. + /// Multiple session entries exist for the passed criteria parameters. + string RetrieveEnvironmentUrl( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null); /// /// Retrieve the Queue unique identifier of a session entry that matches the passed criteria parameters. @@ -64,7 +77,13 @@ public interface ISessionService /// User token. /// Instance ID. /// Queue unique identifier of the matched session entry; null if no match found. - string RetrieveQueueId(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null); + /// applicationKey is null. + /// Multiple session entries exist for the passed criteria parameters. + string RetrieveQueueId( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null); /// /// Retrieve the session token of a session entry that matches the passed criteria parameters. @@ -74,7 +93,13 @@ public interface ISessionService /// User token. /// Instance ID. /// Session token of the matched session entry; null if no match found. - string RetrieveSessionToken(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null); + /// applicationKey is null. + /// Multiple session entries exist for the passed criteria parameters. + string RetrieveSessionToken( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null); /// /// Retrieve the Subscription unique identifier of a session entry that matches the passed criteria parameters. @@ -84,7 +109,13 @@ public interface ISessionService /// User token. /// Instance ID. /// Subscription unique identifier of the matched session entry; null if no match found. - string RetrieveSubscriptionId(string applicationKey, string solutionId = null, string userToken = null, string instanceId = null); + /// applicationKey is null. + /// Multiple session entries exist for the passed criteria parameters. + string RetrieveSubscriptionId( + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null); /// /// Store a session entry associated with Consumer/Provider registration. @@ -95,7 +126,15 @@ public interface ISessionService /// Solution ID. /// User token. /// Instance ID. - void StoreSession(string applicationKey, string sessionToken, string environmentUrl, string solutionId = null, string userToken = null, string instanceId = null); + /// A session entry already exists for the applicationKey/solutionId/userToken/instanceId combination and/or sessionToken specified. + /// applicationKey, sessionToken and/or environmentUrl are null. + void StoreSession( + string applicationKey, + string sessionToken, + string environmentUrl, + string solutionId = null, + string userToken = null, + string instanceId = null); /// /// Update the Queue unique identifier associated with a session entry. @@ -105,7 +144,15 @@ public interface ISessionService /// Solution ID. /// User token. /// Instance ID. - void UpdateQueueId(string queueId, string applicationKey, string solutionId = null, string userToken = null, string instanceId = null); + /// queueId and/or applicationKey are null. + /// Multiple session entries exist for the passed criteria parameters. + /// No session entry exists for the passed criteria parameters. + void UpdateQueueId( + string queueId, + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null); /// /// Update the Subscription unique identifier associated with a session entry. @@ -115,8 +162,14 @@ public interface ISessionService /// Solution ID. /// User token. /// Instance ID. - void UpdateSubscriptionId(string subscriptionId, string applicationKey, string solutionId = null, string userToken = null, string instanceId = null); - + /// subscriptionId and/or applicationKey are null. + /// Multiple session entries exist for the passed criteria parameters. + /// No session entry exists for the passed criteria parameters. + void UpdateSubscriptionId( + string subscriptionId, + string applicationKey, + string solutionId = null, + string userToken = null, + string instanceId = null); } - -} +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework/Sif.Framework.csproj b/Code/Sif3Framework/Sif.Framework/Sif.Framework.csproj index 30e741c5..b79d1cb0 100644 --- a/Code/Sif3Framework/Sif.Framework/Sif.Framework.csproj +++ b/Code/Sif3Framework/Sif.Framework/Sif.Framework.csproj @@ -2,12 +2,12 @@ netstandard2.0;net472;net461 - 4.0.0 + 5.0.0 Rafidzal Rafiq Systemic Pty Ltd SIF Framework library Core library of the SIF Framework based on SIF Infrastructure 3.2.1. - Copyright © Systemic Pty Ltd 2020 + Copyright © Systemic Pty Ltd 2021 Apache-2.0 https://github.com/nsip/sif3-framework-dotnet https://github.com/nsip/sif3-framework-dotnet diff --git a/Code/Sif3Framework/Sif.Framework/Utils/ProviderUtils.cs b/Code/Sif3Framework/Sif.Framework/Utils/ProviderUtils.cs index c139dc45..d05fa565 100644 --- a/Code/Sif3Framework/Sif.Framework/Utils/ProviderUtils.cs +++ b/Code/Sif3Framework/Sif.Framework/Utils/ProviderUtils.cs @@ -1,6 +1,21 @@ -using Sif.Framework.Controllers; +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Sif.Framework.Controllers; using Sif.Framework.Extensions; -using Sif.Framework.Model.Exceptions; using Sif.Framework.Providers; using Sif.Framework.Service; using Sif.Framework.Service.Functional; @@ -8,13 +23,12 @@ using System; using System.Net; using System.Web.Http.Controllers; +using Tardigrade.Framework.Exceptions; namespace Sif.Framework.Utils { - public class ProviderUtils { - /// /// Infer the name of the Object/Functional Service type /// @@ -22,18 +36,21 @@ public static string GetServiceName(IService service) { try { - if (isFunctionalService(service.GetType())) + if (IsFunctionalService(service.GetType())) { return ((IFunctionalService)service).GetServiceName(); } - if (isDataModelService(service.GetType())) + if (IsDataModelService(service.GetType())) { return service.GetType().GenericTypeArguments[0].Name; } } - catch(Exception e) { - throw new NotFoundException("Could not infer the name of the service with type " + service.GetType().Name, e); + catch (Exception e) + { + throw new NotFoundException( + "Could not infer the name of the service with type " + service.GetType().Name, + e); } throw new NotFoundException("Could not infer the name of the service with type " + service.GetType().Name); @@ -44,14 +61,14 @@ public static string GetServiceName(IService service) /// /// The type to check /// See def. - public static Boolean isFunctionalService(Type type) + public static bool IsFunctionalService(Type type) { if (type == null) { - throw new ArgumentNullException("Argument type cannot be null"); + throw new ArgumentNullException(nameof(type)); } - Boolean isFService = type.IsClass + bool isFService = type.IsClass && type.IsVisible && !type.IsAbstract && typeof(IFunctionalService).IsAssignableFrom(type); @@ -64,15 +81,15 @@ public static Boolean isFunctionalService(Type type) /// /// The type to check /// See def. - public static Boolean isDataModelService(Type type) + public static bool IsDataModelService(Type type) { if (type == null) { - throw new ArgumentNullException("Argument type cannot be null"); + throw new ArgumentNullException(nameof(type)); } return type.IsClass - && type.IsVisible + && type.IsVisible && !type.IsAbstract && type.IsAssignableToGenericType(typeof(IObjectService<,,>)); } @@ -82,14 +99,14 @@ public static Boolean isDataModelService(Type type) /// /// The type to check /// See def. - public static Boolean isController(Type type) + public static bool IsController(Type type) { if (type == null) { - throw new ArgumentNullException("Argument type cannot be null"); + throw new ArgumentNullException(nameof(type)); } - Boolean iscontroller = type.IsClass && + bool isController = type.IsClass && type.IsVisible && !type.IsAbstract && (type.IsAssignableToGenericType(typeof(IProvider<,,>)) || @@ -97,8 +114,8 @@ public static Boolean isController(Type type) typeof(FunctionalServiceProvider).IsAssignableFrom(type)) && typeof(IHttpController).IsAssignableFrom(type) && type.Name.EndsWith("Provider"); - - return iscontroller; + + return isController; } /// @@ -106,7 +123,7 @@ public static Boolean isController(Type type) /// /// The Guid instance to check. /// See def. - public static Boolean IsAdvisoryId(Guid id) + public static bool IsAdvisoryId(Guid id) { return StringUtils.NotEmpty(id) && Guid.Empty != id; } @@ -116,7 +133,7 @@ public static Boolean IsAdvisoryId(Guid id) /// /// The string representation of a Guid to check. /// See def. - public static Boolean IsAdvisoryId(string id) + public static bool IsAdvisoryId(string id) { return StringUtils.NotEmpty(id) && Guid.Empty != Guid.Parse(id); } @@ -130,10 +147,7 @@ public static Boolean IsAdvisoryId(string id) /// Error record. public static errorType CreateError(HttpStatusCode statusCode, string scope, string message = null) { - errorType error = new errorType(); - error.id = Guid.NewGuid().ToString(); - error.code = (uint)statusCode; - error.scope = scope; + var error = new errorType { id = Guid.NewGuid().ToString(), code = (uint)statusCode, scope = scope }; if (!string.IsNullOrWhiteSpace(message)) { @@ -143,60 +157,65 @@ public static errorType CreateError(HttpStatusCode statusCode, string scope, str return error; } - public static createType CreateCreate(HttpStatusCode statusCode, string id, string advisoryId = null, errorType error = null) + public static createType CreateCreate( + HttpStatusCode statusCode, + string id, + string advisoryId = null, + errorType error = null) { - createType create = new createType(); - create.statusCode = ((int)statusCode).ToString(); - create.id = id; + var create = new createType { statusCode = ((int)statusCode).ToString(), id = id }; + if (StringUtils.NotEmpty(advisoryId)) { create.advisoryId = advisoryId; } + if (error != null) { create.error = error; } + return create; } public static createResponseType CreateCreateResponse(createType[] creates) { - createResponseType createResponse = new createResponseType(); - createResponse.creates = creates; + var createResponse = new createResponseType { creates = creates }; + return createResponse; } public static createResponseType CreateCreateResponse(createType create) { - createResponseType createResponse = new createResponseType(); - createResponse.creates = new createType[] { create } ; + var createResponse = new createResponseType { creates = new[] { create } }; + return createResponse; } public static deleteStatus CreateDelete(HttpStatusCode statusCode, string id, errorType error = null) { - deleteStatus status = new deleteStatus(); - status.statusCode = ((int)statusCode).ToString(); - status.id = id; + var status = new deleteStatus { statusCode = ((int)statusCode).ToString(), id = id }; + if (error != null) { status.error = error; } + return status; } public static deleteResponseType CreateDeleteResponse(deleteStatus[] statuses) { - deleteResponseType deleteResponse = new deleteResponseType(); - deleteResponse.deletes = statuses; + var deleteResponse = new deleteResponseType { deletes = statuses }; + return deleteResponse; } public static deleteResponseType CreateDeleteResponse(deleteStatus status) { - deleteResponseType deleteResponse = new deleteResponseType(); - deleteResponse.deletes = new deleteStatus[] { status }; + var deleteResponse = new deleteResponseType { deletes = new[] { status } }; + return deleteResponse; } } -} +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework/Utils/SessionsManager.cs b/Code/Sif3Framework/Sif.Framework/Utils/SessionsManager.cs index f44ed919..d80a65cf 100644 --- a/Code/Sif3Framework/Sif.Framework/Utils/SessionsManager.cs +++ b/Code/Sif3Framework/Sif.Framework/Utils/SessionsManager.cs @@ -1,12 +1,12 @@ /* - * Copyright 2015 Systemic Pty Ltd - * + * Copyright 2021 Systemic Pty Ltd + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,7 +18,6 @@ namespace Sif.Framework.Utils { - /// /// Factory class to ensure that the appropriate session service is provided. /// @@ -30,41 +29,13 @@ public static class SessionsManager /// /// Singleton instance of the Consumer session service. /// - public static ISessionService ConsumerSessionService - { - - get - { - - if (consumerSessionService == null) - { - consumerSessionService = new ConsumerSessionService(); - } - - return consumerSessionService; - } - - } + public static ISessionService ConsumerSessionService => + consumerSessionService ?? (consumerSessionService = new ConsumerSessionService()); /// /// Singleton instance of the Provider session service. /// - public static ISessionService ProviderSessionService - { - - get - { - - if (providerSessionService == null) - { - providerSessionService = new ProviderSessionService(); - } - - return providerSessionService; - } - - } - + public static ISessionService ProviderSessionService => + providerSessionService ?? (providerSessionService = new ProviderSessionService()); } - -} +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif.Framework/WebApi/ServiceProviderHttpControllerTypeResolver.cs b/Code/Sif3Framework/Sif.Framework/WebApi/ServiceProviderHttpControllerTypeResolver.cs index dc5f3860..2ea90348 100644 --- a/Code/Sif3Framework/Sif.Framework/WebApi/ServiceProviderHttpControllerTypeResolver.cs +++ b/Code/Sif3Framework/Sif.Framework/WebApi/ServiceProviderHttpControllerTypeResolver.cs @@ -1,12 +1,12 @@ /* - * Copyright 2016 Systemic Pty Ltd - * + * Copyright 2021 Systemic Pty Ltd + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,29 +14,23 @@ * limitations under the License. */ -using Sif.Framework.Controllers; -using Sif.Framework.Extensions; -using Sif.Framework.Providers; using Sif.Framework.Utils; using System; -using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; namespace Sif.Framework.WebApi { - /// /// Controller type resolver that recognises SIF Service Providers. /// public class ServiceProviderHttpControllerTypeResolver : DefaultHttpControllerTypeResolver { - /// /// Default constructor. /// - public ServiceProviderHttpControllerTypeResolver() - : base(IsHttpEndpoint) - { } + public ServiceProviderHttpControllerTypeResolver() : base(IsHttpEndpoint) + { + } /// /// Check whether the specified type defines a Controller endpoint. @@ -45,9 +39,7 @@ public ServiceProviderHttpControllerTypeResolver() /// True if the endpoint defines a Controller; false otherwise. internal static bool IsHttpEndpoint(Type type) { - return ProviderUtils.isController(type); + return ProviderUtils.IsController(type); } - } - -} +} \ No newline at end of file diff --git a/Code/Sif3Framework/Sif3Framework.sln b/Code/Sif3Framework/Sif3Framework.sln index 28c5e303..ac387193 100644 --- a/Code/Sif3Framework/Sif3Framework.sln +++ b/Code/Sif3Framework/Sif3Framework.sln @@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sif.Framework", "Sif.Framew EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sif.Framework.Tests", "Sif.Framework.Tests\Sif.Framework.Tests.csproj", "{D8C0E0E8-B96F-42D5-9FB0-8D055546E308}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sif.Framework.EntityFramework", "Sif.Framework.EntityFramework\Sif.Framework.EntityFramework.csproj", "{2D6ECE58-528F-4340-A18B-4947C15E8B35}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {D8C0E0E8-B96F-42D5-9FB0-8D055546E308}.Debug|Any CPU.Build.0 = Debug|Any CPU {D8C0E0E8-B96F-42D5-9FB0-8D055546E308}.Release|Any CPU.ActiveCfg = Release|Any CPU {D8C0E0E8-B96F-42D5-9FB0-8D055546E308}.Release|Any CPU.Build.0 = Release|Any CPU + {2D6ECE58-528F-4340-A18B-4947C15E8B35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D6ECE58-528F-4340-A18B-4947C15E8B35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D6ECE58-528F-4340-A18B-4947C15E8B35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D6ECE58-528F-4340-A18B-4947C15E8B35}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/App.config b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/App.config index fe5a4a4a..13617cb4 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/App.config +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/App.config @@ -6,8 +6,7 @@
- - + diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/ConsoleApp.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/ConsoleApp.cs new file mode 100644 index 00000000..078f1cd0 --- /dev/null +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/ConsoleApp.cs @@ -0,0 +1,104 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Sif.Framework.EntityFramework.Data; +using Sif.Framework.EntityFramework.Services.Sessions; +using Sif.Framework.Model.Sessions; +using Sif.Framework.Model.Settings; +using Sif.Framework.Service.Sessions; +using Sif.Framework.Settings; +using Sif.Framework.Utils; +using System; +using System.Data.Entity; +using Tardigrade.Framework.Configurations; +using Tardigrade.Framework.EntityFramework; +using Tardigrade.Framework.EntityFramework.Configurations; +using Tardigrade.Framework.Persistence; +using Tardigrade.Framework.Services; + +namespace Sif.Framework.Demo.Au.Consumer +{ + internal abstract class ConsoleApp + { + protected enum SettingsSource { Database, File } + + protected static ISessionService GetSessionService(SettingsSource source) + { + ISessionService sessionService; + + switch (source) + { + case SettingsSource.Database: + DbContext dbContext = new SessionDbContext("name=FrameworkConfigDb"); + IRepository repository = new Repository(dbContext); + IObjectService service = new ObjectService(repository); + sessionService = new SessionService(service); + break; + + case SettingsSource.File: + sessionService = SessionsManager.ConsumerSessionService; + break; + + default: + sessionService = SessionsManager.ConsumerSessionService; + break; + } + + return sessionService; + } + + protected static IFrameworkSettings GetSettings(SettingsSource source) + { + IFrameworkSettings settings; + + switch (source) + { + case SettingsSource.Database: + settings = new ConsumerSettings( + new ApplicationConfiguration(new AppSettingsConfigurationSource("name=FrameworkConfigDb"))); + break; + + case SettingsSource.File: + settings = SettingsManager.ConsumerSettings; + break; + + default: + settings = SettingsManager.ConsumerSettings; + break; + } + + return settings; + } + + protected static SettingsSource SelectFrameworkConfigSource() + { + Console.WriteLine(); + Console.Write( + "Would you like to read the application settings and session token from the SifFramework.config (F)ile or from the SifFrameworkConfig.db (D)atabase? Pressing enter defaults to (F)ile. - "); + ConsoleKeyInfo info; + + do + { + info = Console.ReadKey(); + } while (info.Key != ConsoleKey.D && info.Key != ConsoleKey.F && info.Key != ConsoleKey.Enter); + + Console.WriteLine(); + Console.WriteLine(); + + return info.Key == ConsoleKey.D ? SettingsSource.Database : SettingsSource.File; + } + } +} \ No newline at end of file diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/ConsumerApp.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/ConsumerApp.cs index 209225e7..a4d45357 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/ConsumerApp.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/ConsumerApp.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,38 +20,47 @@ using Sif.Framework.Model.Query; using Sif.Framework.Model.Responses; using Sif.Framework.Model.Settings; -using Sif.Framework.Settings; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Specification.DataModel.Au; using System; using System.Collections.Generic; using System.Linq; -using Tardigrade.Framework.Configurations; -using Tardigrade.Framework.EntityFramework.Configurations; namespace Sif.Framework.Demo.Au.Consumer { - internal class ConsumerApp + internal class ConsumerApp : ConsoleApp { - private static readonly slf4net.ILogger Log = slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private static readonly Random Random = new Random(); + private static readonly slf4net.ILogger Log = + slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private enum SettingsSource { Database, File } + private static readonly Random Random = new Random(); private static StudentPersonal CreateStudent() { - NameOfRecordType name = new NameOfRecordType { Type = NameOfRecordTypeType.LGL, FamilyName = RandomNameGenerator.FamilyName, GivenName = RandomNameGenerator.GivenName }; - PersonInfoType personInfo = new PersonInfoType { Name = name }; - StudentPersonal studentPersonal = new StudentPersonal { LocalId = Random.Next(10000, 99999).ToString(), PersonInfo = personInfo }; + var name = new NameOfRecordType + { + Type = NameOfRecordTypeType.LGL, + FamilyName = RandomNameGenerator.FamilyName, + GivenName = RandomNameGenerator.GivenName + }; + + var personInfo = new PersonInfoType { Name = name }; + + var studentPersonal = new StudentPersonal + { + LocalId = Random.Next(10000, 99999).ToString(), + PersonInfo = personInfo + }; return studentPersonal; } private static List CreateStudents(int count) { - List studentPersonalsCache = new List(); + var studentPersonalsCache = new List(); - for (int i = 1; i <= count; i++) + for (var i = 1; i <= count; i++) { studentPersonalsCache.Add(CreateStudent()); } @@ -59,62 +68,49 @@ private static List CreateStudents(int count) return studentPersonalsCache; } - private static IFrameworkSettings GetSettings(SettingsSource source) + private static void RunConsumer(IFrameworkSettings settings, ISessionService sessionService) { - IFrameworkSettings settings; - - switch (source) - { - case SettingsSource.Database: - settings = new ConsumerSettings(new ApplicationConfiguration(new AppSettingsConfigurationSource("name=SettingsDb"))); - break; - - case SettingsSource.File: - settings = SettingsManager.ConsumerSettings; - break; - - default: - settings = SettingsManager.ConsumerSettings; - break; - } - return settings; - } - - private static void RunStudentPersonalConsumer(IFrameworkSettings settings) - { - var studentPersonalConsumer = new StudentPersonalConsumer( + var consumer = new StudentPersonalConsumer( settings.ApplicationKey, settings.InstanceId, settings.UserToken, settings.SolutionId, - settings); - studentPersonalConsumer.Register(); + settings, + sessionService); + consumer.Register(); + if (Log.IsInfoEnabled) Log.Info("Registered the Consumer."); try { - IEnumerable queriedStudents = studentPersonalConsumer.DynamicQuery("[@id=1234]"); + IEnumerable queriedStudents = consumer.DynamicQuery("[@id=1234]"); foreach (StudentPersonal student in queriedStudents) { - if (Log.IsInfoEnabled) Log.Info("Queried student name is " + student.PersonInfo.Name.GivenName + " " + student.PersonInfo.Name.FamilyName); + if (Log.IsInfoEnabled) + Log.Info($"Queried student name is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } // Retrieve Bart Simpson using QBE. + if (Log.IsInfoEnabled) Log.Info("*** Retrieve Bart Simpson using QBE."); - NameOfRecordType name = new NameOfRecordType { FamilyName = "Simpson", GivenName = "Bart" }; - PersonInfoType personInfo = new PersonInfoType { Name = name }; - StudentPersonal studentPersonal = new StudentPersonal { PersonInfo = personInfo }; - IEnumerable filteredStudents = studentPersonalConsumer.QueryByExample(studentPersonal); + + var name = new NameOfRecordType { FamilyName = "Simpson", GivenName = "Bart" }; + var personInfo = new PersonInfoType { Name = name }; + var studentPersonal = new StudentPersonal { PersonInfo = personInfo }; + IEnumerable filteredStudents = consumer.QueryByExample(studentPersonal); foreach (StudentPersonal student in filteredStudents) { - if (Log.IsInfoEnabled) Log.Info("Filtered student name is " + student.PersonInfo.Name.GivenName + " " + student.PersonInfo.Name.FamilyName); + if (Log.IsInfoEnabled) + Log.Info($"Filtered student name is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } // Create a new student. + if (Log.IsInfoEnabled) Log.Info("*** Create a new student."); - string[] text = new string[] + + var text = new[] { @" @@ -125,40 +121,66 @@ private static void RunStudentPersonalConsumer(IFrameworkSettings settings) " }; - SIF_ExtendedElementsTypeSIF_ExtendedElement extendedElement = new SIF_ExtendedElementsTypeSIF_ExtendedElement { Name = "MedicalConditions", Text = text }; - SIF_ExtendedElementsTypeSIF_ExtendedElement[] extendedElements = new SIF_ExtendedElementsTypeSIF_ExtendedElement[] { extendedElement }; - NameOfRecordType newStudentName = new NameOfRecordType { FamilyName = "Wayne", GivenName = "Bruce", Type = NameOfRecordTypeType.LGL }; - PersonInfoType newStudentInfo = new PersonInfoType { Name = newStudentName }; - string studentID = Guid.NewGuid().ToString(); - StudentPersonal newStudent = new StudentPersonal { RefId = studentID, LocalId = "555", PersonInfo = newStudentInfo, SIF_ExtendedElements = extendedElements }; + + var extendedElement = new SIF_ExtendedElementsTypeSIF_ExtendedElement + { + Name = "MedicalConditions", + Text = text + }; + + SIF_ExtendedElementsTypeSIF_ExtendedElement[] extendedElements = { extendedElement }; + + var newStudentName = new NameOfRecordType + { + FamilyName = "Wayne", + GivenName = "Bruce", + Type = NameOfRecordTypeType.LGL + }; + + var newStudentInfo = new PersonInfoType { Name = newStudentName }; + + var newStudent = new StudentPersonal + { + RefId = Guid.NewGuid().ToString(), + LocalId = "555", + PersonInfo = newStudentInfo, + SIF_ExtendedElements = extendedElements + }; try { - StudentPersonal retrievedNewStudent = studentPersonalConsumer.Create(newStudent, true); - if (Log.IsInfoEnabled) Log.Info($"Created new student {newStudent.PersonInfo.Name.GivenName} {newStudent.PersonInfo.Name.FamilyName} with ID of {studentID}."); + StudentPersonal retrievedNewStudent = consumer.Create(newStudent, true); + + if (Log.IsInfoEnabled) + Log.Info($"Created new student {newStudent.PersonInfo.Name.GivenName} {newStudent.PersonInfo.Name.FamilyName} with ID of {retrievedNewStudent.RefId}."); } catch (UnauthorizedAccessException) { - if (Log.IsInfoEnabled) Log.Info($"Access to create a new student is rejected."); + if (Log.IsInfoEnabled) Log.Info("Access to create a new student is rejected."); } // Create multiple new students. + if (Log.IsInfoEnabled) Log.Info("*** Create multiple new students."); + List newStudents = CreateStudents(5); try { - MultipleCreateResponse multipleCreateResponse = studentPersonalConsumer.Create(newStudents); - int count = 0; + MultipleCreateResponse multipleCreateResponse = consumer.Create(newStudents); + var count = 0; foreach (CreateStatus status in multipleCreateResponse.StatusRecords) { if (Log.IsInfoEnabled) Log.Info("Create status code is " + status.StatusCode); + newStudents[count++].RefId = status.Id; } // Update multiple students. + if (Log.IsInfoEnabled) Log.Info("*** Update multiple students."); + foreach (StudentPersonal student in newStudents) { student.PersonInfo.Name.GivenName += "o"; @@ -166,7 +188,7 @@ private static void RunStudentPersonalConsumer(IFrameworkSettings settings) try { - MultipleUpdateResponse multipleUpdateResponse = studentPersonalConsumer.Update(newStudents); + MultipleUpdateResponse multipleUpdateResponse = consumer.Update(newStudents); foreach (UpdateStatus status in multipleUpdateResponse.StatusRecords) { @@ -175,21 +197,19 @@ private static void RunStudentPersonalConsumer(IFrameworkSettings settings) } catch (UnauthorizedAccessException) { - if (Log.IsInfoEnabled) Log.Info($"Access to update multiple students is rejected."); + if (Log.IsInfoEnabled) Log.Info("Access to update multiple students is rejected."); } // Delete multiple students. + if (Log.IsInfoEnabled) Log.Info("*** Delete multiple students."); - ICollection refIds = new List(); - foreach (CreateStatus status in multipleCreateResponse.StatusRecords) - { - refIds.Add(status.Id); - } + ICollection refIds = + multipleCreateResponse.StatusRecords.Select(status => status.Id).ToList(); try { - MultipleDeleteResponse multipleDeleteResponse = studentPersonalConsumer.Delete(refIds); + MultipleDeleteResponse multipleDeleteResponse = consumer.Delete(refIds); foreach (DeleteStatus status in multipleDeleteResponse.StatusRecords) { @@ -198,111 +218,135 @@ private static void RunStudentPersonalConsumer(IFrameworkSettings settings) } catch (UnauthorizedAccessException) { - if (Log.IsInfoEnabled) Log.Info($"Access to delete multiple students is rejected."); + if (Log.IsInfoEnabled) Log.Info("Access to delete multiple students is rejected."); } } catch (UnauthorizedAccessException) { - if (Log.IsInfoEnabled) Log.Info($"Access to create multiple new students is rejected."); + if (Log.IsInfoEnabled) Log.Info("Access to create multiple new students is rejected."); } // Retrieve all students from zone "Gov" and context "Curr". + if (Log.IsInfoEnabled) Log.Info("*** Retrieve all students from zone \"Gov\" and context \"Curr\"."); - IEnumerable students = studentPersonalConsumer.Query(zoneId: "Gov", contextId: "Curr"); + + IEnumerable students = consumer.Query(zoneId: "Gov", contextId: "Curr"); foreach (StudentPersonal student in students) { - if (Log.IsInfoEnabled) Log.Info("Student name is " + student.PersonInfo.Name.GivenName + " " + student.PersonInfo.Name.FamilyName); + if (Log.IsInfoEnabled) + Log.Info($"Student name is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } if (students.Count() > 1) { // Retrieve a single student. + if (Log.IsInfoEnabled) Log.Info("*** Retrieve a single student."); + string studentId = students.ElementAt(1).RefId; - StudentPersonal secondStudent = studentPersonalConsumer.Query(studentId); - if (Log.IsInfoEnabled) Log.Info("Name of second student is " + secondStudent.PersonInfo.Name.GivenName + " " + secondStudent.PersonInfo.Name.FamilyName); + StudentPersonal secondStudent = consumer.Query(studentId); + if (Log.IsInfoEnabled) + Log.Info($"Name of second student is {secondStudent.PersonInfo.Name.GivenName} {secondStudent.PersonInfo.Name.FamilyName}."); // Update that student and confirm. + if (Log.IsInfoEnabled) Log.Info("*** Update that student and confirm."); + secondStudent.PersonInfo.Name.GivenName = "Homer"; secondStudent.PersonInfo.Name.FamilyName = "Simpson"; try { - studentPersonalConsumer.Update(secondStudent); - secondStudent = studentPersonalConsumer.Query(studentId); - if (Log.IsInfoEnabled) Log.Info("Name of second student has been changed to " + secondStudent.PersonInfo.Name.GivenName + " " + secondStudent.PersonInfo.Name.FamilyName); + consumer.Update(secondStudent); + secondStudent = consumer.Query(studentId); + + if (Log.IsInfoEnabled) + Log.Info($"Name of second student has been changed to {secondStudent.PersonInfo.Name.GivenName} {secondStudent.PersonInfo.Name.FamilyName}."); } catch (UnauthorizedAccessException) { - if (Log.IsInfoEnabled) Log.Info($"Access to update a student is rejected."); + if (Log.IsInfoEnabled) Log.Info("Access to update a student is rejected."); } // Delete that student and confirm. + if (Log.IsInfoEnabled) Log.Info("*** Delete that student and confirm."); try { - studentPersonalConsumer.Delete(studentId); - StudentPersonal deletedStudent = studentPersonalConsumer.Query(studentId); - bool studentDeleted = (deletedStudent == null ? true : false); + consumer.Delete(studentId); + StudentPersonal deletedStudent = consumer.Query(studentId); + bool studentDeleted = deletedStudent == null; if (studentDeleted) { - if (Log.IsInfoEnabled) Log.Info("Student " + secondStudent.PersonInfo.Name.GivenName + " " + secondStudent.PersonInfo.Name.FamilyName + " was successfully deleted."); + if (Log.IsInfoEnabled) + Log.Info($"Student {secondStudent.PersonInfo.Name.GivenName} {secondStudent.PersonInfo.Name.FamilyName} was successfully deleted."); } else { - if (Log.IsInfoEnabled) Log.Info("Student " + secondStudent.PersonInfo.Name.GivenName + " " + secondStudent.PersonInfo.Name.FamilyName + " was NOT deleted."); + if (Log.IsInfoEnabled) + Log.Info($"Student {secondStudent.PersonInfo.Name.GivenName} {secondStudent.PersonInfo.Name.FamilyName} was NOT deleted."); } } catch (UnauthorizedAccessException) { - if (Log.IsInfoEnabled) Log.Info($"Access to delete a student is rejected."); + if (Log.IsInfoEnabled) Log.Info("Access to delete a student is rejected."); } } // Retrieve students based on Teaching Group using Service Paths. + if (Log.IsInfoEnabled) Log.Info("*** Retrieve students based on Teaching Group using Service Paths."); - EqualCondition condition = new EqualCondition() { Left = "TeachingGroups", Right = "597ad3fe-47e7-4b2c-b919-a93c564d19d0" }; - IList conditions = new List + + var condition = new EqualCondition() { - condition + Left = "TeachingGroups", + Right = "597ad3fe-47e7-4b2c-b919-a93c564d19d0" }; + IList conditions = new List { condition }; + try { - IEnumerable teachingGroupStudents = studentPersonalConsumer.QueryByServicePath(conditions); + IEnumerable teachingGroupStudents = consumer.QueryByServicePath(conditions); foreach (StudentPersonal student in teachingGroupStudents) { - if (Log.IsInfoEnabled) Log.Info("Student name is " + student.PersonInfo.Name.GivenName + " " + student.PersonInfo.Name.FamilyName); + if (Log.IsInfoEnabled) + Log.Info($"Student name is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); + + if (student.SIF_ExtendedElements == null || student.SIF_ExtendedElements.Length <= 0) continue; - if (student.SIF_ExtendedElements != null && student.SIF_ExtendedElements.Length > 0) + foreach (SIF_ExtendedElementsTypeSIF_ExtendedElement element in student.SIF_ExtendedElements) { - foreach (SIF_ExtendedElementsTypeSIF_ExtendedElement element in student.SIF_ExtendedElements) + foreach (string content in element.Text) { - foreach (string content in element.Text) - { - if (Log.IsInfoEnabled) Log.Info("Extended element text is ...\n" + content); - } + if (Log.IsInfoEnabled) Log.Info($"Extended element text is ...\n{content}"); } } } } catch (UnauthorizedAccessException) { - if (Log.IsInfoEnabled) Log.Info("Access to query students by Service Path TeachingGroups/{}/StudentPersonals is rejected."); + if (Log.IsInfoEnabled) + Log.Info("Access to query students by Service Path TeachingGroups/{}/StudentPersonals is rejected."); } // Retrieve student changes since a particular point as defined by the Changes Since marker. - if (Log.IsInfoEnabled) Log.Info("*** Retrieve student changes since a particular point as defined by the Changes Since marker."); - string changesSinceMarker = studentPersonalConsumer.GetChangesSinceMarker(); - IEnumerable changedStudents = studentPersonalConsumer.QueryChangesSince(changesSinceMarker, out string nextChangesSinceMarker); - if (Log.IsInfoEnabled) Log.Info("Iteration 1 - Student changes based on Changes Since marker - " + changesSinceMarker); - if (changedStudents == null || changedStudents.Count() == 0) + if (Log.IsInfoEnabled) + Log.Info("*** Retrieve student changes since a particular point as defined by the Changes Since marker."); + + string changesSinceMarker = consumer.GetChangesSinceMarker(); + IEnumerable changedStudents = + consumer.QueryChangesSince(changesSinceMarker, out string nextChangesSinceMarker); + + if (Log.IsInfoEnabled) + Log.Info($"Iteration 1 - Student changes based on Changes Since marker - {changesSinceMarker}"); + + if (changedStudents == null || !changedStudents.Any()) { if (Log.IsInfoEnabled) Log.Info("No student changes"); } @@ -310,16 +354,18 @@ private static void RunStudentPersonalConsumer(IFrameworkSettings settings) { foreach (StudentPersonal student in changedStudents) { - if (Log.IsInfoEnabled) Log.Info("Student name is " + student.PersonInfo.Name.GivenName + " " + student.PersonInfo.Name.FamilyName); + if (Log.IsInfoEnabled) + Log.Info($"Student name is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } } changesSinceMarker = nextChangesSinceMarker; - nextChangesSinceMarker = null; - changedStudents = studentPersonalConsumer.QueryChangesSince(changesSinceMarker, out nextChangesSinceMarker); - if (Log.IsInfoEnabled) Log.Info("Iteration 2 - Student changes based on Changes Since marker - " + changesSinceMarker); + changedStudents = consumer.QueryChangesSince(changesSinceMarker, out nextChangesSinceMarker); + + if (Log.IsInfoEnabled) + Log.Info($"Iteration 2 - Student changes based on Changes Since marker - {changesSinceMarker}"); - if (changedStudents == null || changedStudents.Count() == 0) + if (changedStudents == null || !changedStudents.Any()) { if (Log.IsInfoEnabled) Log.Info("No student changes"); } @@ -327,16 +373,18 @@ private static void RunStudentPersonalConsumer(IFrameworkSettings settings) { foreach (StudentPersonal student in changedStudents) { - if (Log.IsInfoEnabled) Log.Info("Student name is " + student.PersonInfo.Name.GivenName + " " + student.PersonInfo.Name.FamilyName); + if (Log.IsInfoEnabled) + Log.Info($"Student name is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } } changesSinceMarker = nextChangesSinceMarker; - nextChangesSinceMarker = null; - changedStudents = studentPersonalConsumer.QueryChangesSince(changesSinceMarker, out nextChangesSinceMarker); - if (Log.IsInfoEnabled) Log.Info("Iteration 3 - Student changes based on Changes Since marker - " + changesSinceMarker); + changedStudents = consumer.QueryChangesSince(changesSinceMarker, out nextChangesSinceMarker); - if (changedStudents == null || changedStudents.Count() == 0) + if (Log.IsInfoEnabled) + Log.Info($"Iteration 3 - Student changes based on Changes Since marker - {changesSinceMarker}"); + + if (changedStudents == null || !changedStudents.Any()) { if (Log.IsInfoEnabled) Log.Info("No student changes"); } @@ -344,52 +392,43 @@ private static void RunStudentPersonalConsumer(IFrameworkSettings settings) { foreach (StudentPersonal student in changedStudents) { - if (Log.IsInfoEnabled) Log.Info("Student name is " + student.PersonInfo.Name.GivenName + " " + student.PersonInfo.Name.FamilyName); + if (Log.IsInfoEnabled) + Log.Info($"Student name is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } } } catch (UnauthorizedAccessException) { - if (Log.IsInfoEnabled) Log.Info($"Access to query students is rejected."); + if (Log.IsInfoEnabled) Log.Info("Access to query students is rejected."); } catch (Exception e) { - if (Log.IsErrorEnabled) Log.Error("Error running the StudentPersonal Consumer.\n" + ExceptionUtils.InferErrorResponseMessage(e), e); + if (Log.IsErrorEnabled) + Log.Error( + $"Error running the StudentPersonal Consumer.\n{ExceptionUtils.InferErrorResponseMessage(e)}", + e); } finally { - studentPersonalConsumer.Unregister(); - if (Log.IsInfoEnabled) Log.Info("Unregistered the Consumer."); - } - } - - private static SettingsSource SelectSettingsSource() - { - Console.WriteLine(); - Console.Write("Would you like to read the application settings from the SifFramework.config (F)ile or from the SifFrameworkConfig.db (D)atabase? Pressing enter defaults to (F)ile. - "); - ConsoleKeyInfo info; + consumer.Unregister(); - do - { - info = Console.ReadKey(); + if (Log.IsInfoEnabled) Log.Info("Unregistered the Consumer."); } - while (info.Key != ConsoleKey.D && info.Key != ConsoleKey.F && info.Key != ConsoleKey.Enter); - - Console.WriteLine(); - Console.WriteLine(); - - return info.Key == ConsoleKey.D ? SettingsSource.Database : SettingsSource.File; } - private static void Main() + public static void Main() { try { - RunStudentPersonalConsumer(GetSettings(SelectSettingsSource())); + SettingsSource source = SelectFrameworkConfigSource(); + RunConsumer(GetSettings(source), GetSessionService(source)); } catch (Exception e) { - if (Log.IsErrorEnabled) Log.Error("Error running the Student Personal CRUD Consumer.\n" + ExceptionUtils.InferErrorResponseMessage(e), e); + if (Log.IsErrorEnabled) + Log.Error( + $"Error running the Student Personal CRUD Consumer.\n{ExceptionUtils.InferErrorResponseMessage(e)}", + e); } Console.WriteLine("Press any key to continue ..."); diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentPersonalConsumer.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentPersonalConsumer.cs index 854e41d6..5e4637f5 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentPersonalConsumer.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentPersonalConsumer.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,26 +16,33 @@ using Sif.Framework.Consumers; using Sif.Framework.Demo.Au.Consumer.Models; +using Sif.Framework.Model.Infrastructure; using Sif.Framework.Model.Settings; +using Sif.Framework.Service.Sessions; namespace Sif.Framework.Demo.Au.Consumer.Consumers { + /// internal class StudentPersonalConsumer : BasicConsumer { + /// public StudentPersonalConsumer( - Model.Infrastructure.Environment environment, - IFrameworkSettings settings = null) - : base(environment, settings) + Environment environment, + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(environment, settings, sessionService) { } + /// public StudentPersonalConsumer( string applicationKey, string instanceId = null, string userToken = null, string solutionId = null, - IFrameworkSettings settings = null) - : base(applicationKey, instanceId, userToken, solutionId, settings) + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(applicationKey, instanceId, userToken, solutionId, settings, sessionService) { } } diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentPersonalEventConsumer.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentPersonalEventConsumer.cs index 456a8a25..763d09cf 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentPersonalEventConsumer.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentPersonalEventConsumer.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,83 +16,102 @@ using Sif.Framework.Consumers; using Sif.Framework.Demo.Au.Consumer.Models; +using Sif.Framework.Model.Infrastructure; using Sif.Framework.Model.Responses; using Sif.Framework.Model.Settings; +using Sif.Framework.Service.Sessions; using System.Collections.Generic; namespace Sif.Framework.Demo.Au.Consumer.Consumers { + /// internal class StudentPersonalEventConsumer : BasicEventConsumer { - private readonly slf4net.ILogger log = + private static readonly slf4net.ILogger Log = slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + /// public StudentPersonalEventConsumer( - Model.Infrastructure.Environment environment, - IFrameworkSettings settings = null) - : base(environment, settings) + Environment environment, + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(environment, settings, sessionService) { } + /// public StudentPersonalEventConsumer( string applicationKey, string instanceId = null, string userToken = null, string solutionId = null, - IFrameworkSettings settings = null) - : base(applicationKey, instanceId, userToken, solutionId, settings) + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(applicationKey, instanceId, userToken, solutionId, settings, sessionService) { } - public override void OnCreateEvent(List objs, string zoneId = null, string contextId = null) + /// + public override void OnCreateEvent( + List students, + string zoneId = null, + string contextId = null) { - if (log.IsDebugEnabled) log.Debug("*** OnCreateEvent handler called ..."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Zone ID is {zoneId}."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Context ID is {contextId}."); + if (Log.IsDebugEnabled) Log.Debug("*** OnCreateEvent handler called ..."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Zone ID is {zoneId}."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Context ID is {contextId}."); - foreach (StudentPersonal student in objs) + foreach (StudentPersonal student in students) { - if (log.IsDebugEnabled) - log.Debug( + if (Log.IsDebugEnabled) + Log.Debug( $"*** >>> Student created is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } } - public override void OnDeleteEvent(List objs, string zoneId = null, string contextId = null) + /// + public override void OnDeleteEvent( + List students, + string zoneId = null, + string contextId = null) { - if (log.IsDebugEnabled) log.Debug("*** OnDeleteEvent handler called ..."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Zone ID is {zoneId}."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Context ID is {contextId}."); + if (Log.IsDebugEnabled) Log.Debug("*** OnDeleteEvent handler called ..."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Zone ID is {zoneId}."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Context ID is {contextId}."); - foreach (StudentPersonal student in objs) + foreach (StudentPersonal student in students) { - if (log.IsDebugEnabled) - log.Debug( + if (Log.IsDebugEnabled) + Log.Debug( $"*** >>> Student deleted is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } } + /// public override void OnErrorEvent(ResponseError error, string zoneId = null, string contextId = null) { - if (log.IsDebugEnabled) log.Debug("*** OnErrorEvent handler called ..."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Zone ID is {zoneId}."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Context ID is {contextId}."); - - if (log.IsDebugEnabled) log.Debug($"*** >>> Error: {error.Message}."); + if (Log.IsDebugEnabled) Log.Debug("*** OnErrorEvent handler called ..."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Zone ID is {zoneId}."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Context ID is {contextId}."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Error: {error.Message}."); } - public override void OnUpdateEvent(List objs, bool partialUpdate, string zoneId = null, + /// + public override void OnUpdateEvent( + List students, + bool partialUpdate, + string zoneId = null, string contextId = null) { - if (log.IsDebugEnabled) log.Debug("*** OnUpdateEvent handler called ..."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Partial update is {partialUpdate}."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Zone ID is {zoneId}."); - if (log.IsDebugEnabled) log.Debug($"*** >>> Context ID is {contextId}."); + if (Log.IsDebugEnabled) Log.Debug("*** OnUpdateEvent handler called ..."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Partial update is {partialUpdate}."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Zone ID is {zoneId}."); + if (Log.IsDebugEnabled) Log.Debug($"*** >>> Context ID is {contextId}."); - foreach (StudentPersonal student in objs) + foreach (StudentPersonal student in students) { - if (log.IsDebugEnabled) - log.Debug( + if (Log.IsDebugEnabled) + Log.Debug( $"*** >>> Student updated is {student.PersonInfo.Name.GivenName} {student.PersonInfo.Name.FamilyName}."); } } diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentSchoolEnrollmentConsumer.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentSchoolEnrollmentConsumer.cs index 0d428852..e77d2937 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentSchoolEnrollmentConsumer.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Consumers/StudentSchoolEnrollmentConsumer.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,26 +16,33 @@ using Sif.Framework.Consumers; using Sif.Framework.Demo.Au.Consumer.Models; +using Sif.Framework.Model.Infrastructure; using Sif.Framework.Model.Settings; +using Sif.Framework.Service.Sessions; namespace Sif.Framework.Demo.Au.Consumer.Consumers { + /// internal class StudentSchoolEnrollmentConsumer : BasicConsumer { + /// public StudentSchoolEnrollmentConsumer( - Model.Infrastructure.Environment environment, - IFrameworkSettings settings = null) - : base(environment, settings) + Environment environment, + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(environment, settings, sessionService) { } + /// public StudentSchoolEnrollmentConsumer( string applicationKey, string instanceId = null, string userToken = null, string solutionId = null, - IFrameworkSettings settings = null) - : base(applicationKey, instanceId, userToken, solutionId, settings) + IFrameworkSettings settings = null, + ISessionService sessionService = null) + : base(applicationKey, instanceId, userToken, solutionId, settings, sessionService) { } } diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/EnrollmentConsumerApp.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/EnrollmentConsumerApp.cs index 8bc1ca92..9ff54e2d 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/EnrollmentConsumerApp.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/EnrollmentConsumerApp.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ using Sif.Framework.Demo.Au.Consumer.Consumers; using Sif.Framework.Demo.Au.Consumer.Models; +using Sif.Framework.Model.Settings; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using Sif.Specification.DataModel.Au; using System; @@ -23,26 +25,31 @@ namespace Sif.Framework.Demo.Au.Consumer { - internal class EnrollmentConsumerApp + internal class EnrollmentConsumerApp : ConsoleApp { - private static readonly slf4net.ILogger log = slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly slf4net.ILogger Log = + slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private void RunConsumer() + private static void RunConsumer(IFrameworkSettings settings, ISessionService sessionService) { - StudentSchoolEnrollmentConsumer consumer = new StudentSchoolEnrollmentConsumer( - SettingsManager.ConsumerSettings.ApplicationKey, - SettingsManager.ConsumerSettings.InstanceId, - SettingsManager.ConsumerSettings.UserToken, - SettingsManager.ConsumerSettings.SolutionId, - SettingsManager.ConsumerSettings); + var consumer = new StudentSchoolEnrollmentConsumer( + settings.ApplicationKey, + settings.InstanceId, + settings.UserToken, + settings.SolutionId, + settings, + sessionService); consumer.Register(); - if (log.IsInfoEnabled) log.Info("Registered the Consumer."); + + if (Log.IsInfoEnabled) Log.Info("Registered the Consumer."); try { // Retrieve object using QBE. - if (log.IsInfoEnabled) log.Info("*** Retrieve object using QBE."); - StudentSchoolEnrollment enrollmentExample = new StudentSchoolEnrollment + + if (Log.IsInfoEnabled) Log.Info("*** Retrieve object using QBE."); + + var enrollmentExample = new StudentSchoolEnrollment { YearLevel = new YearLevelType @@ -55,35 +62,36 @@ private void RunConsumer() foreach (StudentSchoolEnrollment enrollment in filteredEnrollments) { - if (log.IsInfoEnabled) log.Info($"Filtered year level is {enrollment?.YearLevel.Code}"); + if (Log.IsInfoEnabled) Log.Info($"Filtered year level is {enrollment?.YearLevel.Code}"); } } catch (UnauthorizedAccessException) { - if (log.IsInfoEnabled) log.Info($"Access to query objects is rejected."); + if (Log.IsInfoEnabled) Log.Info("Access to query objects is rejected."); } catch (Exception e) { - if (log.IsErrorEnabled) log.Error("Error running the Consumer.\n" + ExceptionUtils.InferErrorResponseMessage(e), e); + if (Log.IsErrorEnabled) + Log.Error($"Error running the Consumer.\n{ExceptionUtils.InferErrorResponseMessage(e)}", e); } finally { consumer.Unregister(); - if (log.IsInfoEnabled) log.Info("Unregistered the Consumer."); + if (Log.IsInfoEnabled) Log.Info("Unregistered the Consumer."); } } - private static void Main(string[] args) + public static void Main() { - EnrollmentConsumerApp app = new EnrollmentConsumerApp(); - try { - app.RunConsumer(); + SettingsSource source = SelectFrameworkConfigSource(); + RunConsumer(GetSettings(source), GetSessionService(source)); } catch (Exception e) { - if (log.IsErrorEnabled) log.Error("Error running the Consumer.\n" + ExceptionUtils.InferErrorResponseMessage(e), e); + if (Log.IsErrorEnabled) + Log.Error($"Error running the Consumer.\n{ExceptionUtils.InferErrorResponseMessage(e)}", e); } Console.WriteLine("Press any key to continue ..."); diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/EventConsumerApp.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/EventConsumerApp.cs index e481566a..dd063c33 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/EventConsumerApp.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/EventConsumerApp.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,71 +15,71 @@ */ using Sif.Framework.Demo.Au.Consumer.Consumers; +using Sif.Framework.Model.Settings; +using Sif.Framework.Service.Sessions; using Sif.Framework.Utils; using System; namespace Sif.Framework.Demo.Au.Consumer { - internal class EventConsumerApp + internal class EventConsumerApp : ConsoleApp { - private static readonly slf4net.ILogger log = slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly slf4net.ILogger Log = + slf4net.LoggerFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private static bool RunDemo(string demoName) + public static void Main() { Console.WriteLine(); - Console.Write("Would you like run the " + demoName + " demo (Y/N)? - "); - ConsoleKeyInfo info = new ConsoleKeyInfo(); - - do - { - info = Console.ReadKey(); - } - while (info.Key != ConsoleKey.N && info.Key != ConsoleKey.Y && info.Key != ConsoleKey.Enter); - + Console.WriteLine("********************************************************************************"); Console.WriteLine(); + Console.WriteLine("To run this Event Consumer demo, the following steps are required."); Console.WriteLine(); - - return (info.Key == ConsoleKey.Y); - } - - private static void Main(string[] args) - { + Console.WriteLine(" 1) In the demo Consumer project:"); + Console.WriteLine(" 1.1) Set the consumer.environment.template.applicationKey app setting to Sif3DemoEventConsumer."); + Console.WriteLine(" 1.2) Configure the consumer.environment.url app setting to reference the BROKERED environment endpoint - http://localhost:59586/api/environments/environment."); + Console.WriteLine(" 1.3) Configure the EventConsumerApp to be the Startup object for the project."); Console.WriteLine(); - Console.WriteLine("********************************************************************************"); + Console.WriteLine(" 2) In the demo Consumer project:"); + Console.WriteLine(" 2.1) Set the provider.environmentType app setting to BROKERED."); + Console.WriteLine(" 2.2) Configure the provider.environment.url app setting to reference the BROKERED environment endpoint - http://localhost:59586/api/environments/environment."); + Console.WriteLine(" 2.3) This EventConsumerApp needs to be configured to be the Startup object for this project."); Console.WriteLine(); - Console.WriteLine("To run this Event Consumer demo, the following is required:"); + Console.WriteLine(" 3) Run the demo Broker instead of the EnvironmentProvider."); Console.WriteLine(); - Console.WriteLine(" 1) The consumer.environment.url app setting in the SifFramework.config file of this Consumer needs to reference the BROKERED environment endpoint."); - Console.WriteLine(" 2) The provider.environment.url app setting in the SifFramework.config file of the Sif.Framework.Demo.Au.Provider project needs to reference the BROKERED environment endpoint."); - Console.WriteLine(" 3) The Sif.Framework.Demo.Broker needs to be run instead of the Sif.Framework.EnvironmentProvider."); - Console.WriteLine(" 4) The Sif.Framework.Demo.Au.Provider needs to be run."); - Console.WriteLine(" 5) This EventConsumerApp needs to be configured to be the Startup object for this project."); + Console.WriteLine(" 4) Run the demo Provider."); + Console.WriteLine(); + Console.WriteLine(" 5) Run the demo Consumer."); Console.WriteLine(); Console.WriteLine("********************************************************************************"); - if (RunDemo("Student Personal Event Consumer")) + try { - try - { - StudentPersonalEventConsumer studentPersonalConsumer = new StudentPersonalEventConsumer( - SettingsManager.ConsumerSettings.ApplicationKey, - SettingsManager.ConsumerSettings.InstanceId, - SettingsManager.ConsumerSettings.UserToken, - SettingsManager.ConsumerSettings.SolutionId, - SettingsManager.ConsumerSettings); - studentPersonalConsumer.Start("Sif3DemoZone1", "DEFAULT"); - if (log.IsInfoEnabled) log.Info("Started the Event Consumer."); + SettingsSource source = SelectFrameworkConfigSource(); + IFrameworkSettings settings = GetSettings(source); + ISessionService sessionService = GetSessionService(source); + var consumer = new StudentPersonalEventConsumer( + settings.ApplicationKey, + settings.InstanceId, + settings.UserToken, + settings.SolutionId, + settings, + sessionService); + consumer.Start("Sif3DemoZone1", "DEFAULT"); + + if (Log.IsInfoEnabled) Log.Info("Started the Event Consumer."); - Console.WriteLine("Press any key to stop the Event Consumer (may take several seconds to complete) ..."); - Console.ReadKey(); + Console.WriteLine( + "Press any key to stop the Event Consumer (may take several seconds to complete) ..."); + Console.ReadKey(); - studentPersonalConsumer.Stop(); - if (log.IsInfoEnabled) log.Info("Stopped the Event Consumer."); - } - catch (Exception e) - { - if (log.IsErrorEnabled) log.Error("Error running the Student Personal Event Consumer.\n" + ExceptionUtils.InferErrorResponseMessage(e), e); - } + consumer.Stop(); + + if (Log.IsInfoEnabled) Log.Info("Stopped the Event Consumer."); + } + catch (Exception e) + { + if (Log.IsErrorEnabled) + Log.Error($"Error running the Event Consumer.\n{ExceptionUtils.InferErrorResponseMessage(e)}", e); } Console.WriteLine("Press any key to continue ..."); diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Properties/AssemblyInfo.cs index 8f71b7a6..f7f9e3ef 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Au.Consumer")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2020")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.2.1.13")] -[assembly: AssemblyFileVersion("3.2.1.13")] \ No newline at end of file +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] \ No newline at end of file diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Sif.Framework.Demo.Au.Consumer.csproj b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Sif.Framework.Demo.Au.Consumer.csproj index bbc5195d..4b9742d8 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Sif.Framework.Demo.Au.Consumer.csproj +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/Sif.Framework.Demo.Au.Consumer.csproj @@ -46,6 +46,7 @@ + @@ -73,8 +74,8 @@ 2.0.12 - - 4.0.0 + + 1.0.0 3.4.7 diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/SifFrameworkConfig.db b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/SifFrameworkConfig.db index 16c6f2b6..813a6bfb 100644 Binary files a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/SifFrameworkConfig.db and b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Consumer/SifFrameworkConfig.db differ diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/App_Data/SifFrameworkConfig.db b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/App_Data/SifFrameworkConfig.db index 97702773..dd94baf5 100644 Binary files a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/App_Data/SifFrameworkConfig.db and b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/App_Data/SifFrameworkConfig.db differ diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/SchoolInfosProvider.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/SchoolInfosProvider.cs index 0840042f..d80bbb04 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/SchoolInfosProvider.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/SchoolInfosProvider.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,9 @@ using Sif.Framework.Demo.Au.Provider.Models; using Sif.Framework.Demo.Au.Provider.Services; +using Sif.Framework.Demo.Au.Provider.Utils; using Sif.Framework.Providers; -using Sif.Framework.Settings; using System.Web.Http; -using Tardigrade.Framework.Configurations; -using Tardigrade.Framework.EntityFramework.Configurations; namespace Sif.Framework.Demo.Au.Provider.Controllers { @@ -28,7 +26,8 @@ public class SchoolInfosProvider : BasicProvider { public SchoolInfosProvider() : base( new SchoolInfoService(), - new ProviderSettings(new ApplicationConfiguration(new AppSettingsConfigurationSource("name=SettingsDb")))) + FrameworkConfigFactory.CreateSettings(), + FrameworkConfigFactory.CreateSessionService()) { } diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/StudentPersonalsProvider.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/StudentPersonalsProvider.cs index fd41f090..17d3de2a 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/StudentPersonalsProvider.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/StudentPersonalsProvider.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,10 @@ using Sif.Framework.Demo.Au.Provider.Models; using Sif.Framework.Demo.Au.Provider.Services; +using Sif.Framework.Demo.Au.Provider.Utils; using Sif.Framework.Providers; -using Sif.Framework.Settings; using Sif.Framework.WebApi.ModelBinders; using System.Web.Http; -using Tardigrade.Framework.Configurations; -using Tardigrade.Framework.EntityFramework.Configurations; namespace Sif.Framework.Demo.Au.Provider.Controllers { @@ -29,7 +27,8 @@ public class StudentPersonalsProvider : BasicProvider { public StudentPersonalsProvider() : base( new StudentPersonalService(), - new ProviderSettings(new ApplicationConfiguration(new AppSettingsConfigurationSource("name=SettingsDb")))) + FrameworkConfigFactory.CreateSettings(), + FrameworkConfigFactory.CreateSessionService()) { } diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/StudentSchoolEnrollmentsProvider.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/StudentSchoolEnrollmentsProvider.cs index e82e6f73..72568c71 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/StudentSchoolEnrollmentsProvider.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Controllers/StudentSchoolEnrollmentsProvider.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Systemic Pty Ltd + * Copyright 2021 Systemic Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,9 @@ using Sif.Framework.Demo.Au.Provider.Models; using Sif.Framework.Demo.Au.Provider.Services; +using Sif.Framework.Demo.Au.Provider.Utils; using Sif.Framework.Providers; -using Sif.Framework.Settings; using System.Web.Http; -using Tardigrade.Framework.Configurations; -using Tardigrade.Framework.EntityFramework.Configurations; namespace Sif.Framework.Demo.Au.Provider.Controllers { @@ -28,7 +26,8 @@ public class StudentSchoolEnrollmentsProvider : BasicProvider - /// Register this SIF Provider with the EnvironmentProvider based upon settings defined in the SIF 3.0 - /// Framework configuration, e.g. SifFramework.config. + /// Register this SIF Provider with the EnvironmentProvider. ///
- private void Register(IFrameworkSettings settings) + /// Application settings associated with the Provider. + /// Service associated with Provider sessions. + private void Register(IFrameworkSettings settings, ISessionService sessionService) { - registrationService = RegistrationManager.GetProviderRegistrationService( - settings, - SessionsManager.ProviderSessionService); + registrationService = RegistrationManager.GetProviderRegistrationService(settings, sessionService); registrationService.Register(); } diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Properties/AssemblyInfo.cs index fb126d64..c1d69ee6 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Au.Provider")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2020")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.2.1.13")] -[assembly: AssemblyFileVersion("3.2.1.13")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Sif.Framework.Demo.Au.Provider.csproj b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Sif.Framework.Demo.Au.Provider.csproj index 99bf0509..84e57805 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Sif.Framework.Demo.Au.Provider.csproj +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Sif.Framework.Demo.Au.Provider.csproj @@ -115,8 +115,11 @@ ..\packages\Remotion.Linq.EagerFetching.2.2.0\lib\net45\Remotion.Linq.EagerFetching.dll - - ..\packages\Sif.Framework.4.0.0\lib\net461\Sif.Framework.dll + + ..\packages\Sif.Framework.5.0.0\lib\net461\Sif.Framework.dll + + + ..\packages\Sif.Framework.EntityFramework.1.0.0\lib\net461\Sif.Framework.EntityFramework.dll ..\packages\Sif.Specification.DataModel.Au.3.4.7\lib\netstandard2.0\Sif.Specification.DataModel.Au.dll @@ -258,6 +261,7 @@ + @@ -279,7 +283,6 @@ Web.config - 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/SifFramework.config b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/SifFramework.config index afd4ba92..7ff1fc21 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/SifFramework.config +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/SifFramework.config @@ -6,7 +6,7 @@ - + diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Utils/FrameworkConfigFactory.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Utils/FrameworkConfigFactory.cs new file mode 100644 index 00000000..2531e90b --- /dev/null +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Utils/FrameworkConfigFactory.cs @@ -0,0 +1,84 @@ +/* + * Copyright 2021 Systemic Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Sif.Framework.EntityFramework.Data; +using Sif.Framework.EntityFramework.Services.Sessions; +using Sif.Framework.Model.Sessions; +using Sif.Framework.Model.Settings; +using Sif.Framework.Service.Sessions; +using Sif.Framework.Settings; +using Sif.Framework.Utils; +using System; +using System.Data.Entity; +using Tardigrade.Framework.Configurations; +using Tardigrade.Framework.EntityFramework; +using Tardigrade.Framework.EntityFramework.Configurations; +using Tardigrade.Framework.Persistence; +using Tardigrade.Framework.Services; + +namespace Sif.Framework.Demo.Au.Provider.Utils +{ + internal static class FrameworkConfigFactory + { + public static ISessionService CreateSessionService() + { + ISessionService sessionService; + string frameworkConfigSource = + System.Configuration.ConfigurationManager.AppSettings["demo.frameworkConfigSource"]; + + if ("Database".Equals(frameworkConfigSource, StringComparison.InvariantCultureIgnoreCase)) + { + DbContext dbContext = new SessionDbContext("name=FrameworkConfigDb"); + IRepository repository = new Repository(dbContext); + IObjectService service = new ObjectService(repository); + sessionService = new SessionService(service); + } + else if ("File".Equals(frameworkConfigSource, StringComparison.InvariantCultureIgnoreCase)) + { + sessionService = SessionsManager.ProviderSessionService; + } + else + { + sessionService = SessionsManager.ProviderSessionService; + } + + return sessionService; + } + + public static IFrameworkSettings CreateSettings() + { + IFrameworkSettings settings; + string frameworkConfigSource = + System.Configuration.ConfigurationManager.AppSettings["demo.frameworkConfigSource"]; + + if ("Database".Equals(frameworkConfigSource, StringComparison.InvariantCultureIgnoreCase)) + { + settings = new ProviderSettings( + new ApplicationConfiguration(new AppSettingsConfigurationSource("name=FrameworkConfigDb"))); + } + else if ("File".Equals(frameworkConfigSource, StringComparison.InvariantCultureIgnoreCase)) + { + settings = SettingsManager.ProviderSettings; + } + else + { + settings = SettingsManager.ProviderSettings; + } + + return settings; + } + } +} \ No newline at end of file diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Web.config b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Web.config index 7231ebef..cb73be96 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Web.config +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/Web.config @@ -10,11 +10,11 @@
- + - + diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/packages.config b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/packages.config index 708cf718..451a7c70 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/packages.config +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Au.Provider/packages.config @@ -25,7 +25,8 @@ - + + diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Broker/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Broker/Properties/AssemblyInfo.cs index 9c4a9b52..e03b8fab 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Broker/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Broker/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Broker")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2020")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.2.1.13")] -[assembly: AssemblyFileVersion("3.2.1.13")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Hits.Consumer/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Hits.Consumer/Properties/AssemblyInfo.cs index 0f4e7001..8d6f33a7 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Hits.Consumer/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Hits.Consumer/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Hits.Consumer")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2020")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.2.1.13")] -[assembly: AssemblyFileVersion("3.2.1.13")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Setup/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Setup/Properties/AssemblyInfo.cs index 0b25556e..520a292c 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Setup/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Setup/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Setup")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2018")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.2.1.12")] -[assembly: AssemblyFileVersion("3.2.1.12")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Uk.Consumer/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Uk.Consumer/Properties/AssemblyInfo.cs index df337dd1..25fac47c 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Uk.Consumer/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Uk.Consumer/Properties/AssemblyInfo.cs @@ -7,9 +7,9 @@ [assembly: AssemblyTitle("Sif.Framework.Demo.Uk.Consumer")] [assembly: AssemblyDescription("Consumer created to demonstrate SIF 3 Framework usage.")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("ZiNET Data Solutions Limited")] +[assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Uk.Consumer")] -[assembly: AssemblyCopyright("Crown Copyright © Department for Education (UK) 2016")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.2.1.11")] -[assembly: AssemblyFileVersion("3.2.1.11")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Uk.Provider/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Uk.Provider/Properties/AssemblyInfo.cs index c9b25315..bf62807d 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Uk.Provider/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Uk.Provider/Properties/AssemblyInfo.cs @@ -8,9 +8,9 @@ [assembly: AssemblyTitle("Sif.Framework.Demo.Uk.Provider")] [assembly: AssemblyDescription("Provider created to demonstrate SIF 3 Framework usage.")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("ZiNET Data Solutions Limited")] +[assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Uk.Provider")] -[assembly: AssemblyCopyright("Crown Copyright © Department for Education (UK) 2016")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.2.1.11")] -[assembly: AssemblyFileVersion("3.2.1.11")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Us.Consumer/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Us.Consumer/Properties/AssemblyInfo.cs index ad091637..be616f23 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Us.Consumer/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Us.Consumer/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Us.Consumer")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2018")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.2.1.11")] -[assembly: AssemblyFileVersion("3.2.1.11")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Us.Provider/Properties/AssemblyInfo.cs b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Us.Provider/Properties/AssemblyInfo.cs index 490f50a3..ecaf13ac 100644 --- a/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Us.Provider/Properties/AssemblyInfo.cs +++ b/Code/Sif3FrameworkDemo/Sif.Framework.Demo.Us.Provider/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Systemic Pty Ltd")] [assembly: AssemblyProduct("Sif.Framework.Demo.Us.Provider")] -[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2018")] +[assembly: AssemblyCopyright("Copyright © Systemic Pty Ltd 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.2.1.11")] -[assembly: AssemblyFileVersion("3.2.1.11")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/Data/Databases/SQLite/SifFrameworkDatabase.db b/Data/Databases/SQLite/SifFrameworkDatabase.db index 7e5699ef..07666b53 100644 Binary files a/Data/Databases/SQLite/SifFrameworkDatabase.db and b/Data/Databases/SQLite/SifFrameworkDatabase.db differ diff --git a/Documentation/Backward incompatible changes.md b/Documentation/Backward incompatible changes.md index 215af8f3..47d5c6df 100644 --- a/Documentation/Backward incompatible changes.md +++ b/Documentation/Backward incompatible changes.md @@ -1,6 +1,5 @@ # Backward incompatible changes - ### **3.2.1.14 -> 4.0.0** - The public Consumer(Environment) constructor has been made protected. @@ -13,3 +12,8 @@ - The empty default constructor of the AuthorisationService class has been removed. - The Sif.Framework project only targets .NET Standard 2.0, .NET Framework 4.7.2 and .NET Framework 4.6.1. It no longer targets .NET Frameworks 4.6.2, 4.7 and 4.7.1. - The ConsumerRegistrationService and ProviderRegistrationService static properties of the static RegistrationManager class have been made obsolete. + +### **4.0.1 -> 5.0.0** + +- Renamed the ISessionService method HasSession(string) to HasSessionToken(string). +- Various methods in the ISessionService interface have been modified to throw AlreadyExistsException, ArgumentNullException, DuplicateFoundException and NotFoundException as appropriate. diff --git a/Documentation/Developer Guides/Configuring the Event Consumer demo.md b/Documentation/Developer Guides/Configuring the Event Consumer demo.md index 78d33bb4..07956f02 100644 --- a/Documentation/Developer Guides/Configuring the Event Consumer demo.md +++ b/Documentation/Developer Guides/Configuring the Event Consumer demo.md @@ -3,12 +3,14 @@ Configuring the Event Consumer demo 1. In the demo Consumer project: - + Configure the consumer.environment.url app setting to reference the BROKERED environment endpoint. + + Set the consumer.environment.template.applicationKey app setting to Sif3DemoEventConsumer. + + Configure the consumer.environment.url app setting to reference the BROKERED environment endpoint - http://localhost:59586/api/environments/environment. + Configure the EventConsumerApp to be the Startup object for the project. 1. In the demo Provider project: - + Configure the provider.environment.url app setting to reference the BROKERED environment endpoint. + + Set the provider.environmentType app setting to BROKERED. + + Configure the provider.environment.url app setting to reference the BROKERED environment endpoint - http://localhost:59586/api/environments/environment. 1. Run the demo Broker instead of the EnvironmentProvider. diff --git a/Documentation/Managing application settings and session tokens from a database.md b/Documentation/Managing application settings and session tokens from a database.md new file mode 100644 index 00000000..ad124d46 --- /dev/null +++ b/Documentation/Managing application settings and session tokens from a database.md @@ -0,0 +1,104 @@ +# Managing application settings and session tokens from a database + +Both SIF Consumers and Providers now support the passing of SIF Framework application settings and session tokens through constructor parameters. This allows these values to be read from any source (including a database) and not just from the SifFramework.config file (which is used by default if no constructor parameters are specified). + +## SIF Consumer + +The following modifications were made to the Demo AU Consumer. + +### Common configuration + +> 1. Installed the System.Data.SQLite NuGet package (not to be used for a production system). +> 1. Installed the Tardigrade.Framework.EntityFramework NuGet package. +> 1. Added an SQLite database file. Ensure that the `Build Action` is `None` and that the `Copy to Output Directory` is `Copy if newer`. +> 1. Configured the App.config file to support SQLite with EntityFramework 6, including defining the database file to be used. Instructions for the use of SQLite with EntityFramework is not within the scope of this document. + +### Application settings + +> 1. Created an AppSettings database table. An appropriate SQL script for the AppSettings database table can be found in the `Scripts\SQL\Application settings table` directory. +> 1. Updated the Demo AU Consumer classes to implement the constructors that pass an IFrameworkSettings parameter. +> 1. In the ConsumerApp class, read the application settings from the database and passed them to the constructor of the SIF Consumer (in this case, StudentPersonalConsumer). + +To read the application settings from a database, the following code is used: + +```cs +IFrameworkSettings settings = + new ConsumerSettings( + new ApplicationConfiguration( + new AppSettingsConfigurationSource("name=FrameworkConfigDb"))); +``` + +The AppSettingsConfigurationSource constructor takes a connection string name that has been configured in the App.config file. The database file is referenced by default from the `bin\Debug` directory with the `|DataDirectory|` substitution string. + +The AppSettingsConfigurationSource and ApplicationConfiguration classes are referenced from the Tardigrade.Framework.EntityFramework and Tardigrade.Framework NuGet packages respectively. + +### Session tokens + +> 1. Installed the Sif.Framework.EntityFramework NuGet package. +> 1. Created a Sessions database table. An appropriate SQL script for the Sessions database table can be found in the `Scripts\SQL\Session table` directory. +> 1. Updated the Demo AU Consumer classes to implement the constructors that pass an ISessionService parameter. +> 1. In the ConsumerApp class, created the session service and passed it to the constructor of the SIF Consumer (in this case, StudentPersonalConsumer). + +To create the session service, the following code is used: + +```cs +DbContext dbContext = new SessionDbContext("name=FrameworkConfigDb"); +IRepository repository = new Repository(dbContext); +IObjectService service = new ObjectService(repository); +ISessionService sessionService = new SessionService(service); +``` + +The SessionDbContext constructor takes a connection string name that has been configured in the App.config file. The database file is referenced by default from the `bin\Debug` directory with the `|DataDirectory|` substitution string. + +The Repository and ObjectService classes are referenced from the Tardigrade.Framework.EntityFramework and Tardigrade.Framework NuGet packages respectively. The SessionDbContext and SessionService classes are referenced from the Sif.Framework.EntityFramework NuGet package. + +## SIF Provider + +The following modifications were made to the Demo AU Provider. + +### Common configuration + +> 1. Installed the System.Data.SQLite NuGet package (not to be used for a production system). +> 1. Installed the Tardigrade.Framework.EntityFramework NuGet package. +> 1. Added an SQLite database file to the App_Data directory. Ensure that the `Build Action` is `None` and that the `Copy to Output Directory` is `Copy if newer`. +> 1. Configured the Web.config file to support SQLite with EntityFramework 6, including defining the database file to be used. Instructions for the use of SQLite with EntityFramework is not within the scope of this document. +> 1. Added the `demo.frameworkConfigSource` application setting to the Web.config file and set it's value to `Database`. + +### Application settings + +> 1. Created an AppSettings database table. An appropriate SQL script for the AppSettings databaes table can be found in the `Scripts\SQL\Application settings table` directory. +> 1. Updated the Global.asax.cs file to read the application settings from the database and pass them to the `RegistrationManager.GetProviderRegistrationService(IFrameworkSettings, ISessionService)` method. All previous references to `SettingsManager.ProviderSettings` were replaced. +> 1. Updated the Demo AU Providers to implement the constructors that pass an IFrameworkSettings parameter. + +To read the application settings from a database, the following code is used: + +```cs +IFrameworkSettings settings = + new ProviderSettings( + new ApplicationConfiguration( + new AppSettingsConfigurationSource("name=FrameworkConfigDb"))); +``` + +The AppSettingsConfigurationSource constructor takes a connection string name that has been configured in the Web.config file. The database file is referenced by default from the `App_Data` directory with the `|DataDirectory|` substitution string. + +The AppSettingsConfigurationSource and ApplicationConfiguration classes are referenced from the Tardigrade.Framework.EntityFramework and Tardigrade.Framework NuGet packages respectively. + +### Session tokens + +> 1. Installed the Sif.Framework.EntityFramework NuGet package. +> 1. Created a Sessions database table. An appropriate SQL script for the Sessions database table can be found in the `Scripts\SQL\Session table` directory. +> 1. Updated the Global.asax.cs file to create a session service to pass to the `RegistrationManager.GetProviderRegistrationService(IFrameworkSettings, ISessionService)` method. +> 1. Updated the Demo AU Providers to implement the constructors that pass an ISessionService parameter. + +To create the session service, the following code is used: + +```cs +DbContext dbContext = new SessionDbContext("name=FrameworkConfigDb"); +IRepository repository = new Repository(dbContext); +IObjectService service = new ObjectService(repository); +ISessionService sessionService = new SessionService(service); +``` + +The SessionDbContext constructor takes a connection string name that has been configured in the Web.config file. The database file is referenced by default from the `App_Data` directory with the `|DataDirectory|` substitution string. + +The Repository and ObjectService classes are referenced from the Tardigrade.Framework.EntityFramework and Tardigrade.Framework NuGet packages respectively. The SessionDbContext and SessionService classes are referenced from the Sif.Framework.EntityFramework NuGet package. diff --git a/Documentation/Reading application settings from a database.md b/Documentation/Reading application settings from a database.md deleted file mode 100644 index ce1435e8..00000000 --- a/Documentation/Reading application settings from a database.md +++ /dev/null @@ -1,52 +0,0 @@ -# Reading application settings from a database - -Both SIF Providers and Consumers now support the passing of SIF Framework application settings through a constructor parameter. This allows application settings to be read from any source and not just from the SifFramework.config file (which is used by default if no application settings are specified). This includes application settings stored in a database. - -## SIF Consumer - -The following modifications were required to allow the Demo AU Consumer to read appliations settings from a database: - -> 1. Installed the System.Data.SQLite NuGet package (not to be used for a production1system). -> 1. Installed the Tardigrade.Framework.EntityFramework NuGet package. -> 1. Added an SQLite database file where the application settings are stored in the AppSettings database table. Ensure that the `Build Action` is `None` and that the `Copy to Output Directory` is `Copy if newer`. An appropriate SQL script for the AppSettings databaes table can be found in the `Scripts\SQL\Application settings table` directory. -> 1. Configured the App.config file to support SQLite with EntityFramework 6, including defining the database file to be used. -> 1. Updated the Demo AU Consumers to implement the constructors that pass an IFrameworkSettings parameter. -> 1. In the ConsumerApp, read the application settings from the database and passed them to the constructor of the SIF Consumer (in this case, StudentPersonalConsumer). - -To read the application settings from a database, the following code is used: - -```cs -IFrameworkSettings settings = - new ConsumerSettings( - new ApplicationConfiguration( - new AppSettingsConfigurationSource("name=SettingsDb"))); -``` - -The AppSettingsConfigurationSource constructor takes a connection string name that has been configured in the App.config file. The database file is referenced by default from the `bin\Debug` directory with the `|DataDirectory|` substitution string. - -The AppSettingsConfigurationSource and ApplicationConfiguration classes are referenced from the Tardigrade.Framework.EntityFramework and Tardigrade.Framework NuGet packages respectively. - - -## SIF Provider - -The following modifications were required to allow the Demo AU Provider to read appliations settings from a database: - -> 1. Installed the System.Data.SQLite NuGet package (not to be used for a production1system). -> 1. Installed the Tardigrade.Framework.EntityFramework NuGet package. -> 1. Added an SQLite database file to the App_Data directory. The application settings are defined in the AppSettings database table. Ensure that the `Build Action` is `None` and that the `Copy to Output Directory` is `Copy if newer`. An appropriate SQL script for the AppSettings databaes table can be found in the `Scripts\SQL\Application settings table` directory. -> 1. Configured the Web.config file to support SQLite with EntityFramework 6, including defining the database file to be used. -> 1. Updated the Global.asax.cs file to read the application settings from the database and then passed them to the new `RegistrationManager.GetProviderRegistrationService(IFrameworkSettings, ISessionService)` method in the updated `Register(IFrameworkSettings)` method. All previous references to `SettingsManager.ProviderSettings` were replaced. -> 1. Updated the Demo AU Providers to implement the constructors that pass an IFrameworkSettings parameter. - -To read the application settings from a database, the following code is used: - -```cs -IFrameworkSettings settings = - new ProviderSettings( - new ApplicationConfiguration( - new AppSettingsConfigurationSource("name=SettingsDb"))); -``` - -The AppSettingsConfigurationSource constructor takes a connection string name that has been configured in the App.config file. The database file is referenced by default from the `App_Data` directory with the `|DataDirectory|` substitution string. - -The AppSettingsConfigurationSource and ApplicationConfiguration classes are referenced from the Tardigrade.Framework.EntityFramework and Tardigrade.Framework NuGet packages respectively. diff --git a/Documentation/To do list.md b/Documentation/To do list.md new file mode 100644 index 00000000..6ad613e2 --- /dev/null +++ b/Documentation/To do list.md @@ -0,0 +1,3 @@ +## To do list + +- Deprecate the exceptions defined in Sif.Framework.Model.Exceptions in favour of those from Tardigrade.Framework.Exceptions. diff --git a/README.md b/README.md index 42094c25..46be05cb 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,20 @@ See the [wiki associated with this repository](https://github.com/Access4Learnin ## Version control history +**May 26, 2021 - 5.0.0 Enabled session tokens to be stored in a database** + +- Created a service for storing session tokens in a database using Entity Framework. +- Created a new Sif.Framework.EntityFramework project containing the Entity Framework implementation of the session service. +- Updated the Consumer and Provider classes to utilise the session service. +- Updated the AU Demo Consumer and Provider projects to enable the use of the session service. +- Created unit tests for the session service. +- Performed general code improvements based upon ReSharper recommendations. + **Apr 25, 2021 - 4.0.1 Updated to the official release of the SIF AU 3.4.8 Data Model** - Updated to the official release of the SIF AU 3.4.8 Data Model. -**Dec 29, 2020 - 4.0.0 Enable application settings to be read from a database** +**Dec 29, 2020 - 4.0.0 Enabled application settings to be read from a database** - Added classes to enable application settings to be read from a database. - Re-designed the Provider classes to better accommodate passing of application settings. diff --git a/Scripts/SQL/Session table/Create Session database table - 4.0.0 (SQL Server).sql b/Scripts/SQL/Session table/Create Session database table - 4.0.0 (SQL Server).sql new file mode 100644 index 00000000..e69de29b diff --git a/Scripts/SQL/Session table/Create Session database table - 4.0.0 (SQLite).sql b/Scripts/SQL/Session table/Create Session database table - 4.0.0 (SQLite).sql new file mode 100644 index 00000000..edefba59 --- /dev/null +++ b/Scripts/SQL/Session table/Create Session database table - 4.0.0 (SQLite).sql @@ -0,0 +1,12 @@ +CREATE TABLE Sessions +( + Id TEXT NOT NULL CONSTRAINT PK_Session PRIMARY KEY, + ApplicationKey TEXT NOT NULL, + EnvironmentUrl TEXT NOT NULL, + SessionToken TEXT NOT NULL, + SolutionId TEXT NULL, + InstanceId TEXT NULL, + UserToken TEXT NULL, + SubscriptionId TEXT NULL, + QueueId TEXT NULL +)