Skip to content

Commit 9e3c5ee

Browse files
lovollLøvoll, RemiCopilot
authored
Feature/remilovoll/26/03/bug fixing instance delegation from app (#2624)
* UnitTest for Conection Instance Delegation * Fix sequence Bruno test Fix Prefix validering av PartyUrn Fix instance to only look at the last part for comparison * Guardrail preventing same instanceid to belonging to more than one reportee. * Fix responce to not include urn prefix for instanceid * Changed the counting of fromParties to be done before fetching and parsing policy files as this is unnesesery when failing and is expencive to perform. * Update src/apps/Altinn.AccessManagement/test/Bruno/AccessMgmt/test/EnduserAPI/Connections/Instances/Post_Enduser_Conn_Instances_Dagl.bru Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Missed new ProblemDetailCode --------- Co-authored-by: Løvoll, Remi <acn-rlovo@ai-dev.no> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent b9e09e8 commit 9e3c5ee

File tree

9 files changed

+158
-9
lines changed

9 files changed

+158
-9
lines changed

src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/AppsInstanceDelegationService.cs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ public async Task<Result<ResourceDelegationCheckResponse>> DelegationCheck(AppsI
231231

232232
private async Task<MinimalParty> GetMinimalParty(PartyUrn urn, CancellationToken cancellationToken)
233233
{
234-
switch (urn.KeySpan.ToString())
234+
switch (urn.PrefixSpan.ToString())
235235
{
236236
case AltinnXacmlConstants.MatchAttributeIdentifiers.PartyUuidAttribute:
237237
return await _partyService.GetByUid(new Guid(urn.ValueSpan.ToString()), cancellationToken);
@@ -264,7 +264,7 @@ public async Task<Result<AppsInstanceDelegationResponse>> Delegate(AppsInstanceD
264264
}
265265

266266
string instanceUrn = $"{AltinnXacmlConstants.MatchAttributeIdentifiers.InstanceAttribute}:{party.PartyId}/{instanceId}";
267-
request.InstanceId = instanceUrn;
267+
request.InstanceId = instanceUrn;
268268
}
269269

270270
(ValidationErrorBuilder Errors, InstanceRight RulesToHandle, List<RightInternal> RightsAppCantHandle) input = await SetUpDelegationOrRevokeRequest(request, cancellationToken);
@@ -330,7 +330,21 @@ public async Task<Result<List<AppsInstanceRevokeResponse>>> RevokeAll(AppsInstan
330330
}
331331

332332
// Fetch all existing delegations
333-
List<AppsInstanceDelegationResponse> delegations = await _pip.GetInstanceDelegations(request, cancellationToken);
333+
List<AppsInstanceDelegationResponse> delegations;
334+
try
335+
{
336+
delegations = await _pip.GetInstanceDelegations(request, cancellationToken);
337+
}
338+
catch (ValidationException)
339+
{
340+
errors.Add(ValidationErrors.InvalidInstanceId, "request.InstanceId");
341+
if (errors.TryBuild(out var invalidInstanceId))
342+
{
343+
return invalidInstanceId;
344+
}
345+
346+
delegations = [];
347+
}
334348

335349
// If nothing to delete just return with empty result set and no errors
336350
if (delegations.Count == 0)
@@ -365,7 +379,7 @@ public async Task<Result<List<AppsInstanceRevokeResponse>>> RevokeAll(AppsInstan
365379
List<InstanceRight> revokedResult = await _pap.TryWriteInstanceRevokeAllPolicyRules(rightsToRevoke, cancellationToken);
366380
List<AppsInstanceRevokeResponse> result = TransformInstanceRightListToAppsInstanceDelegationResponseList(revokedResult);
367381
result = RemoveInstanceIdFromResourceForRevokeResponseList(result);
368-
382+
result = RemoveUrnPrefixFromInstanceIdForRevokeResponceList(result, request.InstanceId);
369383
return result;
370384
}
371385

@@ -683,11 +697,37 @@ public async Task<Result<List<AppsInstanceDelegationResponse>>> Get(AppsInstance
683697
return errorResult;
684698
}
685699

686-
List<AppsInstanceDelegationResponse> result = await _pip.GetInstanceDelegations(request, cancellationToken);
700+
List<AppsInstanceDelegationResponse> result;
701+
try
702+
{
703+
result = await _pip.GetInstanceDelegations(request, cancellationToken);
704+
}
705+
catch (ValidationException)
706+
{
707+
errors.Add(ValidationErrors.InvalidInstanceId, "request.InstanceId");
708+
if (errors.TryBuild(out var invalidInstanceId))
709+
{
710+
return invalidInstanceId;
711+
}
712+
713+
result = [];
714+
}
715+
687716
result = RemoveInstanceIdFromResourceForDelegationResponseList(result);
717+
result = RemoveUrnPrefixFromInstanceId(result, request.InstanceId);
688718
return result;
689719
}
690720

721+
private static List<AppsInstanceDelegationResponse> RemoveUrnPrefixFromInstanceId(List<AppsInstanceDelegationResponse> input, string instanceId)
722+
{
723+
foreach (AppsInstanceDelegationResponse item in input)
724+
{
725+
item.InstanceId = instanceId;
726+
}
727+
728+
return input;
729+
}
730+
691731
private static AppsInstanceRevokeResponse RemoveInstanceIdFromResourceForRevokeResponse(AppsInstanceRevokeResponse input)
692732
{
693733
foreach (var right in input.Rights)
@@ -708,6 +748,16 @@ private static List<AppsInstanceRevokeResponse> RemoveInstanceIdFromResourceForR
708748
return input;
709749
}
710750

751+
private static List<AppsInstanceRevokeResponse> RemoveUrnPrefixFromInstanceIdForRevokeResponceList(List<AppsInstanceRevokeResponse> input, string instanceId)
752+
{
753+
foreach (AppsInstanceRevokeResponse item in input)
754+
{
755+
item.InstanceId = instanceId;
756+
}
757+
758+
return input;
759+
}
760+
711761
private static List<AppsInstanceDelegationResponse> RemoveInstanceIdFromResourceForDelegationResponseList(List<AppsInstanceDelegationResponse> input)
712762
{
713763
foreach (AppsInstanceDelegationResponse item in input)

src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/PolicyInformationPoint.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,12 @@ public async Task<List<AppsInstanceDelegationResponse>> GetInstanceDelegations(A
308308

309309
List<InstanceDelegationChange> delegations = await _delegationRepository.GetAllLatestInstanceDelegationChanges(request.InstanceDelegationSource, request.ResourceId, request.InstanceId, cancellationToken);
310310

311+
List<Guid> fromParties = delegations.Select(d => d.FromUuid).Distinct().ToList();
312+
if (fromParties.Count > 1)
313+
{
314+
throw new ValidationException($"Multiple from parties found for instance delegations: {string.Join(", ", fromParties)}");
315+
}
316+
311317
foreach (InstanceDelegationChange delegation in delegations)
312318
{
313319
AppsInstanceDelegationResponse appsInstanceDelegationResponse = new AppsInstanceDelegationResponse

src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Persistence/DelegationMetadataEF.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ public async Task<List<InstanceDelegationChange>> GetAllLatestInstanceDelegation
686686
.Include(t => t.Resource).ThenInclude(t => t.Type)
687687

688688
.Where(t => t.Resource.RefId == resourceID)
689-
.Where(t => t.InstanceId == instanceID)
689+
.Where(t => t.InstanceId.EndsWith(instanceID))
690690
.ToListAsync(cancellationToken);
691691

692692
return result.Select(Convert).ToList();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
meta {
2+
name: Post_Enduser_Conn_Instances_Dagl
3+
type: http
4+
seq: 1
5+
}
6+
7+
post {
8+
url: {{baseUrl}}/accessmanagement/api/v1/enduser/connections/resources/rights?party={{party}}&from={{from}}&to={{to}}&resource={{resource}}&instance={{instance}}
9+
body: json
10+
auth: inherit
11+
}
12+
13+
params:query {
14+
party: {{party}}
15+
from: {{from}}
16+
to: {{to}}
17+
resource: {{resource}}
18+
instance: {{instance}}
19+
}
20+
21+
headers {
22+
Accept: application/json
23+
}
24+
25+
body:json {
26+
{
27+
"DirectRightKeys": [
28+
"0144e74457db71df2ba504e6fc5b081d2e72b7396f501de222767cbf838c0a56f3",
29+
"0166c5e067d84985ad6974588ad0b76d7e12c1502c65cbb551e16521696088c742",
30+
"01f223492db1318fea6edad70bed2c2462e9b431e42596a1a6382f5630dfd9486b",
31+
"0159c58c191e76b3e6bbf8e74c81f0b1c1ec2ed6158e51843afb3f7bd9c37fb210"
32+
]
33+
}
34+
}
35+
36+
script:pre-request {
37+
const sharedtestdata = require(`./testdata/sharedtestdata.js`);
38+
const testdata = require(`./testdata/resource-delegationcheck/${bru.getEnvVar("tokenEnv")}.js`);
39+
40+
bru.setVar("requestName", "Post_Enduser_Conn_Instances_Dagl");
41+
42+
bru.setVar("party", testdata.VOKSENDE_FRYKTLØS_TIGER.partyUuid);
43+
bru.setVar("from", testdata.VOKSENDE_FRYKTLØS_TIGER.partyUuid);
44+
bru.setVar("to", testdata.KOMPLEKS_LOJAL_TIGER.dagligleder.partyUuid);
45+
bru.setVar("resource", testdata.resources.instanceResourceId);
46+
bru.setVar("instance", testdata.instances.testInstance1);
47+
48+
var getTokenParameters = {
49+
auth_userId: testdata.VOKSENDE_FRYKTLØS_TIGER.dagligleder.userId,
50+
auth_partyId: testdata.VOKSENDE_FRYKTLØS_TIGER.dagligleder.partyId,
51+
auth_partyUuid: testdata.VOKSENDE_FRYKTLØS_TIGER.dagligleder.partyUuid,
52+
auth_ssn: testdata.VOKSENDE_FRYKTLØS_TIGER.dagligleder.pid,
53+
auth_tokenType: sharedtestdata.authTokenType.personal,
54+
auth_scopes: sharedtestdata.auth_scopes.enduserSystemToOthersWrite
55+
}
56+
57+
58+
const testTokenGenerator = require(`./TestToolsTokenGenerator.js`);
59+
const token = await testTokenGenerator.getToken(getTokenParameters);
60+
bru.setVar("bearerToken", token);
61+
}
62+
63+
tests {
64+
65+
test(bru.getVar("requestName"), function() {
66+
const body = res.getBody();
67+
const actions = body.actions;
68+
69+
expect(res.status).to.equal(201);
70+
});
71+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
meta {
2+
name: Instances
3+
seq: 10
4+
}
5+
6+
auth {
7+
mode: inherit
8+
}

src/apps/Altinn.AccessManagement/test/Bruno/AccessMgmt/test/EnduserAPI/Connections/Resources/AddActions/Post_Enduser_Conn_Resources_Dagl.bru

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ script:pre-request {
3333
const sharedtestdata = require(`./testdata/sharedtestdata.js`);
3434
const testdata = require(`./testdata/resource-delegationcheck/${bru.getEnvVar("tokenEnv")}.js`);
3535

36-
bru.setVar("requestName", "GET_Enduser_Conn_Resources_DelgCheck_Dagl");
36+
bru.setVar("requestName", "Post_Enduser_Conn_Resources_Dagl");
3737

3838
bru.setVar("party", testdata.VOKSENDE_FRYKTLØS_TIGER.partyUuid);
3939
bru.setVar("from", testdata.VOKSENDE_FRYKTLØS_TIGER.partyUuid);

src/apps/Altinn.AccessManagement/test/Bruno/AccessMgmt/testdata/resource-delegationcheck/at22.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
"env": "at22",
44
"resources": {
55
"packageResourceId": "tilgangspakke_delegering_ressurs",
6-
"roleResourceId": "jks-test-resource"
6+
"roleResourceId": "jks-test-resource",
7+
"instanceResourceId": "app_ttd_instance-gui-test"
8+
},
9+
"instances": {
10+
"testInstance1": "urn:altinn:instance-id:51385701/e39ce2dd-7892-44ad-91fd-1b9a03829fac"
711
},
812
"VOKSENDE_FRYKTLØS_TIGER": {
913
"name": "VOKSENDE FRYKTLØS TIGER AS",

src/apps/Altinn.AccessManagement/test/Bruno/AccessMgmt/testdata/resource-delegationcheck/tt02.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
"env": "tt02",
44
"resources": {
55
"packageResourceId": "tilgangspakke_delegering_ressurs",
6-
"roleResourceId": "jks-test-resource"
6+
"roleResourceId": "jks-test-resource",
7+
"instanceResourceId": "app_ttd_instance-gui-test"
8+
},
9+
"instances": {
10+
"testInstance1": "urn:altinn:instance-id:51599233/7567dd1c-1257-4317-85a7-f907810402b4"
711
},
812
"VOKSENDE_FRYKTLØS_TIGER": {
913
"name": "VOKSENDE FRYKTLØS TIGER AS",

src/libs/Altinn.Authorization.Api.Contracts/src/Altinn.Authorization.Api.Contracts/Errors/ValidationErrors.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,4 +235,10 @@ private static readonly ValidationErrorDescriptorFactory _factory
235235
/// </summary>
236236
public static ValidationErrorDescriptor ResourceAndPackageIsSpecified { get; }
237237
= _factory.Create(46, "Either Resource or Package must be included in the request, but not both.");
238+
239+
/// <summary>
240+
/// More than one fromParty is connected to the same instance uuid this should not be posible
241+
/// </summary>
242+
public static ValidationErrorDescriptor InvalidInstanceId { get; }
243+
= _factory.Create(47, $"The instance ID is invalid as more than one owner was found.");
238244
}

0 commit comments

Comments
 (0)