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

Chore/908 move overview org to rtk query #1045

Merged
merged 29 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
86a299f
Move stuff to bff
sonwit Aug 20, 2024
0783682
Add RevokeDelegationDto and RevokeApiDelegationOutput models and batc…
sonwit Aug 20, 2024
e54c08e
update client to use rtk-overview-org
sonwit Aug 20, 2024
1f178eb
add overviewOrg to rtk-store
sonwit Aug 20, 2024
968ae70
Refactor API delegation service
sonwit Aug 23, 2024
09f1061
Refactor API delegation service
sonwit Aug 23, 2024
e26d1f7
Refactor API delegation service
sonwit Aug 23, 2024
b1b6c57
rename layout to DelegationType
sonwit Aug 26, 2024
690e53f
Refactor DeletableListItem component and related files
sonwit Aug 26, 2024
2317676
fix cy tests
sonwit Aug 26, 2024
e5fb03c
lint
sonwit Aug 26, 2024
af5f6c2
fix tests
sonwit Aug 27, 2024
15c935a
Remove debug output and clean up code in APIDelegationControllerTest
sonwit Aug 27, 2024
0ad5133
chore: Add JSON files for partial success in revoke delegation batch
sonwit Aug 27, 2024
2a48ec9
fix revoke batch revoke function
sonwit Aug 27, 2024
747e0ee
Handle failed API delegation revocation in OverviewPageContent
sonwit Aug 27, 2024
45037b7
remove empty line to fix warning
sonwit Aug 28, 2024
aeb6885
fix: Update revoke delegation error message
sonwit Aug 28, 2024
b9750af
fix lint issues
sonwit Aug 28, 2024
2382fdd
Refactor RevokeReceivedDelegation constructor
sonwit Aug 28, 2024
3918ef2
Rename OverviewOrg to OrganizationApiSet
sonwit Aug 28, 2024
f2e65de
Update apiDelegationApi tagTypes to include 'overviewOrg' and invalid…
sonwit Aug 30, 2024
812b0d8
Update revoke delegation error message
sonwit Aug 30, 2024
d92077b
Refactor APIDelegationControllerTest to use separate method for getti…
sonwit Aug 30, 2024
6bfb84f
Move class definitions to separate file and simplfy mapping function
sonwit Aug 30, 2024
ac02342
add test data
sonwit Aug 30, 2024
91fade2
fix: Disable button when there are no items to delete
sonwit Sep 2, 2024
eb83c6f
remove newline
sonwit Sep 2, 2024
43c00c0
remove empty ilne
sonwit Sep 2, 2024
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
@@ -0,0 +1,25 @@
using Altinn.AccessManagement.UI.Core.Models.SingleRight;

namespace Altinn.AccessManagement.UI.Core.Models
{
/// <summary>
/// Response model for the result of a api-delegation to a recipient.
/// </summary>
public class RevokeApiDelegationOutput
{
/// <summary>
/// Gets or sets the organization identifier.
/// </summary>
public string OrgNumber { get; set; }

/// <summary>
/// Gets or sets the API identifier.
/// </summary>
public string ApiId { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the operation was successful.
/// </summary>
public bool Success { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;

namespace Altinn.AccessManagement.UI.Core.Models
{
/// <summary>
/// Represents the data transfer object for revoking an offered or received delegation.
/// </summary>
public class RevokeDelegationDTO

Check warning on line 8 in backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/RevokeDelegationDto.cs

View workflow job for this annotation

GitHub Actions / Continous Integration / Analyze

Rename class 'RevokeDelegationDTO' to match pascal case naming rules, consider using 'RevokeDelegationDto'. (https://rules.sonarsource.com/csharp/RSPEC-101)

Check warning on line 8 in backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/RevokeDelegationDto.cs

View workflow job for this annotation

GitHub Actions / Continous Integration / Analyze

Rename class 'RevokeDelegationDTO' to match pascal case naming rules, consider using 'RevokeDelegationDto'. (https://rules.sonarsource.com/csharp/RSPEC-101)
{
/// <summary>
/// Gets or sets the organization number.
/// </summary>
[Required]
public string OrgNumber { get; set; }

/// <summary>
/// Gets or sets the API identifier.
/// </summary>
[Required]
public string ApiId { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,15 @@ public class RevokeOfferedDelegation
/// </summary>
[Required]
public List<Right> Rights { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="RevokeOfferedDelegation"/> class.
/// </summary>
/// <param name="dto">The DTO object containing the data for the delegation.</param>
public RevokeOfferedDelegation(RevokeDelegationDTO dto)
{
To = new List<IdValuePair> { new IdValuePair { Id = "urn:altinn:organizationnumber", Value = dto.OrgNumber } };
Rights = new List<Right> { new Right { Resource = new List<IdValuePair> { new IdValuePair { Id = "urn:altinn:resource", Value = dto.ApiId } } } };
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,15 @@ public class RevokeReceivedDelegation
/// </summary>
[Required]
public List<Right> Rights { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="RevokeReceivedDelegation"/> class.
/// </summary>
/// <param name="dto">The data transfer object for revoking a received delegation.</param>
public RevokeReceivedDelegation(RevokeDelegationDTO dto)
{
From = new List<IdValuePair> { new IdValuePair { Id = "urn:altinn:organizationnumber", Value = dto.OrgNumber } };
Rights = new List<Right> { new Right { Resource = new List<IdValuePair> { new IdValuePair { Id = "urn:altinn:resource", Value = dto.ApiId } } } };
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,11 @@
/// <summary>
/// Service that integrates with the delegation client. Processes and maps the required data to the frontend model
/// </summary>
public class APIDelegationService : IAPIDelegationService

Check warning on line 15 in backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/APIDelegationService.cs

View workflow job for this annotation

GitHub Actions / Continous Integration / Analyze

Rename class 'APIDelegationService' to match pascal case naming rules, consider using 'ApiDelegationService'. (https://rules.sonarsource.com/csharp/RSPEC-101)

Check warning on line 15 in backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/APIDelegationService.cs

View workflow job for this annotation

GitHub Actions / Continous Integration / Analyze

Rename class 'APIDelegationService' to match pascal case naming rules, consider using 'ApiDelegationService'. (https://rules.sonarsource.com/csharp/RSPEC-101)
{
private readonly IAccessManagementClient _maskinportenSchemaClient;
private readonly IResourceService _resourceService;

private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};

/// <summary>
/// Initializes a new instance of the <see cref="APIDelegationService" /> class.
/// </summary>
Expand All @@ -36,29 +31,29 @@
}

/// <inheritdoc />
public async Task<List<MaskinportenSchemaDelegationFE>> GetOfferedMaskinportenSchemaDelegations(string party, string languageCode)
public async Task<List<OrganizationApiSet>> GetOfferedMaskinportenSchemaDelegations(string party, string languageCode)
{
List<MaskinportenSchemaDelegation> offeredDelegations = await _maskinportenSchemaClient.GetOfferedMaskinportenSchemaDelegations(party);
return await BuildMaskinportenSchemaDelegationFE(offeredDelegations, languageCode);
return await BuildMaskinportenSchemaDelegationFE(offeredDelegations, languageCode, DelegationType.Offered);
}

/// <inheritdoc />
public async Task<List<MaskinportenSchemaDelegationFE>> GetReceivedMaskinportenSchemaDelegations(string party, string languageCode)
public async Task<List<OrganizationApiSet>> GetReceivedMaskinportenSchemaDelegations(string party, string languageCode)
{
List<MaskinportenSchemaDelegation> receivedDelegations = await _maskinportenSchemaClient.GetReceivedMaskinportenSchemaDelegations(party);
return await BuildMaskinportenSchemaDelegationFE(receivedDelegations, languageCode);
return await BuildMaskinportenSchemaDelegationFE(receivedDelegations, languageCode, DelegationType.Received);
}

/// <inheritdoc />
public async Task<HttpResponseMessage> RevokeReceivedMaskinportenScopeDelegation(string party, RevokeReceivedDelegation delegation)
public async Task<HttpResponseMessage> RevokeReceivedMaskinportenScopeDelegation(string party, RevokeDelegationDTO delegationDTO)
{
return await _maskinportenSchemaClient.RevokeReceivedMaskinportenScopeDelegation(party, delegation);
return await _maskinportenSchemaClient.RevokeReceivedMaskinportenScopeDelegation(party, new RevokeReceivedDelegation(delegationDTO));
}

/// <inheritdoc />
public async Task<HttpResponseMessage> RevokeOfferedMaskinportenScopeDelegation(string party, RevokeOfferedDelegation delegation)
public async Task<HttpResponseMessage> RevokeOfferedMaskinportenScopeDelegation(string party, RevokeDelegationDTO delegationDTO)
{
return await _maskinportenSchemaClient.RevokeOfferedMaskinportenScopeDelegation(party, delegation);
return await _maskinportenSchemaClient.RevokeOfferedMaskinportenScopeDelegation(party, new RevokeOfferedDelegation(delegationDTO));
}

/// <inheritdoc />
Expand Down Expand Up @@ -90,18 +85,16 @@
try
{
var response = await _maskinportenSchemaClient.CreateMaskinportenScopeDelegation(party, delegationObject);
string responseContent = await response.Content.ReadAsStringAsync();


delegationOutputs.Add(new ApiDelegationOutput()
{
OrgNumber = org,
ApiId = api,
Success = response.StatusCode == System.Net.HttpStatusCode.Created
});
}
catch (Exception e)
catch
{
System.Diagnostics.Debug.WriteLine(e.Message);
delegationOutputs.Add(new ApiDelegationOutput()
{
OrgNumber = org,
Expand All @@ -121,42 +114,209 @@
return await _maskinportenSchemaClient.MaskinportenSchemaDelegationCheck(partyId, request);
}

private async Task<List<MaskinportenSchemaDelegationFE>> BuildMaskinportenSchemaDelegationFE(List<MaskinportenSchemaDelegation> delegations, string languageCode)
private async Task<List<OrganizationApiSet>> BuildMaskinportenSchemaDelegationFE(List<MaskinportenSchemaDelegation> delegations, string languageCode, DelegationType type)
sonwit marked this conversation as resolved.
Show resolved Hide resolved
{
List<string> resourceIds = delegations.Select(d => d.ResourceId).ToList();
List<ServiceResource> resources = await _resourceService.GetResources(resourceIds);

List<MaskinportenSchemaDelegationFE> result = new List<MaskinportenSchemaDelegationFE>();
List<OrganizationApiSet> overviewOrgList = new List<OrganizationApiSet>();

foreach (MaskinportenSchemaDelegation delegation in delegations)
{
MaskinportenSchemaDelegationFE delegationFE = new MaskinportenSchemaDelegationFE();
delegationFE.LanguageCode = languageCode;
delegationFE.OfferedByPartyId = delegation.OfferedByPartyId;
delegationFE.OfferedByOrganizationNumber = delegation.OfferedByOrganizationNumber;
delegationFE.OfferedByName = delegation.OfferedByName;
delegationFE.CoveredByPartyId = delegation.CoveredByPartyId;
delegationFE.CoveredByOrganizationNumber = delegation.CoveredByOrganizationNumber;
delegationFE.CoveredByName = delegation.CoveredByName;
delegationFE.PerformedByUserId = delegation.PerformedByUserId;
delegationFE.Created = delegation.Created;
delegationFE.ResourceId = delegation.ResourceId;
ServiceResource resource = resources.FirstOrDefault(r => r.Identifier == delegation.ResourceId);
if (resource != null)
var resource = resources.Find(r => r.Identifier == delegation.ResourceId);
if (resource == null)
{
continue;
}

var delegationFE = new MaskinportenSchemaDelegationFE
{
LanguageCode = languageCode,
OfferedByPartyId = delegation.OfferedByPartyId,
OfferedByOrganizationNumber = delegation.OfferedByOrganizationNumber,
OfferedByName = delegation.OfferedByName,
CoveredByPartyId = delegation.CoveredByPartyId,
CoveredByOrganizationNumber = delegation.CoveredByOrganizationNumber,
CoveredByName = delegation.CoveredByName,
PerformedByUserId = delegation.PerformedByUserId,
Created = delegation.Created,
ResourceId = delegation.ResourceId,
ResourceTitle = resource.Title.GetValueOrDefault(languageCode, "nb"),
ResourceType = resource.ResourceType,
ResourceOwnerName = resource.HasCompetentAuthority?.Name.GetValueOrDefault(languageCode, "nb"),
RightDescription = resource.RightDescription.GetValueOrDefault(languageCode, "nb"),
ResourceReferences = resource.ResourceReferences
};

var api = new ApiListItem
{
Id = delegationFE.ResourceId,
ApiName = delegationFE.ResourceTitle,
Owner = delegationFE.ResourceOwnerName,
Description = delegationFE.RightDescription,
Scopes = delegationFE.ResourceReferences?.Where(r => r.ReferenceType.Equals("MaskinportenScope")).Select(r => r.Reference).ToList() ?? new List<string>()
};

string delegationOrg = type == DelegationType.Offered ? delegationFE.CoveredByName : delegationFE.OfferedByName;
string delegationOrgNumber = type == DelegationType.Offered ? delegationFE.CoveredByOrganizationNumber : delegationFE.OfferedByOrganizationNumber;
sonwit marked this conversation as resolved.
Show resolved Hide resolved

var existingOrg = overviewOrgList.Find(org => org.Id == delegationOrg);
if (existingOrg != null)
{
delegationFE.ResourceTitle = resource.Title.GetValueOrDefault(languageCode, "nb");
delegationFE.ResourceType = resource.ResourceType;
delegationFE.ResourceOwnerOrgcode = resource.HasCompetentAuthority?.Orgcode;
delegationFE.ResourceOwnerOrgNumber = resource.HasCompetentAuthority?.Organization;
delegationFE.ResourceOwnerName = resource.HasCompetentAuthority?.Name.GetValueOrDefault(languageCode, "nb");
delegationFE.ResourceDescription = resource.Description.GetValueOrDefault(languageCode, "nb");
delegationFE.RightDescription = resource.RightDescription.GetValueOrDefault(languageCode, "nb");
delegationFE.ResourceReferences = resource.ResourceReferences;
existingOrg.ApiList.Add(api);
}
else
{
var newOrg = new OrganizationApiSet
{
Id = delegationOrg,
Name = delegationOrg,
OrgNumber = delegationOrgNumber,
ApiList = new List<ApiListItem> { api }
};
overviewOrgList.Add(newOrg);
}
}

return overviewOrgList;
}

/// <summary>
/// Revoke a batch of Maskinporten scope delegations.
/// </summary>
/// <param name="party">The party identifier.</param>
/// <param name="delegationDTOs">The list of delegation DTOs.</param>
/// <param name="type">The type of delegation.</param>
/// <returns>A list of tasks representing the HTTP response messages.</returns>
public async Task<List<RevokeApiDelegationOutput>> BatchRevokeMaskinportenScopeDelegation(string party, List<RevokeDelegationDTO> delegationDTOs, DelegationType type)
sonwit marked this conversation as resolved.
Show resolved Hide resolved
{
var responses = new List<RevokeApiDelegationOutput>();

result.Add(delegationFE);
if (type == DelegationType.Offered)
{
foreach (var delegation in delegationDTOs)
{
try
{
var response = await _maskinportenSchemaClient.RevokeOfferedMaskinportenScopeDelegation(party, new RevokeOfferedDelegation(delegation));
responses.Add(new RevokeApiDelegationOutput
{
OrgNumber = delegation.OrgNumber,
ApiId = delegation.ApiId,
Success = response.IsSuccessStatusCode,
});
}
catch
{
responses.Add(new RevokeApiDelegationOutput
{
OrgNumber = delegation.OrgNumber,
ApiId = delegation.ApiId,
Success = false
});
}
}
}
else
{
foreach (var delegation in delegationDTOs)
{
try
{
var res = await _maskinportenSchemaClient.RevokeReceivedMaskinportenScopeDelegation(party, new RevokeReceivedDelegation(delegation));
responses.Add(new RevokeApiDelegationOutput
{
OrgNumber = delegation.OrgNumber,
ApiId = delegation.ApiId,
Success = res.IsSuccessStatusCode,
});
}
catch
{
responses.Add(new RevokeApiDelegationOutput
{
OrgNumber = delegation.OrgNumber,
ApiId = delegation.ApiId,
Success = false
});
}
}
}

return result;
return responses;
}
}

/// <summary>
/// Represents an API item.
/// </summary>
public class ApiListItem
sonwit marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// Gets or sets the ID of the API.
/// </summary>
public string Id { get; set; }

/// <summary>
/// Gets or sets the name of the API.
/// </summary>
public string ApiName { get; set; }

/// <summary>
/// Gets or sets the owner of the API.
/// </summary>
public string Owner { get; set; }

/// <summary>
/// Gets or sets the description of the API.
/// </summary>
public string Description { get; set; }

/// <summary>
/// Gets or sets the scopes associated with the API.
/// </summary>
public List<string> Scopes { get; set; }
}

/// <summary>
/// Represents a set of APIs given to or recieved from an organization.
/// </summary>
public class OrganizationApiSet
{
/// <summary>
/// Gets or sets the ID of the organization.
/// </summary>
public string Id { get; set; }

/// <summary>
/// Gets or sets the name of the organization.
/// </summary>
public string Name { get; set; }

/// <summary>
/// Gets or sets the organization number.
/// </summary>
public string OrgNumber { get; set; }

/// <summary>
/// Gets or sets a set of APIs given to or recieved from an organization
/// </summary>
public List<ApiListItem> ApiList { get; set; } = new List<ApiListItem>();
}

/// <summary>
/// Represents the type of delegation.
/// </summary>
public enum DelegationType
{
/// <summary>
/// Offered delegation type.
/// </summary>
Offered,

/// <summary>
/// Received delegation type.
/// </summary>
Received
}
}
Loading
Loading