diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/ClientInterfaces/ISingleRightClient.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/ClientInterfaces/ISingleRightClient.cs index 59fb3943d..cbbe80226 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/ClientInterfaces/ISingleRightClient.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/ClientInterfaces/ISingleRightClient.cs @@ -19,5 +19,17 @@ public interface ISingleRightClient /// /// List Task> CheckDelegationAccess(string partyId, DelegationRequestDto request); + + /// + /// Creates a single rights delegation + /// + /// + /// The party from which to delegate the right + /// + /// + /// The delegation to be created + /// + /// + Task CreateDelegation(string party, DelegationInput delegation); } } diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/DelegationRequestDto.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/DelegationRequestDto.cs index 44d079211..96809b0cb 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/DelegationRequestDto.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/DelegationRequestDto.cs @@ -17,6 +17,6 @@ public class DelegationRequestDto /// Gets or sets the set of Attribute Id and Attribute Value for a specific action, to identify the action this right /// applies to /// - public IdValuePair? Action { get; set; } + public string? Action { get; set; } } } diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/Frontend/ServiceResourceFE.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/Frontend/ServiceResourceFE.cs index f9d50bc71..2f12a4c35 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/Frontend/ServiceResourceFE.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/Frontend/ServiceResourceFE.cs @@ -38,6 +38,16 @@ public class ServiceResourceFE /// public string Status { get; set; } + /// + /// Is this resource possible to delegate to others or not + /// + public bool Delegable { get; set; } = true; + + /// + /// The visibility of the resource + /// + public bool Visible { get; set; } = true; + /// /// When the resource is available from /// @@ -84,7 +94,7 @@ public ServiceResourceFE() /// /// Basic constructor /// - public ServiceResourceFE(string identifier, string title, string description, string rightDescription, string status, DateTime validFrom, DateTime validTo, string resourceOwnerName, string resourceOwnerOrgNumber, List resourceReferences, ResourceType resourceType, string? homepage = null, int? priorityCounter = null) + public ServiceResourceFE(string identifier, string title, string description, string rightDescription, string status, DateTime validFrom, DateTime validTo, string resourceOwnerName, string resourceOwnerOrgNumber, List resourceReferences, ResourceType resourceType, string? homepage = null, int? priorityCounter = null, bool visible = true, bool delegable = true) { Identifier = identifier; Title = title; @@ -99,6 +109,8 @@ public ServiceResourceFE(string identifier, string title, string description, st ResourceReferences = resourceReferences; PriorityCounter = priorityCounter; ResourceType = resourceType; + Visible = visible; + Delegable = delegable; } /// @@ -120,6 +132,8 @@ public ServiceResourceFE(ServiceResourceFE serviceResourceFE) PriorityCounter = serviceResourceFE.PriorityCounter; ResourceReferences = serviceResourceFE.ResourceReferences; ResourceType = serviceResourceFE.ResourceType; + Visible = serviceResourceFE.Visible; + Delegable = serviceResourceFE.Delegable; } } } diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/ServiceResource.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/ServiceResource.cs index 1d273b0e4..685f8503d 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/ServiceResource.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/ServiceResource.cs @@ -4,7 +4,7 @@ namespace Altinn.AccessManagement.UI.Core.Models.ResourceRegistry { /// - /// Model describing a complete resource from the resource registry. + /// Model describing a complete resource from the resource registry /// public class ServiceResource { @@ -59,20 +59,30 @@ public class ServiceResource public bool IsPublicService { get; set; } /// - /// ThematicArea + /// ThematicAreas /// - public string? ThematicArea { get; set; } + public List? ThematicAreas { get; set; } /// /// ResourceReference /// - public List ResourceReferences { get; set; } + public List? ResourceReferences { get; set; } /// /// IsComplete /// public bool? IsComplete { get; set; } + /// + /// Is this resource possible to delegate to others or not + /// + public bool Delegable { get; set; } = true; + + /// + /// The visibility of the resource + /// + public bool Visible { get; set; } = true; + /// /// HasCompetentAuthority /// @@ -93,5 +103,19 @@ public class ServiceResource /// [JsonConverter(typeof(JsonStringEnumConverter))] public ResourceType ResourceType { get; set; } + + /// + /// The fallback language of the resource + /// + public string MainLanguage { get; set; } = "nb"; + + /// + /// Writes key information when this object is written to Log. + /// + /// + public override string ToString() + { + return $"Identifier: {Identifier}, ResourceType: {ResourceType}"; + } } -} +} \ No newline at end of file diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/Interfaces/ISingleRightService.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/Interfaces/ISingleRightService.cs index a74e42cef..8c2d8e2f5 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/Interfaces/ISingleRightService.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/Interfaces/ISingleRightService.cs @@ -17,5 +17,17 @@ public interface ISingleRightService /// The delegation access check request object that's going to be consumed by the backend /// List Task> CheckDelegationAccess(string partyId, DelegationRequestDto request); + + /// + /// Creates a single right delegation from a given party + /// + /// + /// The party from which to delegate the right + /// + /// + /// The delegation to be created + /// + /// + Task CreateDelegation(string party, DelegationInput delegation); } } diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/ResourceService.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/ResourceService.cs index a1ebf7805..77b25ddc2 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/ResourceService.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/ResourceService.cs @@ -56,7 +56,7 @@ public async Task> GetPaginatedSearchResults(st try { List resources = await GetFullResourceList(); - List resourceList = resources.FindAll(r => r.ResourceType != ResourceType.MaskinportenSchema && r.ResourceType != ResourceType.SystemResource); + List resourceList = resources.FindAll(r => r.ResourceType != ResourceType.MaskinportenSchema && r.ResourceType != ResourceType.SystemResource && r.Delegable && r.Visible); List resourcesFE = MapResourceToFrontendModel(resourceList, languageCode); List filteredresources = FilterResourceList(resourcesFE, resourceOwnerFilters); @@ -76,7 +76,7 @@ public async Task> GetResources(ResourceType resourceTyp try { List resources = await GetResources(); - List resourceList = resources.FindAll(r => r.ResourceType == resourceType); + List resourceList = resources.FindAll(r => r.ResourceType == resourceType && r.Delegable && r.Visible); return MapResourceToFrontendModel(resourceList, languageCode); } catch (Exception ex) @@ -322,7 +322,9 @@ private List MapResourceToFrontendModel(List rightDescription: resource.RightDescription?.GetValueOrDefault(languageCode) ?? resource.RightDescription?.GetValueOrDefault("nb"), description: resource.Description?.GetValueOrDefault(languageCode) ?? resource.Description?.GetValueOrDefault("nb"), validFrom: resource.ValidFrom, - validTo: resource.ValidTo); + validTo: resource.ValidTo, + visible: resource.Visible, + delegable: resource.Delegable); resourceList.Add(resourceFE); } diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/SingleRightService.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/SingleRightService.cs index c49031408..6996e22f3 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/SingleRightService.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/SingleRightService.cs @@ -23,5 +23,11 @@ public async Task> CheckDelegationAccess(str { return await _singleRightClient.CheckDelegationAccess(partyId, request); } + + /// + public async Task CreateDelegation(string party, DelegationInput delegation) + { + return await _singleRightClient.CreateDelegation(party, delegation); + } } } diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Integration/Clients/SingleRightClient.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Integration/Clients/SingleRightClient.cs index d392e987a..33811b5a1 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Integration/Clients/SingleRightClient.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Integration/Clients/SingleRightClient.cs @@ -73,5 +73,15 @@ public async Task> CheckDelegationAccess(str throw; } } + + /// + public async Task CreateDelegation(string party, DelegationInput delegation) + { + string endpointUrl = $"{party}/rights/delegation/offered"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _platformSettings.JwtCookieName); + StringContent requestBody = new StringContent(JsonSerializer.Serialize(delegation, _serializerOptions), Encoding.UTF8, "application/json"); + HttpResponseMessage response = await _client.PostAsync(token, endpointUrl, requestBody); + return response; + } } } diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400/from_p50067798/to_810418362/ExpectedOutput_Default.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400/from_p50067798/to_810418362/ExpectedOutput_Default.json index 14d2294b0..0f1fbd5e1 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400/from_p50067798/to_810418362/ExpectedOutput_Default.json +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400/from_p50067798/to_810418362/ExpectedOutput_Default.json @@ -13,10 +13,7 @@ "value": "appid-400" } ], - "action": { - "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", - "value": "ScopeAccess" - } + "action": "ScopeAccess" } ] } \ No newline at end of file diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400/from_p50067798/to_810418532/ExpectedOutput_Default.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400/from_p50067798/to_810418532/ExpectedOutput_Default.json index 8b98f0438..0c53402eb 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400/from_p50067798/to_810418532/ExpectedOutput_Default.json +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400/from_p50067798/to_810418532/ExpectedOutput_Default.json @@ -13,10 +13,7 @@ "value": "appid-400" } ], - "action": { - "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", - "value": "ScopeAccess" - } + "action": "ScopeAccess" } ] } \ No newline at end of file diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402/from_p50067798/to_810418362/ExpectedOutput_Default.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402/from_p50067798/to_810418362/ExpectedOutput_Default.json index 2879701fd..ad0e43357 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402/from_p50067798/to_810418362/ExpectedOutput_Default.json +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402/from_p50067798/to_810418362/ExpectedOutput_Default.json @@ -13,10 +13,7 @@ "value": "appid-402" } ], - "action": { - "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", - "value": "ScopeAccess" - } + "action": "ScopeAccess" } ] } \ No newline at end of file diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402/from_p50067798/to_810418532/ExpectedOutput_Default.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402/from_p50067798/to_810418532/ExpectedOutput_Default.json index 61ba5fab6..4f5e4e859 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402/from_p50067798/to_810418532/ExpectedOutput_Default.json +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402/from_p50067798/to_810418532/ExpectedOutput_Default.json @@ -13,10 +13,7 @@ "value": "appid-402" } ], - "action": { - "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", - "value": "ScopeAccess" - } + "action": "ScopeAccess" } ] } \ No newline at end of file diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/nav_aa_distribution/from_p50005545/to_810418672/ExpectedOutput_Default.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/nav_aa_distribution/from_p50005545/to_810418672/ExpectedOutput_Default.json index bd0622f26..401969fa5 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/nav_aa_distribution/from_p50005545/to_810418672/ExpectedOutput_Default.json +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/nav_aa_distribution/from_p50005545/to_810418672/ExpectedOutput_Default.json @@ -13,10 +13,7 @@ "value": "nav_aa_distribution" } ], - "action": { - "id": "urn:oasis:names:tc:xacml:1.0:action:action-id", - "value": "ScopeAccess" - } + "action": "ScopeAccess" } ] } \ No newline at end of file diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ResourceRegistry/resources.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ResourceRegistry/resources.json index 075611254..55adf70fd 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ResourceRegistry/resources.json +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ResourceRegistry/resources.json @@ -1091,9 +1091,9 @@ }, { "title": { - "en": "The Shortcut - linked service", - "nb": "Snarveien - lenketjeneste", - "nn": "Snarvegen - lenketjeneste" + "en": "The Magic Closet - linked service", + "nb": "Det magiske klesskapet - lenketjeneste", + "nn": "Det magiske klesskapet - lenketjeneste" }, "sector": null, "status": null, @@ -1102,37 +1102,39 @@ "isPartOf": null, "keywords": null, "validFrom": "2020-03-04T18:04:27.27", - "identifier": "appid-503", + "identifier": "appid-502", "isComplete": true, + "visible": true, + "delegable": true, "description": { - "en": "The Shortcut som lenketjeneste", - "nb": "Snarveien som lenketjeneste", - "nn": "Snarvegen som lenketjeneste" + "en": "The Magic Closet", + "nb": "Det magiske klesskapet", + "nn": "Det magiske klesskapet" }, "resourceType": "Default", "thematicArea": null, "isPublicService": true, "rightDescription": { - "en": "Gives access to shortcuts.", - "nb": "Gir tilgang til snarveier.", - "nn": "Gir tilgang til snarveger." + "en": "Gives access to Narnia.", + "nb": "Gir tilgang til Narnia.", + "nn": "Gir tilgang til Narnia." }, "resourceReferences": [], "hasCompetentAuthority": { - "orgcode": "PAA", - "organization": "130000000", + "orgcode": "NRNA", + "organization": "777777777", "name": { - "en": "DEPARTMENT OF HUMBUG", - "nb": "PÅFUNNSETATEN", - "nn": "PÅFUNNSETATEN" + "en": "NARNIA", + "nb": "NARNIA", + "nn": "NARNIA" } } }, { "title": { - "en": "The Magic Closet - linked service", - "nb": "Det magiske klesskapet - lenketjeneste", - "nn": "Det magiske klesskapet - lenketjeneste" + "en": "The Shortcut - linked service", + "nb": "Snarveien - lenketjeneste", + "nn": "Snarvegen - lenketjeneste" }, "sector": null, "status": null, @@ -1141,29 +1143,31 @@ "isPartOf": null, "keywords": null, "validFrom": "2020-03-04T18:04:27.27", - "identifier": "appid-502", + "identifier": "appid-503", "isComplete": true, + "visible": true, + "delegable": true, "description": { - "en": "The Magic Closet", - "nb": "Det magiske klesskapet", - "nn": "Det magiske klesskapet" + "en": "The Shortcut som lenketjeneste", + "nb": "Snarveien som lenketjeneste", + "nn": "Snarvegen som lenketjeneste" }, "resourceType": "Default", "thematicArea": null, "isPublicService": true, "rightDescription": { - "en": "Gives access to Narnia.", - "nb": "Gir tilgang til Narnia.", - "nn": "Gir tilgang til Narnia." + "en": "Gives access to shortcuts.", + "nb": "Gir tilgang til snarveier.", + "nn": "Gir tilgang til snarveger." }, "resourceReferences": [], "hasCompetentAuthority": { - "orgcode": "NRNA", - "organization": "777777777", + "orgcode": "PAA", + "organization": "130000000", "name": { - "en": "NARNIA", - "nb": "NARNIA", - "nn": "NARNIA" + "en": "DEPARTMENT OF HUMBUG", + "nb": "PÅFUNNSETATEN", + "nn": "PÅFUNNSETATEN" } } }, @@ -1182,12 +1186,14 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-504", "isComplete": true, + "visible": true, + "delegable": true, "description": { "en": "An Altinn 3 app", "nb": "En Altinn 3 app", "nn": "En Altinn 3 app" }, - "resourceType": "Default", + "resourceType": "AltinnApp", "thematicArea": null, "isPublicService": true, "rightDescription": { @@ -1197,14 +1203,9 @@ }, "resourceReferences": [ { - "reference": "AppId:504", - "referenceType": "ServiceCode", - "referenceSource": "Altinn3" - }, - { - "reference": "1", - "referenceType": "ServiceEditionCode", - "referenceSource": "Altinn3" + "referenceSource": "Altinn3", + "reference": "ttd/a3-app", + "referenceType": "ApplicationId" } ], "hasCompetentAuthority": { @@ -1232,29 +1233,31 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-505", "isComplete": true, + "visible": true, + "delegable": true, "description": { - "en": "An Altinn 2 app", - "nb": "En Altinn 2 app", - "nn": "En Altinn 2 app" + "en": "An Altinn 2 form", + "nb": "Et Altinn 2 skjema", + "nn": "Et Altinn 2 skjema" }, - "resourceType": "Default", + "resourceType": "Altinn2Service", "thematicArea": null, "isPublicService": true, "rightDescription": { - "en": "Gives access an A2 app.", - "nb": "Gir tilgang til en A2 app.", - "nn": "Gir tilgang til en A2 app." + "en": "Gives access an A2 form.", + "nb": "Gir tilgang til en A2 skjema.", + "nn": "Gir tilgang til en A2 skjema." }, "resourceReferences": [ { - "reference": "AppId:505", - "referenceType": "ServiceCode", - "referenceSource": "Altinn2" + "referenceSource": "Altinn2", + "reference": "3225", + "referenceType": "ServiceCode" }, { - "reference": "1", - "referenceType": "ServiceEditionCode", - "referenceSource": "Altinn2" + "referenceSource": "Altinn2", + "reference": "1596", + "referenceType": "ServiceEditionCode" } ], "hasCompetentAuthority": { @@ -1282,12 +1285,14 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-506", "isComplete": true, + "visible": true, + "delegable": true, "description": { "en": "An Altinn 3 app", "nb": "En Altinn 3 app", "nn": "En Altinn 3 app" }, - "resourceType": "Default", + "resourceType": "AltinnApp", "thematicArea": null, "isPublicService": true, "rightDescription": { @@ -1297,14 +1302,9 @@ }, "resourceReferences": [ { - "reference": "AppId:506", - "referenceType": "ServiceCode", - "referenceSource": "Altinn3" - }, - { - "reference": "1", - "referenceType": "ServiceEditionCode", - "referenceSource": "Altinn3" + "referenceSource": "Altinn3", + "reference": "ttd/a3-app2", + "referenceType": "ApplicationId" } ], "hasCompetentAuthority": { @@ -1332,29 +1332,31 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-507", "isComplete": true, + "visible": true, + "delegable": true, "description": { - "en": "An Altinn 2 app", - "nb": "En Altinn 2 app", - "nn": "En Altinn 2 app" + "en": "An Altinn 2 form", + "nb": "Et Altinn 2 skjema", + "nn": "Et Altinn 2 skjema" }, - "resourceType": "Default", + "resourceType": "Altinn2Service", "thematicArea": null, "isPublicService": true, "rightDescription": { - "en": "Gives access an A2 app.", - "nb": "Gir tilgang til en A2 app.", - "nn": "Gir tilgang til en A2 app." + "en": "Gives access an A2 form.", + "nb": "Gir tilgang til et A2 skjema.", + "nn": "Gir tilgang til et A2 skjema." }, "resourceReferences": [ { - "reference": "AppId:505", - "referenceType": "ServiceCode", - "referenceSource": "Altinn2" + "referenceSource": "Altinn2", + "reference": "322a", + "referenceType": "ServiceCode" }, { - "reference": "1", - "referenceType": "ServiceEditionCode", - "referenceSource": "Altinn2" + "referenceSource": "Altinn2", + "reference": "159b", + "referenceType": "ServiceEditionCode" } ], "hasCompetentAuthority": { @@ -1382,6 +1384,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-508", "isComplete": true, + "visible": true, + "delegable": true, "description": { "en": "The Firetruck", "nb": "Brannbilen - det er bare én ja", @@ -1421,6 +1425,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-509", "isComplete": true, + "visible": true, + "delegable": true, "description": { "en": "Barista, mazagran and sit barista mazagran, trifecta roast sweet single origin froth. French press, and cinnamon, eu beans ristretto, viennese, and crema roast decaffeinated whipped. Extraction sweet as trifecta java half and half crema rich arabica. Rich, instant, to go sugar macchiato froth, mug macchiato wings iced pumpkin spice.", "nb": "Barista, mazagran and sit barista mazagran, trifecta roast sweet single origin froth. French press, and cinnamon, eu beans ristretto, viennese, and crema roast decaffeinated whipped. Extraction sweet as trifecta java half and half crema rich arabica. Rich, instant, to go sugar macchiato froth, mug macchiato wings iced pumpkin spice.", @@ -1460,6 +1466,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-510", "isComplete": true, + "visible": true, + "delegable": true, "description": { "en": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", "nb": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", @@ -1499,6 +1507,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-511", "isComplete": true, + "visible": true, + "delegable": true, "description": { "en": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", "nb": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", @@ -1538,6 +1548,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-512", "isComplete": true, + "visible": true, + "delegable": true, "description": { "en": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", "nb": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", @@ -1577,6 +1589,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-513", "isComplete": true, + "visible": true, + "delegable": true, "description": { "en": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", "nb": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ResourceRegistry/resourcesfe.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ResourceRegistry/resourcesfe.json index 89f8809ad..8904363be 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ResourceRegistry/resourcesfe.json +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ResourceRegistry/resourcesfe.json @@ -833,7 +833,7 @@ "resourceOwnerOrgNumber": "130000000" }, { - "title": "Snarveien - lenketjeneste", + "title": "Det magiske klesskapet - lenketjeneste", "sector": null, "status": null, "validTo": "9999-12-31T23:59:59.997", @@ -841,19 +841,21 @@ "isPartOf": null, "keywords": null, "validFrom": "2020-03-04T18:04:27.27", - "identifier": "appid-503", + "identifier": "appid-502", "isComplete": true, - "description": "Snarveien som lenketjeneste", + "visible": true, + "delegable": true, + "description": "Det magiske klesskapet", "resourceType": "Default", "thematicArea": null, "isPublicService": true, - "rightDescription": "Gir tilgang til snarveger.", + "rightDescription": "Gir tilgang til Narnia.", "resourceReferences": [], - "resourceOwnerName": "PÅFUNNSETATEN", - "resourceOwnerOrgNumber": "130000000" + "resourceOwnerName": "NARNIA", + "resourceOwnerOrgNumber": "777777777" }, { - "title": "Det magiske klesskapet - lenketjeneste", + "title": "Snarveien - lenketjeneste", "sector": null, "status": null, "validTo": "9999-12-31T23:59:59.997", @@ -861,16 +863,18 @@ "isPartOf": null, "keywords": null, "validFrom": "2020-03-04T18:04:27.27", - "identifier": "appid-502", + "identifier": "appid-503", "isComplete": true, - "description": "Det magiske klesskapet", + "visible": true, + "delegable": true, + "description": "Snarveien som lenketjeneste", "resourceType": "Default", "thematicArea": null, "isPublicService": true, - "rightDescription": "Gir tilgang til Narnia.", + "rightDescription": "Gir tilgang til snarveger.", "resourceReferences": [], - "resourceOwnerName": "NARNIA", - "resourceOwnerOrgNumber": "777777777" + "resourceOwnerName": "PÅFUNNSETATEN", + "resourceOwnerOrgNumber": "130000000" }, { "title": "A3 app", @@ -883,21 +887,18 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-504", "isComplete": true, + "visible": true, + "delegable": true, "description": "En Altinn 3 app", - "resourceType": "Default", + "resourceType": "AltinnApp", "thematicArea": null, "isPublicService": true, "rightDescription": "Gir tilgang til en A3 app.", "resourceReferences": [ { - "reference": "AppId:504", - "referenceType": "ServiceCode", - "referenceSource": "Altinn3" - }, - { - "reference": "1", - "referenceType": "ServiceEditionCode", - "referenceSource": "Altinn3" + "referenceSource": "Altinn3", + "reference": "ttd/a3-app", + "referenceType": "ApplicationId" } ], "resourceOwnerName": "Testdepartementet", @@ -914,21 +915,23 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-505", "isComplete": true, - "description": "En Altinn 2 app", - "resourceType": "Default", + "visible": true, + "delegable": true, + "description": "Et Altinn 2 skjema", + "resourceType": "Altinn2Service", "thematicArea": null, "isPublicService": true, - "rightDescription": "Gir tilgang til en A2 app.", + "rightDescription": "Gir tilgang til et A2 skjema.", "resourceReferences": [ { - "reference": "AppId:505", - "referenceType": "ServiceCode", - "referenceSource": "Altinn2" + "referenceSource": "Altinn2", + "reference": "3225", + "referenceType": "ServiceCode" }, { - "reference": "1", - "referenceType": "ServiceEditionCode", - "referenceSource": "Altinn2" + "referenceSource": "Altinn2", + "reference": "1596", + "referenceType": "ServiceEditionCode" } ], "resourceOwnerName": "Testdepartementet", @@ -945,21 +948,18 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-506", "isComplete": true, + "visible": true, + "delegable": true, "description": "En Altinn 3 app", - "resourceType": "Default", + "resourceType": "AltinnApp", "thematicArea": null, "isPublicService": true, "rightDescription": "Gir tilgang til en A3 app.", "resourceReferences": [ { - "reference": "AppId:506", - "referenceType": "ServiceCode", - "referenceSource": "Altinn3" - }, - { - "reference": "1", - "referenceType": "ServiceEditionCode", - "referenceSource": "Altinn3" + "referenceSource": "Altinn3", + "reference": "ttd/a3-app2", + "referenceType": "ApplicationId" } ], "resourceOwnerName": "Testdepartementet", @@ -976,21 +976,23 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-507", "isComplete": true, - "description": "En Altinn 2 app", - "resourceType": "Default", + "visible": true, + "delegable": true, + "description": "Et Altinn 2 skjema", + "resourceType": "Altinn2Service", "thematicArea": null, "isPublicService": true, - "rightDescription": "Gir tilgang til en A2 app.", + "rightDescription": "Gir tilgang til et A2 skjema.", "resourceReferences": [ { - "reference": "AppId:505", - "referenceType": "ServiceCode", - "referenceSource": "Altinn2" + "referenceSource": "Altinn2", + "reference": "322a", + "referenceType": "ServiceCode" }, { - "reference": "1", - "referenceType": "ServiceEditionCode", - "referenceSource": "Altinn2" + "referenceSource": "Altinn2", + "reference": "159b", + "referenceType": "ServiceEditionCode" } ], "resourceOwnerName": "Testdepartementet", @@ -1007,6 +1009,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-508", "isComplete": true, + "visible": true, + "delegable": true, "description": "Brannbilen - det er bare én ja", "resourceType": "Default", "thematicArea": null, @@ -1027,6 +1031,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-509", "isComplete": true, + "visible": true, + "delegable": true, "description": "Barista, mazagran and sit barista mazagran, trifecta roast sweet single origin froth. French press, and cinnamon, eu beans ristretto, viennese, and crema roast decaffeinated whipped. Extraction sweet as trifecta java half and half crema rich arabica. Rich, instant, to go sugar macchiato froth, mug macchiato wings iced pumpkin spice.", "resourceType": "Default", "thematicArea": null, @@ -1047,6 +1053,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-510", "isComplete": true, + "visible": true, + "delegable": true, "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", "resourceType": "Default", "thematicArea": null, @@ -1067,6 +1075,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-511", "isComplete": true, + "visible": true, + "delegable": true, "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", "resourceType": "Default", "thematicArea": null, @@ -1087,6 +1097,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-512", "isComplete": true, + "visible": true, + "delegable": true, "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", "resourceType": "Default", "thematicArea": null, @@ -1107,6 +1119,8 @@ "validFrom": "2020-03-04T18:04:27.27", "identifier": "appid-513", "isComplete": true, + "visible": true, + "delegable": true, "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus orci turpis, vehicula a dignissim eget, condimentum at diam. Etiam iaculis, purus vel venenatis condimentum, lectus arcu tempor est, et tempor lorem elit ut nunc. Donec eu bibendum leo. Ut ac dolor erat. Vestibulum posuere fringilla iaculis", "resourceType": "Default", "thematicArea": null, diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/3225.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/3225.json new file mode 100644 index 000000000..1f8deebf3 --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/3225.json @@ -0,0 +1,23 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "3225" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "1596" + } + ], + "action": "read" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/322a.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/322a.json new file mode 100644 index 000000000..ae5f7e92d --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/322a.json @@ -0,0 +1,49 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "322a" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "159b" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "322a" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "159b" + } + ], + "action": "write" + }, + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "322a" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "159b" + } + ], + "action": "sign" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/a3-app2.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/a3-app2.json new file mode 100644 index 000000000..686042fc8 --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/a3-app2.json @@ -0,0 +1,36 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:applicationid", + "value": "a3-app2" + }, + { + "id": "urn:altinn:org", + "value": "ttd" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:applicationid", + "value": "a3-app2" + }, + { + "id": "urn:altinn:org", + "value": "ttd" + } + ], + "action": "write" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-502.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-502.json new file mode 100644 index 000000000..783cea3dc --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-502.json @@ -0,0 +1,37 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-502" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-502" + } + ], + "action": "write" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-502" + } + ], + "action": "sign" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-503.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-503.json new file mode 100644 index 000000000..4ea247d26 --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-503.json @@ -0,0 +1,37 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-503" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-503" + } + ], + "action": "write" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-503" + } + ], + "action": "sign" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-508.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-508.json new file mode 100644 index 000000000..5a762db5d --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/CreateDelegation/appid-508.json @@ -0,0 +1,37 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-508" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-508" + } + ], + "action": "write" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-508" + } + ], + "action": "sign" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Mocks/SingleRightClientMock.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Mocks/SingleRightClientMock.cs index 5274a852a..88f32b6aa 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Mocks/SingleRightClientMock.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Mocks/SingleRightClientMock.cs @@ -2,30 +2,69 @@ using Altinn.AccessManagement.UI.Core.Models; using Altinn.AccessManagement.UI.Core.Models.SingleRight.CheckDelegationAccess; using Altinn.AccessManagement.UI.Mocks.Utils; +using Azure.Core; +using System.Net; +using System.Text; namespace Altinn.AccessManagement.UI.Mocks.Mocks { public class SingleRightClientMock : ISingleRightClient { + + private readonly string localPath; /// /// Initializes a new instance of class /// public SingleRightClientMock() { - + localPath = Path.GetDirectoryName(new Uri(typeof(SingleRightClientMock).Assembly.Location).LocalPath); } /// public Task> CheckDelegationAccess(string partyId, DelegationRequestDto request) { - string? unitTestFolder = Path.GetDirectoryName(new Uri(typeof(SingleRightClientMock).Assembly.Location).LocalPath); - string path = Path.Combine(unitTestFolder, "Data", "SingleRight", "DelegationAccessCheckResponse"); + string dataPath = Path.Combine(localPath, "Data", "SingleRight", "DelegationAccessCheckResponse"); - List expectedResponse = Util.GetMockData>(path, DetermineAccessLevel(request)); + List expectedResponse = Util.GetMockData>(dataPath, DetermineAccessLevel(request)); return Task.FromResult(expectedResponse); } + /// + public async Task CreateDelegation(string party, DelegationInput delegation) + { + IdValuePair resource = delegation.Rights.First().Resource.First(); + + string resourceFileName; + switch (resource.Id) { + case "urn:altinn:resource": + case "urn:altinn:servicecode": + case "urn:altinn:applicationid": + resourceFileName = resource.Value; + break; + case "urn:altinn:org": + case "urn:altinn:serviceeditioncode": + resourceFileName = delegation.Rights.First().Resource[1].Value; + break; + default: + resourceFileName = "Unknown"; + break; + } + + string dataPath = Path.Combine(localPath, "Data", "SingleRight", "CreateDelegation"); + try + { + string data = Util.GetMockDataSerialized(dataPath, resourceFileName + ".json"); + return new HttpResponseMessage + { StatusCode = HttpStatusCode.Created, Content = new StringContent(data) }; + + } + catch + { + return new HttpResponseMessage(HttpStatusCode.BadRequest); + } + } + private static string DetermineAccessLevel(DelegationRequestDto request) { string value = request.Resource.FirstOrDefault().Value; diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Utils/Util.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Utils/Util.cs index 9263e7590..cd3d37685 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Utils/Util.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Utils/Util.cs @@ -23,5 +23,18 @@ public static T GetMockData(string path, string filename) T res = JsonSerializer.Deserialize(content, options); return res; } + + public static string GetMockDataSerialized(string path, string filename) + { + string fullPath = Path.Combine(path, filename); + + if (!File.Exists(fullPath)) + { + throw new FileNotFoundException($"The file with path {fullPath} does not exist"); + } + + return File.ReadAllText(Path.Combine(fullPath)); + + } } } diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Controllers/SingleRightCotrollerTest.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Controllers/SingleRightCotrollerTest.cs index e1ddc0d47..8658a2c24 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Controllers/SingleRightCotrollerTest.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Controllers/SingleRightCotrollerTest.cs @@ -1,3 +1,4 @@ +using System; using System.Net; using System.Net.Http.Headers; using System.Text; @@ -8,6 +9,7 @@ using Altinn.AccessManagement.UI.Mocks.Mocks; using Altinn.AccessManagement.UI.Mocks.Utils; using Altinn.AccessManagement.UI.Tests.Utils; +using Microsoft.AspNetCore.Http; namespace Altinn.AccessManagement.UI.Tests.Controllers { @@ -19,6 +21,7 @@ public class SingleRightCotrollerTest : IClassFixture _factory; + private readonly string unitTestFolder; /// /// Constructor setting up factory, test client and dependencies /// @@ -30,6 +33,8 @@ public SingleRightCotrollerTest(CustomWebApplicationFactory @@ -164,9 +169,285 @@ public async Task DelegationAccessCheck_ReadAndWrite_valid_response() Assert.Equal(3, countMatches); } + /// + /// Test case: CreateDelegation delegates the actions of a standard resource + /// Expected: CreateDelegation returns the delegated actions of the standard resource + /// + [Fact] + public async Task CreateDelegation_StandardResource_valid() + { + // Arrange + string partyId = "999 999 999"; + string toSsn = "50019992"; + + string path = Path.Combine(unitTestFolder, "Data", "ExpectedResults", "SingleRight", "CreateDelegation"); + DelegationOutput expectedResponse = Util.GetMockData(path, "appid-503.json"); + + List resource = new List + { + new IdValuePair + { + Id = "urn:altinn:resource", + Value = "appid-503", + + } + }; + + List to = new List + { + new IdValuePair + { + Id = "urn:altinn:ssn", + Value = toSsn + } + }; + + List rights = new List + { + new DelegationRequestDto + { + Resource = resource, + Action = "read" + }, + new DelegationRequestDto + { + Resource = resource, + Action = "write" + }, + new DelegationRequestDto + { + Resource = resource, + Action = "sign" + }, + }; + + DelegationInput delegation = new DelegationInput + { + To = to, + Rights = rights + }; + + string jsonDto = JsonSerializer.Serialize(delegation); + HttpContent content = new StringContent(jsonDto, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage httpResponse = await _client.PostAsync($"accessmanagement/api/v1/singleright/delegate/{partyId}", content); + DelegationOutput actualResponse = await httpResponse.Content.ReadAsAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, httpResponse.StatusCode); + AssertionUtil.AssertDelegationOutputEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: CreateDelegation delegates the actions of an altinn app + /// Expected: CreateDelegation returns the delegated actions of the altinn app + /// + [Fact] + public async Task CreateDelegation_AltinnApp_valid() + { + // Arrange + string partyId = "999 999 999"; + string toSsn = "50019992"; + + string path = Path.Combine(unitTestFolder, "Data", "ExpectedResults", "SingleRight", "CreateDelegation"); + DelegationOutput expectedResponse = Util.GetMockData(path, "a3-app2.json"); + + List resource = new List + { + new IdValuePair + { + Id = "urn:altinn:applicationid", + Value = "a3-app2", + + }, + new IdValuePair + { + Id = "urn:altinn:org", + Value = "ttd", + + } + }; + + List to = new List + { + new IdValuePair + { + Id = "urn:altinn:ssn", + Value = toSsn + } + }; + + List rights = new List + { + new DelegationRequestDto + { + Resource = resource, + Action = "read" + }, + new DelegationRequestDto + { + Resource = resource, + Action = "write" + }, + }; + + DelegationInput delegation = new DelegationInput + { + To = to, + Rights = rights + }; + + string jsonDto = JsonSerializer.Serialize(delegation); + HttpContent content = new StringContent(jsonDto, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage httpResponse = await _client.PostAsync($"accessmanagement/api/v1/singleright/delegate/{partyId}", content); + DelegationOutput actualResponse = await httpResponse.Content.ReadAsAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, httpResponse.StatusCode); + AssertionUtil.AssertDelegationOutputEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: CreateDelegation delegates the actions of an altinn 2 form + /// Expected: CreateDelegation returns the delegated actions of the altinn 2 form + /// + [Fact] + public async Task CreateDelegation_Altinn2Service_valid() + { + // Arrange + string partyId = "999 999 999"; + string toSsn = "50019992"; + + string path = Path.Combine(unitTestFolder, "Data", "ExpectedResults", "SingleRight", "CreateDelegation"); + DelegationOutput expectedResponse = Util.GetMockData(path, "3225.json"); + + List resource = new List + { + new IdValuePair + { + Id = "urn:altinn:servicecode", + Value = "3225", + + }, + new IdValuePair + { + Id = "urn:altinn:serviceeditioncode", + Value = "1596", + + } + }; + + List to = new List + { + new IdValuePair + { + Id = "urn:altinn:ssn", + Value = toSsn + } + }; + + List rights = new List + { + new DelegationRequestDto + { + Resource = resource, + Action = "read" + }, + new DelegationRequestDto + { + Resource = resource, + Action = "write" + }, + }; + + DelegationInput delegation = new DelegationInput + { + To = to, + Rights = rights + }; + + string jsonDto = JsonSerializer.Serialize(delegation); + HttpContent content = new StringContent(jsonDto, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage httpResponse = await _client.PostAsync($"accessmanagement/api/v1/singleright/delegate/{partyId}", content); + DelegationOutput actualResponse = await httpResponse.Content.ReadAsAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, httpResponse.StatusCode); + AssertionUtil.AssertDelegationOutputEqual(expectedResponse, actualResponse); + } + + /// + /// Test case: CreateDelegation does not delegate the actions of a standard resource if the resource does not exist + /// Expected: CreateDelegation returns bad request + /// + [Fact] + public async Task CreateDelegation_StandardResource_invalid() + { + // Arrange + string partyId = "999 999 999"; + string toSsn = "50019992"; + + List resource = new List + { + new IdValuePair + { + Id = "urn:altinn:resource", + Value = "Nonexistent", + + } + }; + + List to = new List + { + new IdValuePair + { + Id = "urn:altinn:ssn", + Value = toSsn + } + }; + + List rights = new List + { + new DelegationRequestDto + { + Resource = resource, + Action = "read" + }, + new DelegationRequestDto + { + Resource = resource, + Action = "write" + }, + new DelegationRequestDto + { + Resource = resource, + Action = "sign" + }, + }; + + DelegationInput delegation = new DelegationInput + { + To = to, + Rights = rights + }; + + string jsonDto = JsonSerializer.Serialize(delegation); + HttpContent content = new StringContent(jsonDto, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage httpResponse = await _client.PostAsync($"accessmanagement/api/v1/singleright/delegate/{partyId}", content); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, httpResponse.StatusCode); + } + private int CountMatches(List actualResponses, string expectedResponseFileName) { - string? unitTestFolder = Path.GetDirectoryName(new Uri(typeof(SingleRightClientMock).Assembly.Location).LocalPath); string path = Path.Combine(unitTestFolder, "Data", "SingleRight", "DelegationAccessCheckResponse"); List expectedResponses = Util.GetMockData>(path, expectedResponseFileName); diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/3225.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/3225.json new file mode 100644 index 000000000..1f8deebf3 --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/3225.json @@ -0,0 +1,23 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "3225" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "1596" + } + ], + "action": "read" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/322a.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/322a.json new file mode 100644 index 000000000..ae5f7e92d --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/322a.json @@ -0,0 +1,49 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "322a" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "159b" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "322a" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "159b" + } + ], + "action": "write" + }, + { + "resource": [ + { + "id": "urn:altinn:servicecode", + "value": "322a" + }, + { + "id": "urn:altinn:serviceeditioncode", + "value": "159b" + } + ], + "action": "sign" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/a3-app2.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/a3-app2.json new file mode 100644 index 000000000..686042fc8 --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/a3-app2.json @@ -0,0 +1,36 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:applicationid", + "value": "a3-app2" + }, + { + "id": "urn:altinn:org", + "value": "ttd" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:applicationid", + "value": "a3-app2" + }, + { + "id": "urn:altinn:org", + "value": "ttd" + } + ], + "action": "write" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-502.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-502.json new file mode 100644 index 000000000..783cea3dc --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-502.json @@ -0,0 +1,37 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-502" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-502" + } + ], + "action": "write" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-502" + } + ], + "action": "sign" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-503.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-503.json new file mode 100644 index 000000000..4ea247d26 --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-503.json @@ -0,0 +1,37 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-503" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-503" + } + ], + "action": "write" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-503" + } + ], + "action": "sign" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-508.json b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-508.json new file mode 100644 index 000000000..5a762db5d --- /dev/null +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/CreateDelegation/appid-508.json @@ -0,0 +1,37 @@ +{ + "to": [ + { + "id": "urn:altinn:ssn", + "value": "50019992" + } + ], + "rightDelegationResults": [ + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-508" + } + ], + "action": "read" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-508" + } + ], + "action": "write" + }, + { + "resource": [ + { + "id": "urn:altinn:resource", + "value": "appid-508" + } + ], + "action": "sign" + } + ] +} diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Utils/AssertionUtil.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Utils/AssertionUtil.cs index 5a6adca0f..d01a2c55a 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Utils/AssertionUtil.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Utils/AssertionUtil.cs @@ -62,7 +62,7 @@ public static void AssertBaseRightExternalEqual(DelegationRequestDto expected, D Assert.NotNull(expected); AssertCollections(expected.Resource, actual.Resource, AssertAttributeMatchEqual); - AssertAttributeMatchEqual(expected.Action, actual.Action); + Assert.Equal(expected.Action, actual.Action); } /// diff --git a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Controllers/SingleRightController.cs b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Controllers/SingleRightController.cs index f90daa22f..5640c4de8 100644 --- a/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Controllers/SingleRightController.cs +++ b/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Controllers/SingleRightController.cs @@ -1,3 +1,5 @@ +using System.Text.Json; +using System.Text.Json.Serialization; using Altinn.AccessManagement.UI.Core.Models; using Altinn.AccessManagement.UI.Core.Models.SingleRight.CheckDelegationAccess; using Altinn.AccessManagement.UI.Core.Services.Interfaces; @@ -15,14 +17,18 @@ namespace Altinn.AccessManagement.UI.Controllers [Route("accessmanagement/api/v1/singleright")] public class SingleRightController : Controller { + private readonly ILogger _logger; private readonly ISingleRightService _singleRightService; + private readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; /// /// Initializes a new instance of the class /// - public SingleRightController(ISingleRightService singleRightService) + public SingleRightController(ISingleRightService singleRightService, ILogger logger) { _singleRightService = singleRightService; + _serializerOptions.Converters.Add(new JsonStringEnumConverter()); + _logger = logger; } /// @@ -43,5 +49,42 @@ public async Task>> CheckDelega return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); } } + + /// + /// Endpoint for delegating a single right from the reportee party to a third party + /// + /// Bad Request + /// Internal Server Error + [HttpPost] + [Authorize] + [Route("delegate/{party}")] + public async Task> CreateDelegation([FromRoute] string party, [FromBody] DelegationInput delegation) + { + try + { + HttpResponseMessage response = await _singleRightService.CreateDelegation(party, delegation); + + if (response.StatusCode == System.Net.HttpStatusCode.Created) + { + string responseContent = await response.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(responseContent, _serializerOptions); + } + else if (response.StatusCode == System.Net.HttpStatusCode.BadRequest) + { + string responseContent = await response.Content.ReadAsStringAsync(); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int?)response.StatusCode, "Bad request", detail: responseContent)); + } + else + { + string responseContent = await response.Content.ReadAsStringAsync(); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext, (int?)response.StatusCode, "Unexpected HttpStatus response", detail: responseContent)); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Unexpected exception occurred during delegation of resource:" + ex.Message); + return new ObjectResult(ProblemDetailsFactory.CreateProblemDetails(HttpContext)); + } + } } } diff --git a/package.json b/package.json index e04ca01ca..14ce86785 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "vite-plugin-svgr": "^3.0.0" }, "devDependencies": { - "@digdir/design-system-tokens": "^0.4.1", + "@digdir/design-system-tokens": "^0.4.2", "@testing-library/cypress": "^9.0.0", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", diff --git a/src/components/ActionBar/ActionBarHeader.module.css b/src/components/ActionBar/ActionBarHeader.module.css index b2a7eefa2..e13431fe6 100644 --- a/src/components/ActionBar/ActionBarHeader.module.css +++ b/src/components/ActionBar/ActionBarHeader.module.css @@ -42,6 +42,11 @@ border-bottom-style: none; } +.actionBar.small.light { + border-color: var(--border-color); + background-color: var(--background-color); +} + .actionBar.light { --border-color: var(--fds-semantic-border-neutral-subtle); --background-color: var(--fds-semantic-surface-neutral-default); diff --git a/yarn.lock b/yarn.lock index dd8bf99e3..830ce8be1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -409,7 +409,7 @@ __metadata: languageName: node linkType: hard -"@digdir/design-system-tokens@npm:^0.4.1, @digdir/design-system-tokens@npm:^0.4.2": +"@digdir/design-system-tokens@npm:^0.4.2": version: 0.4.2 resolution: "@digdir/design-system-tokens@npm:0.4.2" checksum: e75d52501d183eb7a78d92b9403909ec1c00c4ef19bd1fcf0677c1cc3a7b918a48b5d460377bc7ead331a101b817b4a08093b8e394187dec7e181512934f5d04 @@ -1793,7 +1793,7 @@ __metadata: dependencies: "@altinn/altinn-design-system": 0.29.1 "@digdir/design-system-react": 0.23.3 - "@digdir/design-system-tokens": ^0.4.1 + "@digdir/design-system-tokens": ^0.4.2 "@navikt/aksel-icons": ^5.0.3 "@reduxjs/toolkit": ^1.9.5 "@tanstack/react-query": ^4.32.6