11import { Access , AccessModes , getSolidDataset , getThingAll } from "@inrupt/solid-client" ;
22import { SubjectPermissions , BaseSubject , IndexItem , Permission , ResourcePermissions } from "../../../types" ;
3- import { SubjectKey } from "../../../types/modules" ;
3+ import { SubjectKey , TargetSubjects } from "../../../types/modules" ;
44import { getDefaultSession } from "@inrupt/solid-client-authn-browser" ;
5+ import { ODRL } from "../../../classes/utils/PolicyParser" ;
6+ import { PolicyInterpreter } from "../../../classes/utils/PolicyInterpreter" ;
7+ import { PolicyService } from "../../../classes/utils/PolicyService" ;
8+ import { Store } from 'n3' ;
59
610const ACCESS_MODES_TO_PERMISSION_MAPPING : Record < keyof ( AccessModes & Access ) , Permission > = {
711 read : Permission . Read ,
@@ -12,7 +16,6 @@ const ACCESS_MODES_TO_PERMISSION_MAPPING: Record<keyof (AccessModes & Access), P
1216 controlWrite : Permission . Control ,
1317}
1418
15-
1619/**
1720 * A permission manager implementation using the inrupt sdk to actually update the ACL
1821 * The "Inrupt" prefix is to indicate the usage of the inrupt sdk
@@ -75,38 +78,107 @@ export abstract class InruptPermissionManager<T extends Record<keyof T, BaseSubj
7578 return accessModes ;
7679 }
7780
78- abstract getRemotePermissions < K extends SubjectKey < T > > ( resourceUrl : string ) : Promise < SubjectPermissions < T [ K ] > [ ] >
81+ /**
82+ * Function to specifically get the permission list for an assignee on a certain target
83+ *
84+ * TODO: split in subject
85+ */
86+ public async getTargetPermissionsForUser ( assignerId : string , assigneeId : string , targetId : string ) : Promise < Permission [ ] > {
87+ const store : Store = await new PolicyService ( ) . fetchPolicies ( assignerId ) ;
88+ const target : TargetSubjects = new PolicyInterpreter ( ) . permissionsForOneResource ( targetId , store ) ;
89+
90+ // If there are no private permissions, or no private permissions for the assignee, return the public ones (or nothing if they don't exist)
91+ if ( ! target . private || ! target . private . get ( assigneeId ) ) return Array . from ( target . public ?. permissions ! ?? [ ] )
92+
93+ return Array . from ( target . private . get ( assigneeId ) ?. permissions ! ) ?? [ ]
94+ }
7995
80- async getContainerPermissionList ( containerUrl : string , resourceToSkip : string [ ] = [ ] ) {
96+
97+ public async getRemotePermissions < K extends SubjectKey < T > > ( resourceUrl : string ) : Promise < SubjectPermissions < T [ K ] > [ ] > {
98+ // Extract our webID
8199 const session = getDefaultSession ( ) ;
82- // this request is cached, so it doesn't matter if it's emitted multiple times in a short span
83- const dataset = await getSolidDataset ( containerUrl , { fetch : session . fetch } ) ;
84- const results = await Promise . allSettled (
85- getThingAll ( dataset )
86- . map ( async ( resource ) => {
87- if ( resourceToSkip . includes ( resource . url ) ) {
88- return {
89- resourceUrl : resource . url ,
90- // We can set this to false as this is the default & getting doubled checked in the controller
91- canRequestAccess : false ,
92- permissionsPerSubject : [ ] ,
93- }
94- }
95- return {
96- resourceUrl : resource . url ,
97- // We can set this to false as this is the default & getting doubled checked in the controller
98- canRequestAccess : false ,
99- permissionsPerSubject : await this . getRemotePermissions ( resource . url )
100- }
100+ const webId = session . info . webId ;
101+
102+ // We must be logged on
103+ if ( ! webId ) {
104+ throw new Error ( "User not logged in" ) ;
105+ }
106+
107+ // Retrieve our policies
108+ const store = await new PolicyService ( ) . fetchPolicies ( webId ) ;
109+
110+ // Get detailed info about the target
111+ const interpreter = new PolicyInterpreter ( ) ;
112+ const target : TargetSubjects = interpreter . permissionsForOneResource ( resourceUrl , store ) ;
113+
114+
115+ if ( target ) {
116+ const subjectPermissions : SubjectPermissions < T [ K ] > [ ] = [ ] ;
117+ // Add the owner information
118+ subjectPermissions . push ( {
119+ subject : {
120+ type : "webId" ,
121+ selector : { url : target . assigner }
122+ } as unknown as T [ K ] ,
123+ permissions : [ Permission . Append , Permission . Control , Permission . Create , Permission . Read , Permission . Write ] ,
124+ isEnabled : true ,
125+ targetId : target . targetUrl
126+ } )
127+
128+ // Add the public information
129+ if ( target . public && target . public . permissions . size > 0 ) subjectPermissions . push ( {
130+ subject : {
131+ type : "public" ,
132+ } as unknown as T [ K ] ,
133+ permissions : Array . from ( target . public . permissions ) ,
134+ isEnabled : true , // Not yet implemented, there is no odrl equivalent?
135+ targetId : target . targetUrl
136+ } )
137+
138+ // Add the private subjects
139+ if ( target . private ) target . private . forEach ( subject => {
140+ if ( subject . permissions . size > 0 ) subjectPermissions . push ( {
141+ subject : {
142+ type : "webId" ,
143+ selector : { url : subject . subject }
144+ } as unknown as T [ K ] ,
145+ permissions : Array . from ( subject . permissions ) ,
146+ isEnabled : true , // Not yet implemented, there is no odrl equivalent?
147+ targetId : target . targetUrl
101148 } )
102- )
103- return results . reduce < ResourcePermissions < T [ keyof T ] > [ ] > ( ( arr , v ) => {
104- if ( v . status == "fulfilled" ) {
105- arr . push ( v . value ) ;
106- }
107- return arr ;
108- } , [ ] )
149+ } )
150+ return subjectPermissions ;
151+ }
152+
153+ return [ ] ;
154+ }
155+
156+
157+ async getContainerPermissionList ( containerUrl : string , resourceToSkip : string [ ] = [ ] ) : Promise < ResourcePermissions < T [ keyof T ] > [ ] > {
158+ // Extract our webID
159+ const session = getDefaultSession ( ) ;
160+ const webId = session . info . webId ;
161+
162+ // We must be logged on
163+ if ( ! webId ) {
164+ throw new Error ( "User not logged in" ) ;
165+ }
166+
167+ const store = await new PolicyService ( ) . fetchPolicies ( webId ) ;
168+
169+ // Collect target urls
170+ const targetUrls = Array . from ( new Set ( store . getQuads ( null , ODRL ( 'target' ) , null , null ) . map ( q => q . object . id ) ) ) ;
171+ const resourcePermissions : ResourcePermissions < T [ keyof T ] > [ ] = [ ]
172+ for ( const targetUrl of targetUrls ) {
173+ const perms = await this . getRemotePermissions ( targetUrl ) ;
174+ resourcePermissions . push ( {
175+ resourceUrl : targetUrl ,
176+ canRequestAccess : true , // TODO: based on proper access logic
177+ permissionsPerSubject : perms
178+ } )
179+ }
109180
181+ return resourcePermissions ;
110182 }
111183
112184 shouldDeleteOnAllRevoked ( ) { return true }
0 commit comments