Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redirect to systemuser redirectUrl after approving/rejecting change request #927

Merged
merged 6 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -216,30 +216,6 @@ public async Task<ActionResult<ChangeRequestResponse>> GetChangeRequestByGuid(Gu
return NotFound();
}

/// <summary>
/// Retrieves the RedirectURL for the Authn.UI to redirect the user to the correct page
/// based only on the Request.Id GUID
/// </summary>
/// <param name="requestId">The UUID for the Request</param>
/// <param name="cancellationToken">The cancellation token</param>
/// <returns>Status response model CreateRequestSystemUserResponse</returns>
[HttpGet("redirect/{requestId}")]
public async Task<ActionResult<RedirectUrl>> GetRedirectByRequestId(Guid requestId, CancellationToken cancellationToken = default)
{
Result<string> response = await _changeRequestService.GetRedirectByChangeRequestId(requestId);
if (response.IsProblem)
{
return response.Problem.ToActionResult();
}

if (response.IsSuccess)
{
return Ok(new RedirectUrl() { Url = response.Value });
}

return NotFound();
}

/// <summary>
/// Retrieves the Status (Response model) for a Request
/// based on the SystemId, OrgNo and the ExternalRef
Expand Down
12 changes: 10 additions & 2 deletions src/Authentication/Controllers/LogoutController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class LogoutController : ControllerBase
private readonly IEventLog _eventLog;
private readonly IFeatureManager _featureManager;
private readonly IRequestSystemUser _requestSystemUser;
private readonly IChangeRequestSystemUser _changeRequestSystemUser;

/// <summary>
/// Defay
Expand All @@ -46,17 +47,18 @@ public LogoutController(
ILogger<LogoutController> logger,
IOptions<GeneralSettings> generalSettings,
IOptions<OidcProviderSettings> oidcProviderSettings,
IOidcProvider oidcProvider,
IEventLog eventLog,
IFeatureManager featureManager,
IRequestSystemUser requestSystemUser)
IRequestSystemUser requestSystemUser,
IChangeRequestSystemUser changeRequestSystemUser)
{
_generalSettings = generalSettings.Value;
_oidcProviderSettings = oidcProviderSettings.Value;
_validator = new JwtSecurityTokenHandler();
_eventLog = eventLog;
_featureManager = featureManager;
_requestSystemUser = requestSystemUser;
_changeRequestSystemUser = changeRequestSystemUser;
}

/// <summary>
Expand Down Expand Up @@ -113,6 +115,12 @@ public async Task<ActionResult> HandleLoggedOut()
return Redirect(redirectUrl.Value);
}

if (cookieValues != null && cookieValues.TryGetValue("SystemuserChangeRequestId", out string changeRequestId) && Guid.TryParse(changeRequestId, out Guid changeRequestGuid))
{
Result<string> redirectUrl = await _changeRequestSystemUser.GetRedirectByChangeRequestId(changeRequestGuid);
return Redirect(redirectUrl.Value);
}

return Redirect(_generalSettings.SBLLogoutEndpoint);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1094,139 +1094,6 @@ public async Task ChangeRequest_GetStatusByExternalIds_ReturnOk()
Assert.Equal(ChangeRequestStatus.New.ToString(), statusResponse.Status);
}

/// <summary>
/// After having verified that the ChangeRequest is needed, create a ChangeRequest, then approve it
/// </summary>
[Fact]
public async Task ChangeRequest_FrontEnd_GetRedirect_ReturnOk()
{
List<XacmlJsonResult> xacmlJsonResults = GetDecisionResultSingle();

_pdpMock.Setup(p => p.GetDecisionForRequest(It.IsAny<XacmlJsonRequestRoot>())).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<RequestSystemResponse>();
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<XacmlJsonRequestRoot>())).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<ChangeRequestResponse>();
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<XacmlJsonRequestRoot>())).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<RedirectUrl>();
Assert.NotNull(redirectUrlDTO);
Assert.Equal(change.RedirectUrl, redirectUrlDTO.Url);
}

/// <summary>
/// After having verified that the ChangeRequest is needed, create a ChangeRequest, then approve it
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ protected override void ConfigureServices(IServiceCollection services)
services.AddSingleton<IEnterpriseUserAuthenticationService, EnterpriseUserAuthenticationServiceMock>();
services.AddSingleton<IOidcProvider, OidcProviderServiceMock>();
services.AddSingleton<IRequestSystemUser, RequestSystemUserServiceMock>();
services.AddSingleton<IChangeRequestSystemUser, ChangeRequestSystemUserServiceMock>();
services.AddSingleton(_featureManager.Object);
services.AddSingleton(_eventQueue.Object);
services.AddSingleton(_timeProviderMock.Object);
Expand Down Expand Up @@ -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();
Expand All @@ -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<string> 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<string> 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<string> locationValues);
Assert.Equal("https://smartcloudaltinn.azurewebsites.net/changerequest", locationValues?.First());
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// The service that supports the SystemUser CRUD APIcontroller
/// </summary>
[ExcludeFromCodeCoverage]
public class ChangeRequestSystemUserServiceMock : IChangeRequestSystemUser
{
/// <summary>
/// The Constructor
/// </summary>
public ChangeRequestSystemUserServiceMock()
{
}

public Task<Result<bool>> ApproveAndDelegateChangeOnSystemUser(Guid requestId, int partyId, int userId, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

public Task<Result<ChangeRequestResponse>> CreateChangeRequest(ChangeRequestSystemUser createRequest, OrganisationNumber vendorOrgNo)
{
throw new NotImplementedException();
}

public Task<Result<bool>> DeleteChangeRequestByRequestId(Guid requestId)
{
throw new NotImplementedException();
}

public Task<Result<Page<ChangeRequestResponse, Guid>>> GetAllChangeRequestsForVendor(OrganisationNumber vendorOrgNo, string systemId, Page<Guid>.Request continueRequest, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

public Task<Result<ChangeRequestResponse>> GetChangeRequestByExternalRef(ExternalRequestId externalRequestId, OrganisationNumber vendorOrgNo)
{
throw new NotImplementedException();
}

public Task<Result<ChangeRequestResponse>> GetChangeRequestByGuid(Guid requestId, OrganisationNumber vendorOrgNo)
{
throw new NotImplementedException();
}

public Task<Result<ChangeRequestResponse>> GetChangeRequestByPartyAndRequestId(int party, Guid requestId)
{
throw new NotImplementedException();
}

public async Task<Result<string>> GetRedirectByChangeRequestId(Guid requestId)
{
return await Task.FromResult("https://smartcloudaltinn.azurewebsites.net/changerequest");
}

public Task<Result<bool>> RejectChangeOnSystemUser(Guid requestId, int userId, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

public Task<Result<ChangeRequestResponse>> VerifySetOfRights(ChangeRequestSystemUser validateSet, OrganisationNumber vendorOrgNo)
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public Task<Result<Page<RequestSystemResponse, Guid>>> GetAllRequestsForVendor(O

public async Task<Result<string>> GetRedirectByRequestId(Guid requestId)
{
return await Task.FromResult("https://smartcloudaltinn.azurewebsites.net/");
return await Task.FromResult("https://smartcloudaltinn.azurewebsites.net/request");
}

public Task<Result<RequestSystemResponse>> GetRequestByExternalRef(ExternalRequestId externalRequestId, OrganisationNumber vendorOrgNo)
Expand Down
Loading