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

Endpoint for fetching current party roles #983

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
124 changes: 78 additions & 46 deletions src/Altinn.App.Api/Controllers/AuthorizationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using Altinn.App.Core.Internal.Profile;
using Altinn.App.Core.Internal.Registers;
using Altinn.App.Core.Models;
using Altinn.Platform.Register.Models;
using Authorization.Platform.Authorization.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
Expand Down Expand Up @@ -44,57 +46,14 @@
[HttpGet("{org}/{app}/api/authorization/parties/current")]
public async Task<ActionResult> GetCurrentParty(bool returnPartyObject = false)
{
UserContext userContext = await _userHelper.GetUserContext(HttpContext);
int userId = userContext.UserId;

// If selected party is different than party for user self need to verify
if (userContext.UserParty == null || userContext.PartyId != userContext.UserParty.PartyId)
{
bool? isValid = await _authorization.ValidateSelectedParty(userId, userContext.PartyId);

if (isValid == true)
{
if (returnPartyObject)
{
return Ok(userContext.Party);
}

return Ok(userContext.PartyId);
}
else if (userContext.UserParty != null)
{
userContext.Party = userContext.UserParty;
userContext.PartyId = userContext.UserParty.PartyId;
}
else
{
userContext.Party = null;
userContext.PartyId = 0;
}
}

string? cookieValue = Request.Cookies[_settings.GetAltinnPartyCookieName];
if (!int.TryParse(cookieValue, out int partyIdFromCookie))
{
partyIdFromCookie = 0;
}

// Setting cookie to partyID of logged in user if it varies from previus value.
if (partyIdFromCookie != userContext.PartyId)
{
Response.Cookies.Append(
_settings.GetAltinnPartyCookieName,
userContext.PartyId.ToString(CultureInfo.InvariantCulture),
new CookieOptions { Domain = _settings.HostName }
);
}
Party? currentParty = await GetCurrentPartyAsync(HttpContext);

if (returnPartyObject)
{
return Ok(userContext.Party);
return Ok(currentParty);
}

return Ok(userContext.PartyId);
return Ok(currentParty?.PartyId ?? 0);
}

/// <summary>
Expand Down Expand Up @@ -123,4 +82,77 @@
return StatusCode(500, $"Something went wrong when trying to validate party {partyId} for user {userId}");
}
}

/// <summary>
/// Fetches roles for current party.
/// </summary>
/// <returns>Boolean indicating if the selected party is valid.</returns>
[Authorize]
[HttpGet("{org}/{app}/api/authorization/roles")]
public async Task<IActionResult> FetchRolesForCurrentParty()
adamhaeger marked this conversation as resolved.
Show resolved Hide resolved
{
Party? currentParty = await GetCurrentPartyAsync(HttpContext);
UserContext userContext = await _userHelper.GetUserContext(HttpContext);
int userId = userContext.UserId;
adamhaeger marked this conversation as resolved.
Show resolved Hide resolved

if (currentParty == null)
{
return BadRequest("Both userId and partyId must be provided.");
}

List<Role> roles = await _authorization.GetUserRolesAsync(userId, currentParty.PartyId);

Check failure on line 103 in src/Altinn.App.Api/Controllers/AuthorizationController.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (macos-latest)

Converting null literal or possible null value to non-nullable type.

Check failure on line 103 in src/Altinn.App.Api/Controllers/AuthorizationController.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (macos-latest)

Converting null literal or possible null value to non-nullable type.

Check failure on line 103 in src/Altinn.App.Api/Controllers/AuthorizationController.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Converting null literal or possible null value to non-nullable type.

Check failure on line 103 in src/Altinn.App.Api/Controllers/AuthorizationController.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Converting null literal or possible null value to non-nullable type.

Check failure on line 103 in src/Altinn.App.Api/Controllers/AuthorizationController.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

Converting null literal or possible null value to non-nullable type.

Check failure on line 103 in src/Altinn.App.Api/Controllers/AuthorizationController.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (ubuntu-latest)

Converting null literal or possible null value to non-nullable type.

Check failure on line 103 in src/Altinn.App.Api/Controllers/AuthorizationController.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (ubuntu-latest)

Converting null literal or possible null value to non-nullable type.

// TODO: implement actual logic here using currentParty
adamhaeger marked this conversation as resolved.
Show resolved Hide resolved
// For now, return false as before
return Ok(roles);
}

/// <summary>
/// Helper method to retrieve the current party from the HTTP context.
/// </summary>
/// <param name="context">The current HttpContext.</param>
/// <returns>The current party or null if none could be determined.</returns>
private async Task<Party?> GetCurrentPartyAsync(HttpContext context)
{
UserContext userContext = await _userHelper.GetUserContext(context);
int userId = userContext.UserId;

// If selected party is different than party for user self need to verify
if (userContext.UserParty == null || userContext.PartyId != userContext.UserParty.PartyId)
{
bool? isValid = await _authorization.ValidateSelectedParty(userId, userContext.PartyId);
if (isValid != true)
{
// Not valid, fall back to userParty if available
if (userContext.UserParty != null)
{
userContext.Party = userContext.UserParty;
userContext.PartyId = userContext.UserParty.PartyId;
}
else
{
userContext.Party = null;
userContext.PartyId = 0;
}
}
}

// Sync cookie if needed
string? cookieValue = Request.Cookies[_settings.GetAltinnPartyCookieName];
if (!int.TryParse(cookieValue, out int partyIdFromCookie))
{
partyIdFromCookie = 0;
}

if (partyIdFromCookie != userContext.PartyId)
{
Response.Cookies.Append(
_settings.GetAltinnPartyCookieName,
userContext.PartyId.ToString(CultureInfo.InvariantCulture),
new CookieOptions { Domain = _settings.HostName }
);
}

return userContext.Party;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Altinn.Platform.Register.Models;
using Altinn.Platform.Storage.Interface.Models;
using AltinnCore.Authentication.Utils;
using Authorization.Platform.Authorization.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
Expand Down Expand Up @@ -179,4 +180,47 @@ List<string> actions
}
return MultiDecisionHelper.ValidatePdpMultiDecision(actionsResult, response.Response, user);
}

/// <summary>
/// Retrieves roles for a user on a specified party.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="userPartyId">The user party id.</param>
/// <returns>A list of roles for the user on the specified party.</returns>
public async Task<List<Role>?> GetUserRolesAsync(int userId, int userPartyId)
{
List<Role>? roles = null;
string apiUrl = $"roles?coveredByUserId={userId}&offeredByPartyId={userPartyId}";
string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _settings.RuntimeCookieName);

try
{
HttpResponseMessage response = await _client.GetAsync(token, apiUrl);
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
roles = JsonConvert.DeserializeObject<List<Role>>(responseContent);
}
else
{
_logger.LogError(
"Failed to retrieve roles for userId {UserId} and partyId {PartyId}. StatusCode: {StatusCode}",
userId,
userPartyId,
response.StatusCode
);
}
}
catch (Exception ex)
{
_logger.LogError(
ex,
"An error occurred while retrieving roles for userId {UserId} and partyId {PartyId}",
userId,
userPartyId
);
}

return roles;
}
}
9 changes: 9 additions & 0 deletions src/Altinn.App.Core/Internal/Auth/IAuthorizationClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Altinn.App.Core.Models;
using Altinn.Platform.Register.Models;
using Altinn.Platform.Storage.Interface.Models;
using Authorization.Platform.Authorization.Models;

namespace Altinn.App.Core.Internal.Auth;

Expand Down Expand Up @@ -50,4 +51,12 @@ Task<bool> AuthorizeAction(
/// <param name="actions"></param>
/// <returns></returns>
Task<Dictionary<string, bool>> AuthorizeActions(Instance instance, ClaimsPrincipal user, List<string> actions);

/// <summary>
/// Retrieves roles for a user on a specified party.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="userPartyId">The user party id.</param>
/// <returns>A list of roles for the user on the specified party.</returns>
Task<List<Role>?> GetUserRolesAsync(int userId, int userPartyId);
}
Loading