@@ -2,11 +2,14 @@ import { NamedNode } from '@rdfjs/types';
22import { getLoggerFor } from 'global-logger-factory' ;
33import { DataFactory as DF , Quad_Subject , Store } from 'n3' ;
44import { ODRL } from 'odrl-evaluator' ;
5- import { CLIENTID , PURPOSE , WEBID } from '../../credentials/Claims' ;
5+ import { CLIENTID , PURPOSE , VC , WEBID } from '../../credentials/Claims' ;
66import { ClaimSet } from '../../credentials/ClaimSet' ;
77import { ReadOnlyStore , UCRulesStorage } from '../../ucp/storage/UCRulesStorage' ;
8+ import { OVC } from '../../ucp/util/Vocabularies' ;
9+ import { array , reType , string } from '../../util/ReType' ;
810import { Permission } from '../../views/Permission' ;
911import { Authorizer } from './Authorizer' ;
12+ import jp from 'jsonpath' ;
1013
1114const ANONYMOUS = DF . namedNode ( 'urn:solidlab:uma:id:anonymous' ) ;
1215
@@ -28,7 +31,7 @@ const dateComparators: NodeJS.Dict<(a: Date, b: Date) => boolean> = {
2831} ;
2932
3033const claimOperandMap : Record < string , string > = {
31- [ ODRL . deliveryChannel ] : CLIENTID ,
34+ [ ODRL . deliveryChannel ] : CLIENTID ,
3235} as const ;
3336
3437/**
@@ -109,18 +112,19 @@ export class SimpleOdrlAuthorizer implements Authorizer {
109112 }
110113 return ruleAssignees . some ( ruleAssignee => assignees . some ( assignee => assignee . equals ( ruleAssignee ) ) ) ;
111114 } ) ;
112- this . logger . warn ( 'Rejecting request because no rules with a matching assignee or party collection were found' ) ;
113115 if ( rules . length === 0 ) {
116+ this . logger . warn ( 'Rejecting request because no rules with a matching assignee or party collection were found' ) ;
114117 return [ ] ;
115118 }
116119
117120 // Check simple constraints
118121 const validRules : Quad_Subject [ ] = [ ] ;
119122 for ( const rule of rules ) {
120123 const constraintResponse = this . validateConstraints ( rule , policies , claims ) ;
121- if ( constraintResponse === true ) {
124+ const vcConstraintResponse = this . validateOvcConstraints ( rule , policies , claims ) ;
125+ if ( constraintResponse && vcConstraintResponse ) {
122126 validRules . push ( rule ) ;
123- } else if ( constraintResponse === undefined ) {
127+ } else if ( constraintResponse === undefined || vcConstraintResponse === undefined ) {
124128 return ;
125129 }
126130 }
@@ -201,4 +205,42 @@ export class SimpleOdrlAuthorizer implements Authorizer {
201205 }
202206 return true ;
203207 }
208+
209+ // https://gitlab.com/gaia-x/lab/policy-reasoning/odrl-vc-profile
210+ protected validateOvcConstraints ( rule : Quad_Subject , policies : ReadOnlyStore , claims : ClaimSet ) : boolean | undefined {
211+ const constraints = policies . getObjects ( rule , OVC . terms . constraint , null ) . map ( constraint => ( {
212+ leftOperand : policies . getObjects ( constraint , OVC . terms . leftOperand , null ) [ 0 ] ,
213+ operator : policies . getObjects ( constraint , ODRL . terms . operator , null ) [ 0 ] ,
214+ rightOperand : policies . getObjects ( constraint , ODRL . terms . rightOperand , null ) [ 0 ] ,
215+ credentialSubjectType : policies . getObjects ( constraint , OVC . terms . credentialSubjectType , null ) [ 0 ] ,
216+ } ) ) ;
217+ // If any of these are undefined this is too complex to handle here (credentialSubjectType can be undefined)
218+ if ( constraints . some ( ( { leftOperand, operator, rightOperand } ) => ! leftOperand || ! operator || ! rightOperand ) ) {
219+ return ;
220+ }
221+ // Can't match a VC constraint if there is no VC input
222+ const vc = claims [ VC ] ;
223+ if ( constraints . length > 0 && typeof vc !== 'object' ) {
224+ return false ;
225+ }
226+
227+ for ( const constraint of constraints ) {
228+ // Only support odrl:eq for now
229+ if ( ! constraint . operator . equals ( ODRL . terms . eq ) ) {
230+ return ;
231+ }
232+ const results = jp . query ( vc , constraint . leftOperand . value ) . flat ( ) ;
233+ if ( ! results . some ( result => result === constraint . rightOperand . value ) ) {
234+ return false ;
235+ }
236+ if ( constraint . credentialSubjectType ) {
237+ const types = jp . query ( vc , '$.type' ) . flat ( ) ;
238+ if ( ! types . some ( typ => constraint . credentialSubjectType . value === typ ) ) {
239+ return false ;
240+ }
241+ }
242+ }
243+
244+ return true ;
245+ }
204246}
0 commit comments