diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityService.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityService.cs index d60e8fc657..ddf74f896b 100644 --- a/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityService.cs +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityService.cs @@ -8,7 +8,11 @@ namespace EdFi.Ods.Features.IdentityManagement.Models /// /// Implement this interface if the supporting service supports synchronous methods /// - public interface IIdentityService + public interface IIdentityService + where TCreateRequest : IdentityCreateRequest + where TSearchRequest : IdentitySearchRequest + where TSearchResponse : IdentitySearchResponse + where TIdentityResponse : IdentityResponse { /// /// Which IdentityServices does the supporting service implement @@ -20,20 +24,20 @@ public interface IIdentityService /// /// an array of identities to be created /// An identity response status of: Success - Task> Create(IdentityCreateRequest createRequest); + Task> Create(TCreateRequest createRequest); /// /// Find existing identities by their identifiers /// /// Unique person identifiers to look up /// An identity response status of: Success with IdentityResponse[] - Task> Find(params string[] findRequest); + Task> Find(params string[] findRequest); /// /// Search for exact and potential identity matches /// /// /// An identity response status of: Success - Task> Search(params IdentitySearchRequest[] searchRequest); + Task> Search(params TSearchRequest[] searchRequest); } } diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceAsync.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceAsync.cs index 76104ecff3..dc24a986e8 100644 --- a/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceAsync.cs +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceAsync.cs @@ -1,9 +1,17 @@ -namespace EdFi.Ods.Features.IdentityManagement.Models +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +namespace EdFi.Ods.Features.IdentityManagement.Models { /// /// Implement this interface if the supporting service supports asynchronous methods /// - public interface IIdentityServiceAsync + public interface IIdentityServiceAsync + where TSearchRequest : IdentitySearchRequest + where TSearchResponse : IdentitySearchResponse + where TIdentityResponse : IdentityResponse { /// /// Which IdentityServices does the supporting service implement @@ -22,13 +30,13 @@ public interface IIdentityServiceAsync /// /// /// An identity response status of: Success - Task> Search(params IdentitySearchRequest[] searchRequest); + Task> Search(params TSearchRequest[] searchRequest); /// /// Retrieve the results from a previously submitted search /// /// a unique string representing the request /// An identity response status of: Incomplete, Success with IdentityResponse[], or NotFound - Task> Response(string requestToken); + Task> Response(string requestToken); } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceWithDefaultModels.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceWithDefaultModels.cs new file mode 100644 index 0000000000..99ba42642d --- /dev/null +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceWithDefaultModels.cs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +namespace EdFi.Ods.Features.IdentityManagement.Models; + +/// +/// Defines an interface that closes the generic types of the +/// with the default Identities request/response models. +/// +public interface IIdentityServiceWithDefaultModels + : IIdentityService, + IdentityResponse> { }; diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceWithDefaultModelsAsync.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceWithDefaultModelsAsync.cs new file mode 100644 index 0000000000..d45fb2e929 --- /dev/null +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IIdentityServiceWithDefaultModelsAsync.cs @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +namespace EdFi.Ods.Features.IdentityManagement.Models; + +/// +/// Defines an interface that closes the generic types of the +/// with the default Identities request/response models. +/// +public interface IIdentityServiceWithDefaultModelsAsync + : IIdentityServiceAsync, IdentityResponse> { }; diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityCreateRequest.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityCreateRequest.cs index 2cea7d83b6..bf603b93c5 100644 --- a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityCreateRequest.cs +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityCreateRequest.cs @@ -1,8 +1,11 @@ -using EdFi.Ods.Common.Expando; +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. namespace EdFi.Ods.Features.IdentityManagement.Models { - public class IdentityCreateRequest : Expando + public class IdentityCreateRequest { public string LastSurname { get; set; } @@ -20,4 +23,4 @@ public class IdentityCreateRequest : Expando public Location BirthLocation { get; set; } } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityResponse.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityResponse.cs index de2f51ab5d..83595713c8 100644 --- a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityResponse.cs +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityResponse.cs @@ -1,8 +1,11 @@ -using EdFi.Ods.Common.Expando; +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. namespace EdFi.Ods.Features.IdentityManagement.Models { - public class IdentityResponse : Expando + public class IdentityResponse { public string UniqueId { get; set; } @@ -24,4 +27,4 @@ public class IdentityResponse : Expando public Location BirthLocation { get; set; } } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityResponseStatus.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityResponseStatus.cs index 0d3dd548ed..68f675e2af 100644 --- a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityResponseStatus.cs +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentityResponseStatus.cs @@ -15,4 +15,4 @@ public class IdentityResponseStatus public IEnumerable Errors { get; set; } } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchRequest.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchRequest.cs index f19cf5301b..4407d2d4f3 100644 --- a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchRequest.cs +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchRequest.cs @@ -1,8 +1,11 @@ -using EdFi.Ods.Common.Expando; +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. namespace EdFi.Ods.Features.IdentityManagement.Models { - public class IdentitySearchRequest : Expando + public class IdentitySearchRequest { public string LastSurname { get; set; } @@ -20,4 +23,4 @@ public class IdentitySearchRequest : Expando public Location BirthLocation { get; set; } } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchResponse.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchResponse.cs index 030387a4f2..a3b6ddd912 100644 --- a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchResponse.cs +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchResponse.cs @@ -1,9 +1,15 @@ -namespace EdFi.Ods.Features.IdentityManagement.Models +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +namespace EdFi.Ods.Features.IdentityManagement.Models { - public class IdentitySearchResponse + public class IdentitySearchResponse + where TIdentityResponse : IdentityResponse { public SearchResponseStatus Status { get; set; } - public IdentitySearchResponses[] SearchResponses { get; set; } + public IdentitySearchResponses[] SearchResponses { get; set; } } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchResponses.cs b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchResponses.cs index 4834bdcf18..1b29c378d2 100644 --- a/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchResponses.cs +++ b/Application/EdFi.Ods.Features.IdentityManagement/Models/IdentitySearchResponses.cs @@ -1,7 +1,13 @@ -namespace EdFi.Ods.Features.IdentityManagement.Models +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +namespace EdFi.Ods.Features.IdentityManagement.Models { - public class IdentitySearchResponses + public class IdentitySearchResponses + where TIdentityResponse : IdentityResponse { - public IdentityResponse[] Responses { get; set; } + public TIdentityResponse[] Responses { get; set; } } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Features/Container/Modules/IdentityModule.cs b/Application/EdFi.Ods.Features/Container/Modules/IdentityModule.cs index 7be18928ca..40e8a189e3 100644 --- a/Application/EdFi.Ods.Features/Container/Modules/IdentityModule.cs +++ b/Application/EdFi.Ods.Features/Container/Modules/IdentityModule.cs @@ -8,7 +8,7 @@ using EdFi.Ods.Common.Constants; using EdFi.Ods.Common.Container; using EdFi.Ods.Features.IdentityManagement; -using EdFi.Ods.Features.IdentityManagement.Models; +using Microsoft.AspNetCore.Mvc.ApplicationModels; namespace EdFi.Ods.Features.Container.Modules { @@ -21,10 +21,13 @@ public IdentityModule(ApiSettings apiSettings) public override void ApplyConfigurationSpecificRegistrations(ContainerBuilder builder) { + builder.RegisterType() + .As() + .SingleInstance(); + builder.RegisterType() - .As() - .As() - .SingleInstance(); + .AsImplementedInterfaces() + .SingleInstance(); } } } diff --git a/Application/EdFi.Ods.Features/Controllers/IdentitiesController.cs b/Application/EdFi.Ods.Features/Controllers/IdentitiesControllerBase.cs similarity index 92% rename from Application/EdFi.Ods.Features/Controllers/IdentitiesController.cs rename to Application/EdFi.Ods.Features/Controllers/IdentitiesControllerBase.cs index e973895a40..cfe2d877b6 100644 --- a/Application/EdFi.Ods.Features/Controllers/IdentitiesController.cs +++ b/Application/EdFi.Ods.Features/Controllers/IdentitiesControllerBase.cs @@ -33,14 +33,20 @@ namespace EdFi.Ods.Features.Controllers [Produces("application/json")] [ApplyOdsRouteRootTemplate] [Route($"{IdentityManagementConstants.IdentityRoutePrefix}/identities")] - public class IdentitiesController : ControllerBase + public abstract class IdentitiesControllerBase : ControllerBase + where TCreateRequest : IdentityCreateRequest + where TSearchRequest : IdentitySearchRequest + where TSearchResponse : IdentitySearchResponse + where TIdentityResponse : IdentityResponse { private const string InvalidServerResponse = "Invalid response from identity service: "; private const string NoIdentitySystem = "There is no integrated Unique Identity System"; - private readonly IIdentityService _identitySubsystem; - private readonly IIdentityServiceAsync _identitySubsystemAsync; - public IdentitiesController(IIdentityService identitySubsystem, IIdentityServiceAsync identitySubsystemAsync) + private readonly IIdentityService _identitySubsystem; + private readonly IIdentityServiceAsync _identitySubsystemAsync; + + protected IdentitiesControllerBase(IIdentityService identitySubsystem, + IIdentityServiceAsync identitySubsystemAsync) { _identitySubsystem = identitySubsystem; _identitySubsystemAsync = identitySubsystemAsync; @@ -103,7 +109,7 @@ public async Task GetById([FromRoute(Name = "id")] string uniqueI /// The server does not support the requested function. /// The underlying identity system returned an error. [HttpPost] - public async Task Create([FromBody] IdentityCreateRequest request) + public async Task Create([FromBody] TCreateRequest request) { try { @@ -194,7 +200,7 @@ public async Task Find([FromBody] string[] uniqueIds) /// The underlying identity system returned an error. [HttpPost] [Route("search")] - public async Task Search([FromBody] IdentitySearchRequest[] criteria) + public async Task Search([FromBody] TSearchRequest[] criteria) { try { @@ -294,4 +300,4 @@ public class ErrorResponse public string IdentitySystemStatusCode { get; set; } public IEnumerable IdentitySystemErrors { get; set; } } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Features/IdentityManagement/IdentitiesController.cs b/Application/EdFi.Ods.Features/IdentityManagement/IdentitiesController.cs new file mode 100644 index 0000000000..5c04783067 --- /dev/null +++ b/Application/EdFi.Ods.Features/IdentityManagement/IdentitiesController.cs @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.Features.Controllers; +using EdFi.Ods.Features.IdentityManagement.Models; + +namespace EdFi.Ods.Features.IdentityManagement; + +/// +/// Closes the Identities base controller around the default request/response model types to enable ASP.NET to find +/// and instantiate it. +/// +/// You can extend the default Identities request/response models by registering replacement services +/// with different (derived) model types, and then providing a new controller that derives from the +/// class and closes the generic type definition so that ASP.NET will locate and instantiate it (instead of the +/// out-of-the-box . +/// +public class IdentitiesController + : IdentitiesControllerBase, + IdentityResponse> +{ + public IdentitiesController( + IIdentityServiceWithDefaultModels identitySubsystem, + IIdentityServiceWithDefaultModelsAsync identitySubsystemAsync) + : base(identitySubsystem, identitySubsystemAsync) { } +} diff --git a/Application/EdFi.Ods.Features/IdentityManagement/IdentitiesControllerOverrideConvention.cs b/Application/EdFi.Ods.Features/IdentityManagement/IdentitiesControllerOverrideConvention.cs new file mode 100644 index 0000000000..79c34c08ef --- /dev/null +++ b/Application/EdFi.Ods.Features/IdentityManagement/IdentitiesControllerOverrideConvention.cs @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using System.Linq; +using System.Reflection; +using EdFi.Ods.Common; +using EdFi.Ods.Features.Controllers; +using Microsoft.AspNetCore.Mvc.ApplicationModels; + +namespace EdFi.Ods.Features.IdentityManagement; + +/// +/// Implements a convention that looks for multiple controllers derived from the abstract +/// base controller class, and removes the entry for the default out-of-the-box +/// to prevent from occurring when resolving requests for identity management routes. +/// +public class IdentitiesControllerOverrideConvention : IApplicationModelConvention +{ + public void Apply(ApplicationModel application) + { + // Find all Identities controllers (should only be either 1 or 2, if custom implementation provided) + var identitiesControllers = application.Controllers.Where( + m => + { + // Eliminate most controllers using the namespace + if (!m.ControllerType.Namespace.StartsWith(Namespaces.Api.Controllers)) + { + // Identities controllers (should) inherit from the IdentitiesControllerBase class that is generic + if (m.ControllerType.BaseType is { IsGenericType: true }) + { + // Is it an identities controller? + if (m.ControllerType.BaseType.GetGenericTypeDefinition() == typeof(IdentitiesControllerBase<,,,>)) + { + return true; + } + } + } + + return false; + }) + .ToArray(); + + // Determine if we will have an ambiguous match, and remove the UnimplementedIdentitiesController from the model + if (identitiesControllers.Length > 1) + { + foreach (var controllerModel in identitiesControllers) + { + if (controllerModel.ControllerType == typeof(IdentitiesController).GetTypeInfo()) + { + application.Controllers.Remove(controllerModel); + } + } + } + } +} diff --git a/Application/EdFi.Ods.Features/IdentityManagement/UnimplementedIdentityService.cs b/Application/EdFi.Ods.Features/IdentityManagement/UnimplementedIdentityService.cs index 425078b7fe..3fa128f04b 100644 --- a/Application/EdFi.Ods.Features/IdentityManagement/UnimplementedIdentityService.cs +++ b/Application/EdFi.Ods.Features/IdentityManagement/UnimplementedIdentityService.cs @@ -9,7 +9,10 @@ namespace EdFi.Ods.Features.IdentityManagement { - public class UnimplementedIdentityService : IIdentityService, IIdentityServiceAsync + /// + /// Implements the Identities service such that it exhibits no capabilities and each method throws . + /// + public class UnimplementedIdentityService : IIdentityServiceWithDefaultModels, IIdentityServiceWithDefaultModelsAsync { public IdentityServiceCapabilities IdentityServiceCapabilities { @@ -21,29 +24,29 @@ public Task> Create(IdentityCreateRequest createR throw new NotImplementedException(); } - public Task> Find(params string[] findRequest) + Task>> IIdentityService, IdentityResponse>.Find(params string[] findRequest) { throw new NotImplementedException(); } - public Task> Search(params IdentitySearchRequest[] searchRequest) + Task> IIdentityServiceAsync, IdentityResponse>.Search(params IdentitySearchRequest[] searchRequest) { throw new NotImplementedException(); } - Task> IIdentityServiceAsync.Search(params IdentitySearchRequest[] searchRequest) + public Task>> Response(string requestToken) { throw new NotImplementedException(); } - public Task> Response(string requestToken) + Task> IIdentityServiceAsync, IdentityResponse>.Find(params string[] findRequest) { throw new NotImplementedException(); } - Task> IIdentityServiceAsync.Find(params string[] findRequest) + Task>> IIdentityService, IdentityResponse>.Search(params IdentitySearchRequest[] searchRequest) { throw new NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/Application/EdFi.Ods.Tests/EdFi.Ods.Features/Controllers/IdentitiesControllerTests.cs b/Application/EdFi.Ods.Tests/EdFi.Ods.Features/Controllers/IdentitiesControllerTests.cs index 5ee899b195..82fe509bc0 100644 --- a/Application/EdFi.Ods.Tests/EdFi.Ods.Features/Controllers/IdentitiesControllerTests.cs +++ b/Application/EdFi.Ods.Tests/EdFi.Ods.Features/Controllers/IdentitiesControllerTests.cs @@ -17,20 +17,31 @@ using Shouldly; using Test.Common; +using TestIdentitySearchResponse = EdFi.Ods.Features.IdentityManagement.Models.IdentitySearchResponse; + namespace EdFi.Ods.Tests.EdFi.Ods.Features.Controllers { + public class TestIdentitiesController + : IdentitiesControllerBase, + IdentityResponse> + { + public TestIdentitiesController(IIdentityService, IdentityResponse> identitySubsystem, IIdentityServiceAsync, IdentityResponse> identitySubsystemAsync) + : base(identitySubsystem, identitySubsystemAsync) { } + } + [TestFixture] public class IdentitiesControllerTests { public class InvalidPropertiesGetByIdRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; + private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.InvalidProperties); - _controller = new IdentitiesController(identityService, identityService); + _controller = new (identityService, identityService); return Task.CompletedTask; } @@ -55,13 +66,13 @@ public void Should_return_invalid_properties_details() public class IncompleteGetByIdRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Incomplete); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -86,13 +97,13 @@ public void Should_return_incomplete_details() public class NotFoundGetByIdRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.NotFound); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -112,7 +123,7 @@ public void Should_return_not_found_details() public class SuccessGetByIdRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() @@ -121,7 +132,7 @@ protected override Task ArrangeAsync() A.CallTo(() => urlHelper.Link(A.Ignored, A.Ignored)).Returns("https://localhost"); var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Success); - _controller = new IdentitiesController(identityService, identityService) { Url = urlHelper }; + _controller = new TestIdentitiesController(identityService, identityService) { Url = urlHelper }; return Task.CompletedTask; } @@ -143,13 +154,13 @@ public void Should_return_success_details() public class InvalidPropertiesCreateRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.InvalidProperties); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -168,13 +179,13 @@ public void Should_return_invalid_properties_details() public class IncompleteCreateRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Incomplete); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -199,13 +210,13 @@ public void Should_return_incomplete_details() public class NotFoundCreateRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.NotFound); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -225,7 +236,7 @@ public void Should_return_not_found_details() public class SuccessCreateRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() @@ -234,7 +245,7 @@ protected override Task ArrangeAsync() A.CallTo(() => urlHelper.Link(A.Ignored, A.Ignored)).Returns("https://localhost"); var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Success); - _controller = new IdentitiesController(identityService, identityService) { Url = urlHelper }; + _controller = new TestIdentitiesController(identityService, identityService) { Url = urlHelper }; return Task.CompletedTask; } @@ -256,13 +267,13 @@ public void Should_return_success_details() public class InvalidPropertiesFindRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.InvalidProperties); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -287,13 +298,13 @@ public void Should_return_invalid_properties_details() public class IncompleteFindRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Incomplete); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -318,13 +329,13 @@ public void Should_return_incomplete_details() public class NotFoundFindRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.NotFound); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -344,7 +355,7 @@ public void Should_return_not_found_details() public class SuccessFindRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() @@ -353,7 +364,7 @@ protected override Task ArrangeAsync() A.CallTo(() => urlHelper.Link(A.Ignored, A.Ignored)).Returns("https://localhost"); var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Success); - _controller = new IdentitiesController(identityService, identityService) {Url = urlHelper}; + _controller = new TestIdentitiesController(identityService, identityService) {Url = urlHelper}; return Task.CompletedTask; } @@ -371,13 +382,13 @@ public void Should_return_success_details() public class InvalidPropertiesSearchRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.InvalidProperties); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -402,13 +413,13 @@ public void Should_return_invalid_properties_details() public class IncompleteSearchRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Incomplete); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -433,13 +444,13 @@ public void Should_return_incomplete_details() public class NotFoundSearchRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.NotFound); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -459,7 +470,7 @@ public void Should_return_not_found_details() public class SuccessSearchRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() @@ -468,7 +479,7 @@ protected override Task ArrangeAsync() A.CallTo(() => urlHelper.Link(A.Ignored, A.Ignored)).Returns("https://localhost"); var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Success); - _controller = new IdentitiesController(identityService, identityService) { Url = urlHelper }; + _controller = new TestIdentitiesController(identityService, identityService) { Url = urlHelper }; return Task.CompletedTask; } @@ -486,13 +497,13 @@ public void Should_return_success_details() public class InvalidPropertiesResultRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.InvalidProperties); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -517,7 +528,7 @@ public void Should_return_invalid_properties_details() public class IncompleteResultRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() @@ -536,7 +547,7 @@ protected override Task ArrangeAsync() }; var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Incomplete); - _controller = new IdentitiesController(identityService, identityService) {ControllerContext = controllerContext}; + _controller = new TestIdentitiesController(identityService, identityService) {ControllerContext = controllerContext}; return Task.CompletedTask; } @@ -555,13 +566,13 @@ public void Should_return_incomplete_details() public class NotFoundResultRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.NotFound); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -581,7 +592,7 @@ public void Should_return_not_found_details() public class SuccessResultRequest : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() @@ -590,7 +601,7 @@ protected override Task ArrangeAsync() A.CallTo(() => urlHelper.Link(A.Ignored, A.Ignored)).Returns("https://localhost"); var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.Success); - _controller = new IdentitiesController(identityService, identityService) { Url = urlHelper }; + _controller = new TestIdentitiesController(identityService, identityService) { Url = urlHelper }; return Task.CompletedTask; } @@ -602,7 +613,7 @@ protected override async Task ActAsync() [Test] public void Should_return_success_details() { - var response = (IdentitySearchResponse)_actionResult.Value; + var response = (TestIdentitySearchResponse)_actionResult.Value; AssertHelper.All( () => _actionResult.StatusCode.ShouldBe(StatusCodes.Status200OK), @@ -612,13 +623,13 @@ public void Should_return_success_details() public class UnknownResult : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.UnknownStatusCode); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } @@ -642,13 +653,13 @@ public void Should_return_success_details() public class NullErrorListResult : TestFixtureAsyncBase { - private IdentitiesController _controller; + private TestIdentitiesController _controller; private ObjectResult _actionResult; protected override Task ArrangeAsync() { var identityService = new TestIdentitiesService(TestIdentitiesService.ResponseBehaviour.NullErrorList); - _controller = new IdentitiesController(identityService, identityService); + _controller = new TestIdentitiesController(identityService, identityService); return Task.CompletedTask; } diff --git a/Application/EdFi.Ods.Tests/EdFi.Ods.Features/_Helpers/TestIdentitiesService.cs b/Application/EdFi.Ods.Tests/EdFi.Ods.Features/_Helpers/TestIdentitiesService.cs index fe4b159da5..20d127fedc 100644 --- a/Application/EdFi.Ods.Tests/EdFi.Ods.Features/_Helpers/TestIdentitiesService.cs +++ b/Application/EdFi.Ods.Tests/EdFi.Ods.Features/_Helpers/TestIdentitiesService.cs @@ -8,9 +8,15 @@ using EdFi.Ods.Features.IdentityManagement.Models; using Microsoft.AspNetCore.Identity; +using TestIdentityService = EdFi.Ods.Features.IdentityManagement.Models.IIdentityService, EdFi.Ods.Features.IdentityManagement.Models.IdentityResponse>; +using TestIdentityServiceAsync = EdFi.Ods.Features.IdentityManagement.Models.IIdentityServiceAsync, EdFi.Ods.Features.IdentityManagement.Models.IdentityResponse>; +using TestIdentityResponseStatus = EdFi.Ods.Features.IdentityManagement.Models.IdentityResponseStatus>; +using TestIdentitySearchResponse = EdFi.Ods.Features.IdentityManagement.Models.IdentitySearchResponse; +using TestIdentitySearchResponses = EdFi.Ods.Features.IdentityManagement.Models.IdentitySearchResponses; + namespace EdFi.Ods.Tests.EdFi.Ods.Features.Helpers { - public class TestIdentitiesService : IIdentityService, IIdentityServiceAsync + public class TestIdentitiesService : TestIdentityService, TestIdentityServiceAsync { public enum ResponseBehaviour { @@ -22,10 +28,11 @@ public enum ResponseBehaviour NullErrorList } - public IdentityServiceCapabilities IdentityServiceCapabilities => IdentityServiceCapabilities.Create - | IdentityServiceCapabilities.Find - | IdentityServiceCapabilities.Search - | IdentityServiceCapabilities.Results; + public IdentityServiceCapabilities IdentityServiceCapabilities + => IdentityServiceCapabilities.Create + | IdentityServiceCapabilities.Find + | IdentityServiceCapabilities.Search + | IdentityServiceCapabilities.Results; private readonly ResponseBehaviour _responseBehaviour; @@ -39,7 +46,11 @@ public Task> Create(IdentityCreateRequest createR return _responseBehaviour switch { ResponseBehaviour.Success => Task.FromResult( - new IdentityResponseStatus { StatusCode = IdentityStatusCode.Success, Data = "ignored"}), + new IdentityResponseStatus + { + StatusCode = IdentityStatusCode.Success, + Data = "ignored" + }), ResponseBehaviour.InvalidProperties => BuildInvalidResponse(), ResponseBehaviour.Incomplete => BuildIncompleteResponse(), ResponseBehaviour.NotFound => BuildNotFoundResponse(), @@ -53,7 +64,7 @@ public Task> Create(IdentityCreateRequest createR }; } - Task> IIdentityServiceAsync.Find(params string[] findRequest) + Task> TestIdentityServiceAsync.Find(params string[] findRequest) { return _responseBehaviour switch { @@ -66,31 +77,31 @@ Task> IIdentityServiceAsync.Find(params string[] }; } - public Task> Find(params string[] findRequest) + public Task Find(params string[] findRequest) { return _responseBehaviour switch { ResponseBehaviour.Success => Task.FromResult( - new IdentityResponseStatus + new TestIdentityResponseStatus { - Data = new IdentitySearchResponse + Data = new TestIdentitySearchResponse { Status = SearchResponseStatus.Complete, - SearchResponses = new IdentitySearchResponses[] + SearchResponses = new TestIdentitySearchResponses[] { new() {Responses = new[] {new IdentityResponse {Score = 100, UniqueId = "ignored"}}} } }, StatusCode = IdentityStatusCode.Success }), - ResponseBehaviour.InvalidProperties => BuildInvalidResponse(), - ResponseBehaviour.Incomplete => BuildIncompleteResponse(), - ResponseBehaviour.NotFound => BuildNotFoundResponse(), + ResponseBehaviour.InvalidProperties => BuildInvalidResponse(), + ResponseBehaviour.Incomplete => BuildIncompleteResponse(), + ResponseBehaviour.NotFound => BuildNotFoundResponse(), _ => throw new NotImplementedException() }; } - Task> IIdentityServiceAsync.Search(params IdentitySearchRequest[] searchRequest) + Task> TestIdentityServiceAsync.Search(params IdentitySearchRequest[] searchRequest) { return _responseBehaviour switch { @@ -103,31 +114,31 @@ Task> IIdentityServiceAsync.Search(params Identit }; } - public Task> Search(params IdentitySearchRequest[] searchRequest) + public Task Search(params IdentitySearchRequest[] searchRequest) { throw new NotImplementedException(); } - public Task> Response(string requestToken) + public Task Response(string requestToken) { return _responseBehaviour switch { ResponseBehaviour.Success => Task.FromResult( - new IdentityResponseStatus + new TestIdentityResponseStatus { - Data = new IdentitySearchResponse + Data = new TestIdentitySearchResponse { Status = SearchResponseStatus.Complete, - SearchResponses = new IdentitySearchResponses[] + SearchResponses = new TestIdentitySearchResponses[] { new() {Responses = new[] {new IdentityResponse {Score = 100, UniqueId = "ignored" } }} } }, StatusCode = IdentityStatusCode.Success }), - ResponseBehaviour.InvalidProperties => BuildInvalidResponse(), - ResponseBehaviour.Incomplete => BuildIncompleteResponse(), - ResponseBehaviour.NotFound => BuildNotFoundResponse(), + ResponseBehaviour.InvalidProperties => BuildInvalidResponse(), + ResponseBehaviour.Incomplete => BuildIncompleteResponse(), + ResponseBehaviour.NotFound => BuildNotFoundResponse(), _ => throw new NotImplementedException() }; }