Skip to content

Commit 81a0fda

Browse files
committed
feat(odrl): support specifying scopes for rules
Extend ODRL rules with a `scopes` slot that allows to provide 0..* strings as scopes for a rule.
1 parent cc0395f commit 81a0fda

2 files changed

Lines changed: 28 additions & 10 deletions

File tree

odrl/odrl.lisp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ simply be down cased."
114114
:reader target) ; odrl:target
115115
(assignee :initarg :assignee
116116
:type party-collection
117-
:reader assignee)) ; odrl:assignee
117+
:reader assignee) ; odrl:assignee
118+
(scopes :initarg :scopes
119+
:type list
120+
:reader scopes))
118121
(:documentation "An ODRL rule combines the common parts for permissions, prohibitions, and duties. In contrast to the ODRL specification we allow a rule to specify multiple actions, as `acl::access-grant's allows multiple usages to be specified."))
119122

120123
(defmethod initialize-instance :after ((concept rule) &key)
@@ -146,10 +149,17 @@ simply be down cased."
146149
(defgeneric odrl-to-acl (concept)
147150
(:documentation "Convert an ODRL concept to its corresponding sparql-parser configuration macro."))
148151

152+
;; NOTE (08/04/2026): This is NOT equality of rules as it does not take into account actions.
149153
(defun rules-match-p (left right)
150-
"Return t if the rules LEFT and RIGHT have the same target and assignee, nil otherwise."
154+
"Return t if the rules LEFT and RIGHT have the same target, assignee, and set of scopes."
151155
(and (eq (slot-value left 'assignee) (slot-value right 'assignee))
152-
(eq (slot-value left 'target) (slot-value right 'target))))
156+
(eq (slot-value left 'target) (slot-value right 'target))
157+
;; set equality for scopes slots
158+
(let ((lscopes (slot-value left 'scopes))
159+
(rscopes (slot-value right 'scopes)))
160+
(and
161+
(null (set-difference lscopes rscopes :test #'string=))
162+
(null (set-difference rscopes lscopes :test #'string=))))))
153163

154164
(defun find-matching-rule (rule rules)
155165
"Find a rule in RULES that `rules-match-p' RULE."
@@ -203,9 +213,9 @@ simply be down cased."
203213

204214
;; TODO: This partially replicates the logic in the `acl:grant' macro
205215
(defmethod odrl-to-acl ((concept permission))
206-
(with-slots (actions target assignee) concept
216+
(with-slots (actions target assignee scopes) concept
207217
(acl:grant*
208-
:scopes (list 'acl:_) ;; TODO: support scopes
218+
:scopes (or scopes (list 'acl:_))
209219
:rights (mapcar
210220
(lambda (action)
211221
(intern (symbol-name (odrl-to-acl action)) :keyword))
@@ -238,15 +248,16 @@ simply be down cased."
238248

239249
(defmethod print-object ((object rule) stream)
240250
(print-unreadable-object (object stream)
241-
(with-slots (uri actions target assignee) object
251+
(with-slots (uri actions target assignee scopes) object
242252
(format
243253
stream
244-
"~a ~a~&~2t<actions: ~{~a~^, ~}>~&~2t<target: ~a>~&~2t<assignee: ~a>"
254+
"~a ~a~&~2t<actions: ~{~a~^, ~}>~&~2t<target: ~a>~&~2t<assignee: ~a>~&~2t<scopes: ~{~a~^, ~}>"
245255
(type-of object)
246256
uri
247257
actions
248258
(uri target)
249-
(uri assignee)))))
259+
(uri assignee)
260+
scopes))))
250261

251262
(defmethod print-object ((concept action) stream)
252263
(print-unreadable-object (concept stream)

odrl/parse-ttl.lisp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ If FILENAME is nil, fall back to \"config\" as default filename for the policy f
3030
:ext-defined-by "http://mu.semte.ch/vocabularies/ext/definedBy"
3131
:ext-graph-prefix "http://mu.semte.ch/vocabularies/ext/graphPrefix"
3232
:ext-query-parameters "http://mu.semte.ch/vocabularies/ext/queryParameters"
33+
;; TODO: Use proper predicate
34+
:ext-scope "http://mu.semte.ch/vocabularies/ext/scope"
3335
:odrl-action "http://www.w3.org/ns/odrl/2/action"
3436
:odrl-assignee "http://www.w3.org/ns/odrl/2/assignee"
3537
:odrl-assigner "http://www.w3.org/ns/odrl/2/assigner"
@@ -341,13 +343,18 @@ ASSET-COL and PARTY-COL should be lists of, respectively, `asset-collection' and
341343
asset-col))
342344
(assignee (find-concept-with-uri
343345
(first-value-for-predicate (predicate-uri :odrl-assignee) triples)
344-
party-col)))
346+
party-col))
347+
(scopes (filter-predicate (predicate-uri :ext-scope) triples)))
345348
(make-instance
346349
'permission
347350
:uri (uri-string uri)
348351
:actions (when action (list (make-action action)))
349352
:target target
350-
:assignee assignee)))
353+
:assignee assignee
354+
:scopes (mapcar
355+
(lambda (scope)
356+
(cl-ttl-parser:rdf-literal-value (triple-object scope)))
357+
scopes))))
351358

352359
(defun make-action (uri)
353360
"Make an `action' instance for the given URI."

0 commit comments

Comments
 (0)