Skip to content

Commit

Permalink
L2 get vendor request (#372)
Browse files Browse the repository at this point in the history
* init branch, Request Controller

* service and client

* init client

* bugfix

* housekeeping

* comment fix
  • Loading branch information
simen-rekkedal authored Sep 19, 2024
1 parent ade991f commit d083d89
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Altinn.Authorization.ProblemDetails;

namespace Altinn.Authentication.UI.Core.SystemUsers;

public interface IRequestClient
{
Task<Result<VendorRequest>> GetVendorRequest(int partyId, Guid requestId, CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Altinn.Authorization.ProblemDetails;

namespace Altinn.Authentication.UI.Core.SystemUsers;

public interface IRequestService
{
Task<Result<VendorRequest>> GetVendorRequest(int partyId, Guid requestId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Altinn.Authorization.ProblemDetails;

namespace Altinn.Authentication.UI.Core.SystemUsers;

/// <summary>
/// Request Service
/// </summary>
/// <param name="requestClient">The client</param>
internal class RequestService(
IRequestClient requestClient
) : IRequestService
{
public Task<Result<VendorRequest>> GetVendorRequest(int partyId, Guid requestId)
{
return requestClient.GetVendorRequest(partyId, requestId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Altinn.Authentication.UI.Core.Common.Rights;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;

namespace Altinn.Authentication.UI.Core.SystemUsers;

/// <summary>
/// Response DTO through the API after Vendor calls to Create a new Request for a SystemUser
/// </summary>
public class VendorRequest
{
/// <summary>
/// Guid in the format of a UUID-v4 Id generated by us; also will be reused by the SystemUser when it is approved.
/// We use a Guid rather than the External Request Id, to facilitate Db administration and the possiblity to delete and renew a SystemUser.
/// </summary>
[Required]
[JsonPropertyName("id")]
public Guid Id { get; set; }

/// <summary>
/// Either just the Orgno for the customer, or a TenantId or other form of disambiguation Id the Vendor needs.
/// Is one of the three parts of the External Request Id.
/// A blank ExternalRef will be overwritten as a copy of the Cutomer's OrgNo
/// </summary>
[JsonPropertyName("externalRef")]
public string? ExternalRef { get; set; }

/// <summary>
/// The Id for the Registered System that this Request will be based on.
/// Is one of the three parts of the External Request Id.
/// </summary>
[Required]
[JsonPropertyName("systemId")]
public string SystemId { get; set; }

/// <summary>
/// The organisation number for the SystemUser's Party ( the customer that delegates rights to the systemuser).
/// Is one of the three parts of the External Request Id.
/// </summary>
[Required]
[JsonPropertyName("partyOrgNo")]
public string PartyOrgNo { get; set; }

/// <summary>
/// The set of Rights requested for this system user. Must be equal to or less than the set defined in the Registered System.
/// Must be a minimum of 1 selected Right.
/// </summary>
[Required]
[JsonPropertyName("rights")]
public List<Right> Rights { get; set; }

/// <summary>
/// Initially the request is "new",
/// other values are "accepted", "rejected", "denied"
/// </summary>
[Required]
[JsonPropertyName("status")]
public string Status { get; set; }

/// <summary>
/// Optional redirect URL to navigate to after the customer has accepted/denied the Request
/// </summary>
[JsonPropertyName("redirectUrl")]
public string? RedirectUrl { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Altinn.Authentication.UI.Core.Authentication;
using Altinn.Authentication.UI.Core.SystemUsers;
using Altinn.Authentication.UI.Integration.AccessToken;
using Altinn.Authentication.UI.Integration.Configuration;
using Altinn.Authorization.ProblemDetails;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Altinn.Authentication.UI.Core.Extensions;
using System.Text.Json;
using Altinn.Authentication.UI.Core.Common.Problems;

namespace Altinn.Authentication.UI.Integration.SystemUsers;

public class RequestClient(
HttpClient client,
IOptions<PlatformSettings> optionsPlatformSetting,
IHttpContextAccessor httpContext
) : IRequestClient
{
private readonly JsonSerializerOptions _jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };

private string InitClient()
{
client.BaseAddress = new(optionsPlatformSetting.Value.ApiAuthenticationEndpoint!);
client.DefaultRequestHeaders.Add(optionsPlatformSetting.Value.SubscriptionKeyHeaderName, optionsPlatformSetting.Value.SubscriptionKey);
return JwtTokenUtil.GetTokenFromContext(httpContext.HttpContext!, optionsPlatformSetting.Value.JwtCookieName!)!;
}

public async Task<Result<VendorRequest>> GetVendorRequest(int partyId, Guid requestId, CancellationToken cancellationToken)
{
string endpoint = $"systemuser/request/{partyId}/{requestId}";
HttpResponseMessage res = await client.GetAsync(InitClient(), endpoint);

if (res.IsSuccessStatusCode)
{
var val = JsonSerializer.Deserialize<VendorRequest>(await res.Content.ReadAsStringAsync(cancellationToken), _jsonSerializerOptions);
if (val is null)
{
return Problem.Generic_EndOfMethod;
}

return val;
}

return Problem.Generic_EndOfMethod;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Altinn.Authentication.UI.Core.Authentication;
using Altinn.Authentication.UI.Core.SystemUsers;
using Altinn.Authentication.UI.Filters;
using Altinn.Authorization.ProblemDetails;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http.Headers;

/// <summary>
/// API for the Frontend to fetch a Request then reject or approve it.
/// The adminstration ( CRUD API ) of Requests are done by Vendors directly towards the Authentication component.
/// </summary>

[Route("authfront/api/v1/systemuser/request")]
[ApiController]
[AutoValidateAntiforgeryTokenIfAuthCookie]
public class RequestController(
IRequestService _requestService) : ControllerBase
{
/// <summary>
/// Gets a VendorRequest by Id
/// </summary>
/// <returns></returns>
[Authorize]
[HttpGet("{requestId}")]
public async Task<ActionResult> GetRequestByPartyIdAndRequestId(Guid requestId)
{
int partyId = AuthenticationHelper.GetRepresentingPartyId(HttpContext);
if (partyId == 0)
{
return BadRequest("PartyId not provided in the context.");
}

Result<VendorRequest> req = await _requestService.GetVendorRequest(partyId, requestId);
if (req.IsProblem)
{
return req.Problem.ToActionResult();
}

return Ok(req.Value);
}
}

0 comments on commit d083d89

Please sign in to comment.