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

add auth to all legacy enpoints #468

Merged
merged 3 commits into from
Nov 8, 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 @@ -16,7 +16,6 @@ internal static LegacyGetCorrespondencesRequest MapToRequest(LegacyGetCorrespond
IncludeArchived = requestExt.IncludeArchived,
IncludeDeleted = requestExt.IncludeDeleted,
InstanceOwnerPartyIdList = requestExt.InstanceOwnerPartyIdList,
OnbehalfOfPartyId = requestExt.OnbehalfOfPartyId,
Offset = requestExt.Offset,
Limit = requestExt.Limit,
Language = requestExt.Language,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ public class LegacyGetCorrespondencesRequestExt
[JsonPropertyName("limit")]
public int Limit { get; set; }

/// <summary>
/// PartyId of the end user performing the search
/// </summary>
[JsonPropertyName("onbehalfOfPartyId")]
public required int OnbehalfOfPartyId { get; set; }

/// <summary>
/// A list of the parties/recipients that own the Correspondence instances
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,14 @@ public async Task<OneOf<LegacyGetCorrespondencesResponse, Error>> Process(Legacy
var limit = request.Limit == 0 ? 50 : request.Limit;
DateTimeOffset? to = request.To != null ? ((DateTimeOffset)request.To).ToUniversalTime() : null;
DateTimeOffset? from = request.From != null ? ((DateTimeOffset)request.From).ToUniversalTime() : null;

// Verify and map partyId for user
if (request.OnbehalfOfPartyId == 0 || request.OnbehalfOfPartyId == int.MinValue)
if (_userClaimsHelper.GetPartyId() is not int partyId)
{
return Errors.CouldNotFindOrgNo; // TODO: Update to better error message
return Errors.InvalidPartyId;
}
Andreass2 marked this conversation as resolved.
Show resolved Hide resolved
var userParty = await _altinnRegisterService.LookUpPartyByPartyId(request.OnbehalfOfPartyId, cancellationToken);
var userParty = await _altinnRegisterService.LookUpPartyByPartyId(partyId, cancellationToken);
if (userParty == null || (string.IsNullOrEmpty(userParty.SSN) && string.IsNullOrEmpty(userParty.OrgNumber)))
{
return Errors.CouldNotFindOrgNo; // TODO: Update to better error message
return Errors.CouldNotFindOrgNo;
}
var recipients = new List<string>();
if (request.InstanceOwnerPartyIdList != null && request.InstanceOwnerPartyIdList.Length > 0)
Expand All @@ -68,16 +66,15 @@ public async Task<OneOf<LegacyGetCorrespondencesResponse, Error>> Process(Legacy
}
else
{
recipients.Add(string.IsNullOrEmpty(userParty.SSN) ? "0192:" + userParty.OrgNumber : userParty.SSN);
if (!string.IsNullOrEmpty(userParty.SSN)) recipients.Add(userParty.SSN);
if (!string.IsNullOrEmpty(userParty.OrgNumber)) recipients.Add("0192:" + userParty.OrgNumber);
}

List<string> resourcesToSearch = new List<string>();

// Get all correspondences owned by Recipients
var correspondences = await _correspondenceRepository.GetCorrespondencesForParties(request.Offset, limit, from, to, request.Status, recipients, resourcesToSearch, request.Language, request.IncludeActive, request.IncludeArchived, request.IncludeDeleted, request.SearchString, cancellationToken);

Console.WriteLine($"Found {correspondences.Item1.Count} correspondences");

var resourceIds = correspondences.Item1.Select(c => c.ResourceId).Distinct().ToList();
var authorizedCorrespondences = new List<CorrespondenceEntity>();
List<LegacyCorrespondenceItem> correspondenceItems = new List<LegacyCorrespondenceItem>();
Expand Down Expand Up @@ -112,6 +109,11 @@ public async Task<OneOf<LegacyGetCorrespondencesResponse, Error>> Process(Legacy
}
foreach (var correspondence in correspondences.Item1)
{
var minAuthLevel = await _altinnAuthorizationService.CheckUserAccessAndGetMinimumAuthLevel(userParty.SSN, correspondence.ResourceId, new List<ResourceAccessLevel> { ResourceAccessLevel.Read }, correspondence.Recipient, cancellationToken);
if (minAuthLevel == null)
{
continue;
}
var purgedStatus = correspondence.GetPurgedStatus();
var owner = resourceOwners.SingleOrDefault(r => r.OrgNumber == correspondence.Sender)?.Party;
var recipient = recipientDetails.SingleOrDefault(r => r.OrgNumber == correspondence.Recipient)?.Party;
Expand All @@ -124,7 +126,7 @@ public async Task<OneOf<LegacyGetCorrespondencesResponse, Error>> Process(Legacy
MessageTitle = correspondence.Content.MessageTitle,
Status = correspondence.GetLatestStatusWithoutPurged().Status,
CorrespondenceId = correspondence.Id,
MinimumAuthenticationLevel = 0, // Insert from response from PDP multirequest
MinimumAuthenticationLevel = (int)minAuthLevel,
Published = correspondence.Published,
PurgedStatus = purgedStatus?.Status,
Purged = purgedStatus?.StatusChanged,
Expand All @@ -135,7 +137,6 @@ public async Task<OneOf<LegacyGetCorrespondencesResponse, Error>> Process(Legacy
}
);
}
Console.WriteLine($"Finished correspondences: {correspondenceItems.Count}");
var response = new LegacyGetCorrespondencesResponse
{
Items = correspondenceItems,
Expand All @@ -148,14 +149,4 @@ public async Task<OneOf<LegacyGetCorrespondencesResponse, Error>> Process(Legacy
};
return response;
}
}

// TODO: Get All Resources these parties can access. I do think these resources is included in authorized parties response
// <https://docs.altinn.studio/api/resourceregistry/spec/#/Resource/post_resource_bysubjects>
// https://digdir.slack.com/archives/D07CXBW9AJH/p1727966248268839?thread_ts=1727960943.538609&cid=D07CXBW9AJH

// TODO: Authorize each correspondence using multirequests
// https://docs.altinn.studio/authorization/guides/xacml/#request-for-multiple-decisions
// https://docs.altinn.studio/api/authorization/spec/#/Decision/post_authorize
// Filter out where authorization failed
// Enrich with minimum authentication level where successfull
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ public class LegacyGetCorrespondencesRequest
{
public required int[] InstanceOwnerPartyIdList { get; set; }

public required int OnbehalfOfPartyId { get; set; }

public int Offset { get; set; }

public int Limit { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,21 @@ public async Task<OneOf<LegacyGetCorrespondenceHistoryResponse, Error>> Process(
{
return Errors.CouldNotFindOrgNo;
}
// TODO: Authorize party
var correspondence = await _correspondenceRepository.GetCorrespondenceById(correspondenceId, true, true, cancellationToken);
if (correspondence is null)
{
return Errors.CorrespondenceNotFound;
}
var minimumAuthLevel = await _altinnAuthorizationService.CheckUserAccessAndGetMinimumAuthLevel(recipientParty.SSN, correspondence.ResourceId, new List<ResourceAccessLevel> { ResourceAccessLevel.Read }, correspondence.Recipient, cancellationToken);
if (minimumAuthLevel is null)
{
return Errors.LegacyNoAccessToCorrespondence;
}
Andreass2 marked this conversation as resolved.
Show resolved Hide resolved
var senderParty = await _altinnRegisterService.LookUpPartyById(correspondence.Sender, cancellationToken);
if (senderParty == null || (string.IsNullOrEmpty(senderParty.SSN) && string.IsNullOrEmpty(senderParty.OrgNumber)))
{
return Errors.CouldNotFindOrgNo;
}
var minimumAuthLevel = await _altinnAuthorizationService.CheckUserAccessAndGetMinimumAuthLevel(recipientParty.SSN, correspondence.ResourceId, new List<ResourceAccessLevel> { ResourceAccessLevel.Read }, correspondence.Recipient, cancellationToken);
if (minimumAuthLevel is not int authenticationLevel)
{
authenticationLevel = 2; // TODO: Remove when authorization is implemented
// return Errors.LegacyNoAccessToCorrespondence;
}

var correspondenceHistory = correspondence.Statuses
.Where(s => s.Status.IsAvailableForRecipient())
Expand All @@ -61,7 +59,7 @@ public async Task<OneOf<LegacyGetCorrespondenceHistoryResponse, Error>> Process(
User = new LegacyUser
{
PartyId = recipientParty.PartyId.ToString(),
AuthenticationLevel = authenticationLevel
AuthenticationLevel = (int)minimumAuthLevel
},
}).ToList();

Expand All @@ -81,7 +79,7 @@ public async Task<OneOf<LegacyGetCorrespondenceHistoryResponse, Error>> Process(
notificationDetails.NotificationsStatusDetails.Sms.Recipient,
notification.IsReminder,
senderParty.PartyId.ToString(),
authenticationLevel));
(int)minimumAuthLevel));
}
if (notificationDetails.NotificationsStatusDetails.Email is not null)
{
Expand All @@ -90,7 +88,7 @@ public async Task<OneOf<LegacyGetCorrespondenceHistoryResponse, Error>> Process(
notificationDetails.NotificationsStatusDetails.Email.Recipient,
notification.IsReminder,
senderParty.PartyId.ToString(),
authenticationLevel));
(int)minimumAuthLevel));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public async Task<OneOf<LegacyGetCorrespondenceOverviewResponse, Error>> Process
{
if (_userClaimsHelper.GetPartyId() is not int partyId)
{
return Errors.NoAccessToResource;
return Errors.InvalidPartyId;
}
var userParty = await _altinnRegisterService.LookUpPartyByPartyId(partyId, cancellationToken);
if (userParty == null || (string.IsNullOrEmpty(userParty.SSN) && string.IsNullOrEmpty(userParty.OrgNumber)))
Expand All @@ -51,7 +51,6 @@ public async Task<OneOf<LegacyGetCorrespondenceOverviewResponse, Error>> Process
{
return Errors.LegacyNoAccessToCorrespondence;
}
var recipients = new List<string>();
if (correspondence.Recipient != userParty.SSN && correspondence.Recipient != ("0192:" + userParty.OrgNumber))
{
var authorizedParties = await _altinnAccessManagementService.GetAuthorizedParties(userParty, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Altinn.Correspondence.Application.Helpers;
using Altinn.Correspondence.Core.Models.Entities;
using Altinn.Correspondence.Core.Models.Enums;
using Altinn.Correspondence.Core.Repositories;
using Altinn.Correspondence.Core.Services;
using OneOf;
Expand All @@ -9,20 +10,23 @@ public class LegacyUpdateCorrespondenceStatusHandler : IHandler<UpdateCorrespond
{
private readonly ICorrespondenceRepository _correspondenceRepository;
private readonly ICorrespondenceStatusRepository _correspondenceStatusRepository;
private readonly IAltinnAuthorizationService _altinnAuthorizationService;
private readonly IAltinnRegisterService _altinnRegisterService;
private readonly IEventBus _eventBus;
private readonly UserClaimsHelper _userClaimsHelper;
private readonly UpdateCorrespondenceStatusHelper _updateCorrespondenceStatusHelper;
public LegacyUpdateCorrespondenceStatusHandler(
ICorrespondenceRepository correspondenceRepository,
ICorrespondenceStatusRepository correspondenceStatusRepository,
IAltinnAuthorizationService altinnAuthorizationService,
IAltinnRegisterService altinnRegisterService,
IEventBus eventBus,
UserClaimsHelper userClaimsHelper,
UpdateCorrespondenceStatusHelper updateCorrespondenceStatusHelper)
{
_correspondenceRepository = correspondenceRepository;
_correspondenceStatusRepository = correspondenceStatusRepository;
_altinnAuthorizationService = altinnAuthorizationService;
_altinnRegisterService = altinnRegisterService;
_eventBus = eventBus;
_userClaimsHelper = userClaimsHelper;
Expand All @@ -39,12 +43,16 @@ public async Task<OneOf<Guid, Error>> Process(UpdateCorrespondenceStatusRequest
{
return Errors.CouldNotFindOrgNo;
}
// TODO: Authorize party
var correspondence = await _correspondenceRepository.GetCorrespondenceById(request.CorrespondenceId, true, false, cancellationToken);
if (correspondence == null)
{
return Errors.CorrespondenceNotFound;
}
var minimumAuthLevel = await _altinnAuthorizationService.CheckUserAccessAndGetMinimumAuthLevel(party.SSN, correspondence.ResourceId, new List<ResourceAccessLevel> { ResourceAccessLevel.Read }, correspondence.Recipient, cancellationToken);
if (minimumAuthLevel == null)
{
return Errors.LegacyNoAccessToCorrespondence;
}
Andreass2 marked this conversation as resolved.
Show resolved Hide resolved
var currentStatus = correspondence.GetLatestStatus();
if (currentStatus is null)
{
Expand Down
Loading