From 0d3b15436eba456c6df7515f7ed0a8f1e6d1db18 Mon Sep 17 00:00:00 2001 From: Martin Gunnerud Date: Sun, 17 Nov 2024 19:18:32 +0100 Subject: [PATCH 1/5] add redirect to vendor after approve/reject change request --- src/Authentication/Controllers/LogoutController.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Authentication/Controllers/LogoutController.cs b/src/Authentication/Controllers/LogoutController.cs index 550679c5..db836c0d 100644 --- a/src/Authentication/Controllers/LogoutController.cs +++ b/src/Authentication/Controllers/LogoutController.cs @@ -38,6 +38,7 @@ public class LogoutController : ControllerBase private readonly IEventLog _eventLog; private readonly IFeatureManager _featureManager; private readonly IRequestSystemUser _requestSystemUser; + private readonly IChangeRequestSystemUser _changeRequestSystemUser; /// /// Defay @@ -49,7 +50,8 @@ public LogoutController( IOidcProvider oidcProvider, IEventLog eventLog, IFeatureManager featureManager, - IRequestSystemUser requestSystemUser) + IRequestSystemUser requestSystemUser, + IChangeRequestSystemUser changeRequestSystemUser) { _generalSettings = generalSettings.Value; _oidcProviderSettings = oidcProviderSettings.Value; @@ -57,6 +59,7 @@ public LogoutController( _eventLog = eventLog; _featureManager = featureManager; _requestSystemUser = requestSystemUser; + _changeRequestSystemUser = changeRequestSystemUser; } /// @@ -113,6 +116,12 @@ public async Task HandleLoggedOut() return Redirect(redirectUrl.Value); } + if (cookieValues != null && cookieValues.TryGetValue("SystemuserChangeRequestId", out string changeRequestId) && Guid.TryParse(changeRequestId, out Guid changeRequestGuid)) + { + Result redirectUrl = await _changeRequestSystemUser.GetRedirectByChangeRequestId(changeRequestGuid); + return Redirect(redirectUrl.Value); + } + return Redirect(_generalSettings.SBLLogoutEndpoint); } From 001b7d9a4ff7a4815a8df76265ba4788d29d6832 Mon Sep 17 00:00:00 2001 From: Martin Gunnerud Date: Thu, 5 Dec 2024 12:29:51 +0100 Subject: [PATCH 2/5] add test for logout and redirect after approving systemuser change request --- .../Controllers/LogoutControllerTests.cs | 27 ++++++- .../ChangeRequestSystemUserServiceMock.cs | 76 +++++++++++++++++++ .../Mocks/RequestSystemUserServiceMock.cs | 2 +- 3 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 test/Altinn.Platform.Authentication.Tests/Mocks/ChangeRequestSystemUserServiceMock.cs diff --git a/test/Altinn.Platform.Authentication.Tests/Controllers/LogoutControllerTests.cs b/test/Altinn.Platform.Authentication.Tests/Controllers/LogoutControllerTests.cs index 988e5759..be5ee955 100644 --- a/test/Altinn.Platform.Authentication.Tests/Controllers/LogoutControllerTests.cs +++ b/test/Altinn.Platform.Authentication.Tests/Controllers/LogoutControllerTests.cs @@ -90,6 +90,7 @@ protected override void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(_featureManager.Object); services.AddSingleton(_eventQueue.Object); services.AddSingleton(_timeProviderMock.Object); @@ -267,7 +268,7 @@ public async Task Logout_LogedIn_RedirectToIss() } [Fact] - public async Task Logout_HandleLoggedOut_RedirectToRedirectUrl() + public async Task Logout_HandleLoggedOut_RedirectToRequestRedirectUrl() { // Arrange HttpClient client = CreateClient(); @@ -285,7 +286,29 @@ public async Task Logout_HandleLoggedOut_RedirectToRedirectUrl() Assert.Equal("AltinnLogoutInfo=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=localhost; path=/; secure; httponly", cookieValues?.First()); response.Headers.TryGetValues("location", out IEnumerable locationValues); - Assert.Equal("https://smartcloudaltinn.azurewebsites.net/", locationValues?.First()); + Assert.Equal("https://smartcloudaltinn.azurewebsites.net/request", locationValues?.First()); + } + + [Fact] + public async Task Logout_HandleLoggedOut_RedirectToChangeRequestRedirectUrl() + { + // Arrange + HttpClient client = CreateClient(); + + HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, "/authentication/api/v1/logout/handleloggedout"); + requestMessage.Headers.Add("Cookie", "AltinnLogoutInfo=SystemuserChangeRequestId=c0970300-005c-4784-aea6-5e7bac61b9b1"); + + // Act + HttpResponseMessage response = await client.SendAsync(requestMessage); + + // Assert + Assert.Equal(System.Net.HttpStatusCode.Found, response.StatusCode); + + response.Headers.TryGetValues("Set-Cookie", out IEnumerable cookieValues); + Assert.Equal("AltinnLogoutInfo=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=localhost; path=/; secure; httponly", cookieValues?.First()); + + response.Headers.TryGetValues("location", out IEnumerable locationValues); + Assert.Equal("https://smartcloudaltinn.azurewebsites.net/changerequest", locationValues?.First()); } [Fact] diff --git a/test/Altinn.Platform.Authentication.Tests/Mocks/ChangeRequestSystemUserServiceMock.cs b/test/Altinn.Platform.Authentication.Tests/Mocks/ChangeRequestSystemUserServiceMock.cs new file mode 100644 index 00000000..c7679f64 --- /dev/null +++ b/test/Altinn.Platform.Authentication.Tests/Mocks/ChangeRequestSystemUserServiceMock.cs @@ -0,0 +1,76 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Authorization.ProblemDetails; +using Altinn.Platform.Authentication.Core.Models; +using Altinn.Platform.Authentication.Core.Models.Parties; +using Altinn.Platform.Authentication.Core.Models.SystemUsers; +using Altinn.Platform.Authentication.Services.Interfaces; + +namespace Altinn.Platform.Authentication.Tests.Mocks +{ + /// + /// The service that supports the SystemUser CRUD APIcontroller + /// + [ExcludeFromCodeCoverage] + public class ChangeRequestSystemUserServiceMock : IChangeRequestSystemUser + { + /// + /// The Constructor + /// + public ChangeRequestSystemUserServiceMock() + { + } + + public Task> ApproveAndDelegateChangeOnSystemUser(Guid requestId, int partyId, int userId, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> CreateChangeRequest(ChangeRequestSystemUser createRequest, OrganisationNumber vendorOrgNo) + { + throw new NotImplementedException(); + } + + public Task> DeleteChangeRequestByRequestId(Guid requestId) + { + throw new NotImplementedException(); + } + + public Task>> GetAllChangeRequestsForVendor(OrganisationNumber vendorOrgNo, string systemId, Page.Request continueRequest, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> GetChangeRequestByExternalRef(ExternalRequestId externalRequestId, OrganisationNumber vendorOrgNo) + { + throw new NotImplementedException(); + } + + public Task> GetChangeRequestByGuid(Guid requestId, OrganisationNumber vendorOrgNo) + { + throw new NotImplementedException(); + } + + public Task> GetChangeRequestByPartyAndRequestId(int party, Guid requestId) + { + throw new NotImplementedException(); + } + + public async Task> GetRedirectByChangeRequestId(Guid requestId) + { + return await Task.FromResult("https://smartcloudaltinn.azurewebsites.net/changerequest"); + } + + public Task> RejectChangeOnSystemUser(Guid requestId, int userId, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> VerifySetOfRights(ChangeRequestSystemUser validateSet, OrganisationNumber vendorOrgNo) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/test/Altinn.Platform.Authentication.Tests/Mocks/RequestSystemUserServiceMock.cs b/test/Altinn.Platform.Authentication.Tests/Mocks/RequestSystemUserServiceMock.cs index cb8f0b5e..2c3286a8 100644 --- a/test/Altinn.Platform.Authentication.Tests/Mocks/RequestSystemUserServiceMock.cs +++ b/test/Altinn.Platform.Authentication.Tests/Mocks/RequestSystemUserServiceMock.cs @@ -45,7 +45,7 @@ public Task>> GetAllRequestsForVendor(O public async Task> GetRedirectByRequestId(Guid requestId) { - return await Task.FromResult("https://smartcloudaltinn.azurewebsites.net/"); + return await Task.FromResult("https://smartcloudaltinn.azurewebsites.net/request"); } public Task> GetRequestByExternalRef(ExternalRequestId externalRequestId, OrganisationNumber vendorOrgNo) From 76d991378436c129659859b5965071dc2727576a Mon Sep 17 00:00:00 2001 From: Martin Gunnerud Date: Thu, 5 Dec 2024 13:04:57 +0100 Subject: [PATCH 3/5] remove unneeded constructor parameter --- src/Authentication/Controllers/LogoutController.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Authentication/Controllers/LogoutController.cs b/src/Authentication/Controllers/LogoutController.cs index db836c0d..76c2f0f4 100644 --- a/src/Authentication/Controllers/LogoutController.cs +++ b/src/Authentication/Controllers/LogoutController.cs @@ -47,7 +47,6 @@ public LogoutController( ILogger logger, IOptions generalSettings, IOptions oidcProviderSettings, - IOidcProvider oidcProvider, IEventLog eventLog, IFeatureManager featureManager, IRequestSystemUser requestSystemUser, From 553f1dcecc4308c3047e6e04b51409cdc02335be Mon Sep 17 00:00:00 2001 From: Martin Gunnerud Date: Thu, 5 Dec 2024 13:13:07 +0100 Subject: [PATCH 4/5] remove unused service --- .../ChangeRequestSystemUserController.cs | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/src/Authentication/Controllers/ChangeRequestSystemUserController.cs b/src/Authentication/Controllers/ChangeRequestSystemUserController.cs index 92f03ba6..2e7c0b29 100644 --- a/src/Authentication/Controllers/ChangeRequestSystemUserController.cs +++ b/src/Authentication/Controllers/ChangeRequestSystemUserController.cs @@ -216,30 +216,6 @@ public async Task> GetChangeRequestByGuid(Gu return NotFound(); } - /// - /// Retrieves the RedirectURL for the Authn.UI to redirect the user to the correct page - /// based only on the Request.Id GUID - /// - /// The UUID for the Request - /// The cancellation token - /// Status response model CreateRequestSystemUserResponse - [HttpGet("redirect/{requestId}")] - public async Task> GetRedirectByRequestId(Guid requestId, CancellationToken cancellationToken = default) - { - Result response = await _changeRequestService.GetRedirectByChangeRequestId(requestId); - if (response.IsProblem) - { - return response.Problem.ToActionResult(); - } - - if (response.IsSuccess) - { - return Ok(new RedirectUrl() { Url = response.Value }); - } - - return NotFound(); - } - /// /// Retrieves the Status (Response model) for a Request /// based on the SystemId, OrgNo and the ExternalRef From f5ab7e5a1175bbc59b8b53bf9dd61a96c7f92e7d Mon Sep 17 00:00:00 2001 From: Martin Gunnerud Date: Thu, 5 Dec 2024 13:37:31 +0100 Subject: [PATCH 5/5] remove test --- .../ChangeRequestControllerTest.cs | 133 ------------------ 1 file changed, 133 deletions(-) diff --git a/test/Altinn.Platform.Authentication.Tests/Controllers/ChangeRequestControllerTest.cs b/test/Altinn.Platform.Authentication.Tests/Controllers/ChangeRequestControllerTest.cs index db83780d..39305d89 100644 --- a/test/Altinn.Platform.Authentication.Tests/Controllers/ChangeRequestControllerTest.cs +++ b/test/Altinn.Platform.Authentication.Tests/Controllers/ChangeRequestControllerTest.cs @@ -1094,139 +1094,6 @@ public async Task ChangeRequest_GetStatusByExternalIds_ReturnOk() Assert.Equal(ChangeRequestStatus.New.ToString(), statusResponse.Status); } - /// - /// After having verified that the ChangeRequest is needed, create a ChangeRequest, then approve it - /// - [Fact] - public async Task ChangeRequest_FrontEnd_GetRedirect_ReturnOk() - { - List xacmlJsonResults = GetDecisionResultSingle(); - - _pdpMock.Setup(p => p.GetDecisionForRequest(It.IsAny())).ReturnsAsync(new XacmlJsonResponse - { - Response = xacmlJsonResults - }); - - // Create System used for test - string dataFileName = "Data/SystemRegister/Json/SystemRegister2Rights.json"; - HttpResponseMessage response = await CreateSystemRegister(dataFileName); - - HttpClient client = CreateClient(); - string token = AddSystemUserRequestWriteTestTokenToClient(client); - string endpoint = $"/authentication/api/v1/systemuser/request/vendor"; - - Right right = new() - { - Resource = - [ - new AttributePair() - { - Id = "urn:altinn:resource", - Value = "ske-krav-og-betalinger" - } - ] - }; - - Right right2 = new() - { - Resource = - [ - new AttributePair() - { - Id = "urn:altinn:resource", - Value = "ske-krav-og-betalinger-2" - } - ] - }; - - // Arrange - CreateRequestSystemUser req = new() - { - ExternalRef = "external", - SystemId = "991825827_the_matrix", - PartyOrgNo = "910493353", - Rights = [right], - RedirectUrl = "https://altinn.no" - }; - - HttpRequestMessage request = new(HttpMethod.Post, endpoint) - { - Content = JsonContent.Create(req) - }; - HttpResponseMessage message = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); - - Assert.Equal(HttpStatusCode.Created, message.StatusCode); - - RequestSystemResponse? res = await message.Content.ReadFromJsonAsync(); - Assert.NotNull(res); - Assert.Equal(req.ExternalRef, res.ExternalRef); - - // Party Get Request - HttpClient client2 = CreateClient(); - client2.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", PrincipalUtil.GetToken(1337, null, 3)); - - int partyId = 500000; - - // Approve the SystemUser - string approveEndpoint = $"/authentication/api/v1/systemuser/request/{partyId}/{res.Id}/approve"; - HttpRequestMessage approveRequestMessage = new(HttpMethod.Post, approveEndpoint); - HttpResponseMessage approveResponseMessage = await client2.SendAsync(approveRequestMessage, HttpCompletionOption.ResponseHeadersRead); - Assert.Equal(HttpStatusCode.OK, approveResponseMessage.StatusCode); - - xacmlJsonResults = GetDecisionResultListNotAllPermit(); - - _pdpMock.Setup(p => p.GetDecisionForRequest(It.IsAny())).ReturnsAsync(new XacmlJsonResponse - { - Response = xacmlJsonResults - }); - - // ChangeRequest create - string createChangeRequestEndpoint = $"/authentication/api/v1/systemuser/changerequest/vendor/"; - - ChangeRequestSystemUser change = new() - { - ExternalRef = "external", - SystemId = "991825827_the_matrix", - PartyOrgNo = "910493353", - RequiredRights = [right2], - UnwantedRights = [], - RedirectUrl = "https://altinn.no" - }; - - HttpRequestMessage createChangeRequestMessage = new(HttpMethod.Post, createChangeRequestEndpoint) - { - Content = JsonContent.Create(change) - }; - HttpResponseMessage createdResponseMessage = await client.SendAsync(createChangeRequestMessage, HttpCompletionOption.ResponseHeadersRead); - Assert.Equal(HttpStatusCode.Created, createdResponseMessage.StatusCode); - - ChangeRequestResponse? createdResponse = await createdResponseMessage.Content.ReadFromJsonAsync(); - Assert.NotNull(createdResponse); - Assert.NotEmpty(createdResponse.RequiredRights); - Assert.True(DeepCompare(createdResponse.RequiredRights, change.RequiredRights)); - - // works up to here - xacmlJsonResults = GetDecisionResultSingle(); - _pdpMock.Setup(p => p.GetDecisionForRequest(It.IsAny())).ReturnsAsync(new XacmlJsonResponse - { - Response = xacmlJsonResults - }); - - // Reject the Change Request - string requestId = createdResponse.Id.ToString(); - HttpClient client3 = CreateClient(); - - string statusChangeRequestEndpoint = $"/authentication/api/v1/systemuser/changerequest/redirect/{requestId}"; - HttpRequestMessage statusChangeRequestMessage = new(HttpMethod.Get, statusChangeRequestEndpoint); - HttpResponseMessage statusChangeResponseMessage = await client3.SendAsync(statusChangeRequestMessage, HttpCompletionOption.ResponseHeadersRead); - Assert.Equal(HttpStatusCode.OK, statusChangeResponseMessage.StatusCode); - - Assert.NotNull(statusChangeResponseMessage.Content); - RedirectUrl redirectUrlDTO = await statusChangeResponseMessage.Content.ReadFromJsonAsync(); - Assert.NotNull(redirectUrlDTO); - Assert.Equal(change.RedirectUrl, redirectUrlDTO.Url); - } - /// /// After having verified that the ChangeRequest is needed, create a ChangeRequest, then approve it ///