oldaplib 0.3.29__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oldaplib/ontologies/admin-testing.trig +62 -11
- oldaplib/ontologies/admin.trig +12 -51
- oldaplib/ontologies/gaga.trigs +23 -0
- oldaplib/ontologies/oldap.trig +138 -62
- oldaplib/src/connection.py +39 -34
- oldaplib/src/enums/adminpermissions.py +1 -1
- oldaplib/src/enums/datapermissions.py +20 -3
- oldaplib/src/enums/{permissionsetattr.py → roleattr.py} +2 -3
- oldaplib/src/enums/userattr.py +3 -2
- oldaplib/src/helpers/observable_dict.py +1 -0
- oldaplib/src/in_project.py +0 -1
- oldaplib/src/objectfactory.py +348 -105
- oldaplib/src/propertyclass.py +1 -1
- oldaplib/src/resourceclass.py +13 -2
- oldaplib/src/{permissionset.py → role.py} +90 -112
- oldaplib/src/user.py +176 -97
- oldaplib/src/userdataclass.py +67 -38
- oldaplib/src/version.py +1 -1
- oldaplib/test/test_datamodel.py +5 -2
- oldaplib/test/test_in_project.py +21 -20
- oldaplib/test/test_objectfactory.py +100 -34
- oldaplib/test/test_resourceclass.py +3 -3
- oldaplib/test/test_role.py +407 -0
- oldaplib/test/test_user.py +158 -98
- oldaplib/testdata/instances_test.trig +48 -26
- {oldaplib-0.3.29.dist-info → oldaplib-0.4.0.dist-info}/METADATA +1 -1
- {oldaplib-0.3.29.dist-info → oldaplib-0.4.0.dist-info}/RECORD +28 -27
- oldaplib/test/test_permissionset.py +0 -443
- {oldaplib-0.3.29.dist-info → oldaplib-0.4.0.dist-info}/WHEEL +0 -0
oldaplib/src/propertyclass.py
CHANGED
|
@@ -927,7 +927,7 @@ class PropertyClass(Model, Notify):
|
|
|
927
927
|
# If obj is already a member, keep it; otherwise look it up by value
|
|
928
928
|
prop_type = obj if isinstance(obj, OwlPropertyType) else OwlPropertyType(obj)
|
|
929
929
|
except ValueError as e:
|
|
930
|
-
raise OldapErrorNotFound(f'Unknown owl:Property type "{obj}"') from e
|
|
930
|
+
raise OldapErrorNotFound(f'{self._property_class_iri}: Unknown owl:Property type "{obj}"') from e
|
|
931
931
|
self._attributes[PropClassAttr.TYPE].add(prop_type)
|
|
932
932
|
case 'owl:subPropertyOf':
|
|
933
933
|
self._attributes[PropClassAttr.SUBPROPERTY_OF] = obj
|
oldaplib/src/resourceclass.py
CHANGED
|
@@ -1601,10 +1601,21 @@ class ResourceClass(Model, Notify):
|
|
|
1601
1601
|
sparql = f'INSERT DATA {{#E\n'
|
|
1602
1602
|
sparql += f' GRAPH {self._graph}:onto {{\n'
|
|
1603
1603
|
sparql += f'{blank:{indent * indent_inc}}{self._owlclass_iri} rdfs:subClassOf [\n'
|
|
1604
|
+
sparql += f'{blank:{(indent + 1) * indent_inc}}rdf:type owl:Restriction ;\n'
|
|
1604
1605
|
if isinstance(prop, Xsd_QName):
|
|
1605
|
-
sparql += prop.create_owl_part2(haspropdata=hasprop.haspropdata)
|
|
1606
|
+
# sparql += prop.create_owl_part2(haspropdata=hasprop.haspropdata)
|
|
1607
|
+
sparql += f'{blank:{(indent + 1) * indent_inc}}owl:onProperty {prop.toRdf}'
|
|
1608
|
+
if hasprop.haspropdata.minCount and hasprop.haspropdata.maxCount and hasprop.haspropdata.minCount == hasprop.haspropdata.maxCount:
|
|
1609
|
+
tmp = Xsd_nonNegativeInteger(hasprop.haspropdata.minCount)
|
|
1610
|
+
sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}owl:qualifiedCardinality {tmp.toRdf}'
|
|
1611
|
+
else:
|
|
1612
|
+
if hasprop.haspropdata.minCount:
|
|
1613
|
+
tmp = Xsd_nonNegativeInteger(hasprop.haspropdata.minCount)
|
|
1614
|
+
sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}owl:minQualifiedCardinality {tmp.toRdf}'
|
|
1615
|
+
if hasprop.haspropdata.maxCount:
|
|
1616
|
+
tmp = Xsd_nonNegativeInteger(hasprop.haspropdata.maxCount)
|
|
1617
|
+
sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}owl:maxQualifiedCardinality {tmp.toRdf}'
|
|
1606
1618
|
elif isinstance(prop, PropertyClass):
|
|
1607
|
-
sparql += f'{blank:{(indent + 1) * indent_inc}}rdf:type owl:Restriction ;\n'
|
|
1608
1619
|
sparql += f'{blank:{(indent + 1) * indent_inc}}owl:onProperty {prop.property_class_iri.toRdf}'
|
|
1609
1620
|
sparql += hasprop.create_owl(indent=1)
|
|
1610
1621
|
else:
|
|
@@ -12,9 +12,10 @@ from functools import partial
|
|
|
12
12
|
|
|
13
13
|
from oldaplib.src.cachesingleton import CacheSingletonRedis
|
|
14
14
|
from oldaplib.src.connection import Connection
|
|
15
|
-
from oldaplib.src.enums.
|
|
15
|
+
from oldaplib.src.enums.roleattr import RoleAttr
|
|
16
16
|
from oldaplib.src.enums.adminpermissions import AdminPermission
|
|
17
17
|
from oldaplib.src.enums.datapermissions import DataPermission
|
|
18
|
+
from oldaplib.src.enums.roleattr import RoleAttr
|
|
18
19
|
from oldaplib.src.helpers.context import Context
|
|
19
20
|
from oldaplib.src.enums.action import Action
|
|
20
21
|
from oldaplib.src.helpers.serializer import serializer
|
|
@@ -39,23 +40,23 @@ from oldaplib.src.xsd.xsd_string import Xsd_string
|
|
|
39
40
|
|
|
40
41
|
#@strict
|
|
41
42
|
@serializer
|
|
42
|
-
class
|
|
43
|
+
class Role(Model):
|
|
43
44
|
"""
|
|
44
|
-
Represents a
|
|
45
|
+
Represents a Role, typically for use in a semantic knowledge-based system.
|
|
45
46
|
|
|
46
|
-
This class provides methods to define, manage, and manipulate
|
|
47
|
+
This class provides methods to define, manage, and manipulate Roles, which specify
|
|
47
48
|
data access permissions within a project. It includes methods for creating permissions in
|
|
48
49
|
a triple store, validating consistency, and managing notifications for changes to attributes.
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
Roles are uniquely identified by their association with a project and their ID.
|
|
51
52
|
The class ensures that operations are consistent within a defined project context and
|
|
52
53
|
permissions are compliant with system access controls.
|
|
53
54
|
|
|
54
|
-
:ivar iri: The unique IRI of the
|
|
55
|
+
:ivar iri: The unique IRI of the role, derived from the project and permission set ID.
|
|
55
56
|
:type iri: Iri
|
|
56
57
|
"""
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
__role_iri: Xsd_QName | None
|
|
59
60
|
__project: Project | None
|
|
60
61
|
|
|
61
62
|
def __init__(self, *,
|
|
@@ -101,25 +102,25 @@ class PermissionSet(Model):
|
|
|
101
102
|
modified=modified,
|
|
102
103
|
validate=validate)
|
|
103
104
|
self.__project = None
|
|
104
|
-
self.set_attributes(kwargs,
|
|
105
|
+
self.set_attributes(kwargs, RoleAttr)
|
|
105
106
|
#
|
|
106
107
|
# Consistency checks
|
|
107
108
|
#
|
|
108
|
-
if self._attributes.get(
|
|
109
|
-
self.check_consistency(
|
|
109
|
+
if self._attributes.get(RoleAttr.DEFINED_BY_PROJECT):
|
|
110
|
+
self.check_consistency(RoleAttr.DEFINED_BY_PROJECT, self._attributes[RoleAttr.DEFINED_BY_PROJECT])
|
|
110
111
|
|
|
111
112
|
#
|
|
112
113
|
# The IRI of the permission set is a QName consisting of the prefix of the project (aka projectShortname)
|
|
113
114
|
# and the permissionSetId. Thus, the same permission set ID could be used in different projects...
|
|
114
115
|
#
|
|
115
|
-
self.
|
|
116
|
+
self.__role_iri = Xsd_QName(self.__project.projectShortName, self._attributes[RoleAttr.ROLE_ID])
|
|
116
117
|
#self.__permset_iri = Iri.fromPrefixFragment(self.__project.projectShortName, self._attributes[PermissionSetAttr.PERMISSION_SET_ID], validate=False)
|
|
117
118
|
|
|
118
|
-
for attr in
|
|
119
|
-
setattr(
|
|
120
|
-
partial(
|
|
121
|
-
partial(
|
|
122
|
-
partial(
|
|
119
|
+
for attr in RoleAttr:
|
|
120
|
+
setattr(Role, attr.value.fragment, property(
|
|
121
|
+
partial(Role._get_value, attr=attr),
|
|
122
|
+
partial(Role._set_value, attr=attr),
|
|
123
|
+
partial(Role._del_value, attr=attr)))
|
|
123
124
|
self._changeset = {}
|
|
124
125
|
|
|
125
126
|
def update_notifier(self):
|
|
@@ -145,19 +146,19 @@ class PermissionSet(Model):
|
|
|
145
146
|
# Copy internals of Model:
|
|
146
147
|
instance._attributes = deepcopy(self._attributes, memo)
|
|
147
148
|
instance._changset = deepcopy(self._changeset, memo)
|
|
148
|
-
instance.
|
|
149
|
+
instance.__role_iri = deepcopy(self.__role_iri, memo)
|
|
149
150
|
instance.__project = deepcopy(self.__project, memo)
|
|
150
151
|
return instance
|
|
151
152
|
|
|
152
|
-
def check_consistency(self, attr:
|
|
153
|
-
if attr ==
|
|
153
|
+
def check_consistency(self, attr: RoleAttr, value: Any) -> None:
|
|
154
|
+
if attr == RoleAttr.DEFINED_BY_PROJECT:
|
|
154
155
|
if not isinstance(value, Project):
|
|
155
156
|
self.__project = Project.read(self._con, value)
|
|
156
157
|
self._attributes[attr] = self.__project.projectIri
|
|
157
158
|
|
|
158
159
|
def check_for_permissions(self) -> (bool, str):
|
|
159
160
|
"""
|
|
160
|
-
Internal method to check if a user may modify
|
|
161
|
+
Internal method to check if a user may modify role.
|
|
161
162
|
:return: a tuple with a boolean (True, False) and the error message (or "OK")
|
|
162
163
|
"""
|
|
163
164
|
#
|
|
@@ -173,27 +174,27 @@ class PermissionSet(Model):
|
|
|
173
174
|
return True, "OK"
|
|
174
175
|
else:
|
|
175
176
|
if actor.inProject.get(self.definedByProject) is None:
|
|
176
|
-
return False, f'Actor has no
|
|
177
|
+
return False, f'Actor has no ADMIN_ROLES permission for project {self.definedByProject}'
|
|
177
178
|
else:
|
|
178
|
-
if AdminPermission.
|
|
179
|
-
return False, f'Actor has no
|
|
179
|
+
if AdminPermission.ADMIN_ROLES not in actor.inProject.get(self.definedByProject):
|
|
180
|
+
return False, f'Actor has no ADMIN_ROLES permission for project {self.definedByProject}'
|
|
180
181
|
return True, "OK"
|
|
181
182
|
|
|
182
|
-
def notifier(self, what:
|
|
183
|
+
def notifier(self, what: RoleAttr, value: Any = None) -> None:
|
|
183
184
|
self._changeset[what] = AttributeChange(None, Action.MODIFY)
|
|
184
185
|
|
|
185
186
|
@property
|
|
186
187
|
def iri(self) -> Xsd_QName:
|
|
187
|
-
return self.
|
|
188
|
+
return self.__role_iri
|
|
188
189
|
|
|
189
190
|
@property
|
|
190
191
|
def qname(self) -> Xsd_QName:
|
|
191
|
-
return self.
|
|
192
|
+
return self.__role_iri
|
|
192
193
|
|
|
193
194
|
def trig_to_str(self, created: Xsd_dateTime, modified: Xsd_dateTime, indent: int = 0, indent_inc: int = 4):
|
|
194
195
|
blank = ''
|
|
195
196
|
sparql = ''
|
|
196
|
-
sparql += f'{blank:{indent * indent_inc}} {self.
|
|
197
|
+
sparql += f'{blank:{indent * indent_inc}} {self.__role_iri.toRdf} a oldap:Role'
|
|
197
198
|
sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:creator {self._con.userIri.toRdf}'
|
|
198
199
|
sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:created {created.toRdf}'
|
|
199
200
|
sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:contributor {self._con.userIri.toRdf}'
|
|
@@ -207,12 +208,12 @@ class PermissionSet(Model):
|
|
|
207
208
|
|
|
208
209
|
def create(self, indent: int = 0, indent_inc: int = 4) -> None:
|
|
209
210
|
"""
|
|
210
|
-
Creates and stores a
|
|
211
|
+
Creates and stores a role in the triple store.
|
|
211
212
|
|
|
212
213
|
The method handles creating SPARQL queries to insert data related to
|
|
213
|
-
the given
|
|
214
|
+
the given role. The data includes metadata such as creator,
|
|
214
215
|
creation timestamp, contributors, and other attributes defined in the
|
|
215
|
-
|
|
216
|
+
role. It also ensures that no duplicate roles exists
|
|
216
217
|
before attempting insertion. The changes are managed as a transaction,
|
|
217
218
|
and the cache is updated upon successful persistence.
|
|
218
219
|
|
|
@@ -238,11 +239,11 @@ class PermissionSet(Model):
|
|
|
238
239
|
|
|
239
240
|
sparql1 = context.sparql_context
|
|
240
241
|
sparql1 += f"""
|
|
241
|
-
SELECT ?
|
|
242
|
+
SELECT ?role
|
|
242
243
|
FROM oldap:admin
|
|
243
244
|
WHERE {{
|
|
244
|
-
?
|
|
245
|
-
FILTER(?
|
|
245
|
+
?role a oldap:Role .
|
|
246
|
+
FILTER(?role = {self.__role_iri.toRdf})
|
|
246
247
|
}}
|
|
247
248
|
"""
|
|
248
249
|
|
|
@@ -252,15 +253,6 @@ class PermissionSet(Model):
|
|
|
252
253
|
sparql += f'{blank:{(indent + 1) * indent_inc}}GRAPH oldap:admin {{\n'
|
|
253
254
|
|
|
254
255
|
sparql += self.trig_to_str(created=timestamp, modified=timestamp, indent=indent + 2, indent_inc=indent_inc)
|
|
255
|
-
# sparql += f'{blank:{(indent + 2) * indent_inc}} {self.__permset_iri.toRdf} a oldap:PermissionSet'
|
|
256
|
-
# sparql += f' ;\n{blank:{(indent + 3) * indent_inc}}dcterms:creator {self._con.userIri.toRdf}'
|
|
257
|
-
# sparql += f' ;\n{blank:{(indent + 3) * indent_inc}}dcterms:created {timestamp.toRdf}'
|
|
258
|
-
# sparql += f' ;\n{blank:{(indent + 3) * indent_inc}}dcterms:contributor {self._con.userIri.toRdf}'
|
|
259
|
-
# sparql += f' ;\n{blank:{(indent + 3) * indent_inc}}dcterms:modified {timestamp.toRdf}'
|
|
260
|
-
# for attr, value in self._attributes.items():
|
|
261
|
-
# if attr.value.prefix == 'virtual' or not value:
|
|
262
|
-
# continue
|
|
263
|
-
# sparql += f' ;\n{blank:{(indent + 3) * indent_inc}}{attr.value.toRdf} {value.toRdf}'
|
|
264
256
|
sparql += f'\n{blank:{(indent + 1) * indent_inc}}}}\n'
|
|
265
257
|
sparql += f'{blank:{indent * indent_inc}}}}\n'
|
|
266
258
|
|
|
@@ -273,7 +265,7 @@ class PermissionSet(Model):
|
|
|
273
265
|
res = QueryProcessor(context, jsonobj)
|
|
274
266
|
if len(res) > 0:
|
|
275
267
|
self._con.transaction_abort()
|
|
276
|
-
raise OldapErrorAlreadyExists(f'A
|
|
268
|
+
raise OldapErrorAlreadyExists(f'A role "{self.__role_iri}" already exists')
|
|
277
269
|
|
|
278
270
|
try:
|
|
279
271
|
self._con.transaction_update(sparql)
|
|
@@ -290,13 +282,13 @@ class PermissionSet(Model):
|
|
|
290
282
|
self._modified = timestamp
|
|
291
283
|
self._contributor = self._con.userIri
|
|
292
284
|
cache = CacheSingletonRedis()
|
|
293
|
-
cache.set(self.
|
|
285
|
+
cache.set(self.__role_iri, self)
|
|
294
286
|
|
|
295
287
|
@classmethod
|
|
296
288
|
def read(cls, *,
|
|
297
289
|
con: IConnection,
|
|
298
290
|
qname: Xsd_QName | str | None = None,
|
|
299
|
-
|
|
291
|
+
roleId: Xsd_NCName | str | None = None,
|
|
300
292
|
definedByProject: Project | Iri | Xsd_NCName | str | None = None,
|
|
301
293
|
ignore_cache: bool = False) -> Self:
|
|
302
294
|
"""
|
|
@@ -307,7 +299,7 @@ class PermissionSet(Model):
|
|
|
307
299
|
:param con: The connection object used to interact with the system.
|
|
308
300
|
:param qname: The Internationalized Resource Identifier of the permission set. If provided,
|
|
309
301
|
it will be used to read the permission set.
|
|
310
|
-
:param
|
|
302
|
+
:param roleId: The unique identifier of the permission set within a project.
|
|
311
303
|
Required if `iri` is not provided.
|
|
312
304
|
:param definedByProject: The project either as an object, its IRI, or its short name
|
|
313
305
|
which defines the namespace of the permission set. This is
|
|
@@ -325,57 +317,56 @@ class PermissionSet(Model):
|
|
|
325
317
|
"""
|
|
326
318
|
context = Context(name=con.context_name)
|
|
327
319
|
if qname:
|
|
328
|
-
|
|
329
|
-
elif
|
|
330
|
-
id = Xsd_NCName(
|
|
320
|
+
role_iri = Xsd_QName(qname, validate=True)
|
|
321
|
+
elif roleId and definedByProject:
|
|
322
|
+
id = Xsd_NCName(roleId, validate=True)
|
|
331
323
|
|
|
332
324
|
if isinstance(definedByProject, Project):
|
|
333
325
|
project = definedByProject
|
|
334
326
|
else:
|
|
335
327
|
project = Project.read(con, definedByProject)
|
|
336
|
-
|
|
328
|
+
role_iri = Xsd_QName(project.projectShortName, roleId)
|
|
337
329
|
else:
|
|
338
|
-
raise OldapErrorValue('Either the parameter "iri" of both "
|
|
330
|
+
raise OldapErrorValue('Either the parameter "iri" of both "roleId" and "definedByProject" must be provided.')
|
|
339
331
|
if not ignore_cache:
|
|
340
332
|
cache = CacheSingletonRedis()
|
|
341
|
-
tmp = cache.get(
|
|
333
|
+
tmp = cache.get(role_iri, connection=con)
|
|
342
334
|
if tmp is not None:
|
|
343
335
|
tmp.update_notifier()
|
|
344
336
|
return tmp
|
|
345
337
|
sparql = context.sparql_context
|
|
346
338
|
sparql += f"""
|
|
347
|
-
SELECT ?
|
|
339
|
+
SELECT ?role ?p ?o
|
|
348
340
|
FROM oldap:admin
|
|
349
341
|
WHERE {{
|
|
350
|
-
BIND({
|
|
351
|
-
?
|
|
352
|
-
?
|
|
342
|
+
BIND({role_iri.toRdf} as ?role)
|
|
343
|
+
?role a oldap:Role .
|
|
344
|
+
?role ?p ?o .
|
|
353
345
|
}}
|
|
354
346
|
"""
|
|
355
347
|
jsonobj = con.query(sparql)
|
|
356
348
|
res = QueryProcessor(context, jsonobj)
|
|
357
349
|
if len(res) == 0:
|
|
358
|
-
raise OldapErrorNotFound(f'No permission set "{
|
|
350
|
+
raise OldapErrorNotFound(f'No permission set "{role_iri}"')
|
|
359
351
|
|
|
360
|
-
|
|
352
|
+
role_iri: Xsd_QName | None = None
|
|
361
353
|
creator: Iri | None = None
|
|
362
354
|
created: Xsd_dateTime | None = None
|
|
363
355
|
contributor: Iri | None = None
|
|
364
356
|
modified: Xsd_dateTime | None = None
|
|
365
357
|
label: LangString = LangString()
|
|
366
358
|
comment: LangString = LangString()
|
|
367
|
-
|
|
368
|
-
_permissionSetId: Xsd_NCName | None = None
|
|
359
|
+
_roleId: Xsd_NCName | None = None
|
|
369
360
|
_definedByProject: Iri | None = None
|
|
370
361
|
for r in res:
|
|
371
|
-
if not
|
|
362
|
+
if not role_iri:
|
|
372
363
|
try:
|
|
373
|
-
permset_iri = r['
|
|
364
|
+
permset_iri = r['role']
|
|
374
365
|
except Exception as e:
|
|
375
366
|
raise OldapErrorInconsistency(f'Invalid project identifier "{r['o']}".')
|
|
376
367
|
if not permset_iri.is_qname:
|
|
377
368
|
raise OldapErrorInconsistency(f'Invalid project identifier "{r['o']}".')
|
|
378
|
-
|
|
369
|
+
_roleId = permset_iri.fragment
|
|
379
370
|
match str(r['p']):
|
|
380
371
|
case 'dcterms:creator':
|
|
381
372
|
creator = r['o']
|
|
@@ -389,36 +380,32 @@ class PermissionSet(Model):
|
|
|
389
380
|
label.add(r['o'])
|
|
390
381
|
case 'rdfs:comment':
|
|
391
382
|
comment.add(r['o'])
|
|
392
|
-
case 'oldap:givesPermission':
|
|
393
|
-
givesPermission = DataPermission.from_string(str(r['o']))
|
|
394
383
|
case 'oldap:definedByProject':
|
|
395
384
|
_definedByProject = r['o']
|
|
396
|
-
cls.
|
|
385
|
+
cls.__role_iri = role_iri
|
|
397
386
|
if comment:
|
|
398
387
|
comment.clear_changeset()
|
|
399
|
-
comment.set_notifier(cls.notifier, Xsd_QName(
|
|
388
|
+
comment.set_notifier(cls.notifier, Xsd_QName(RoleAttr.LABEL.value))
|
|
400
389
|
if label:
|
|
401
390
|
label.clear_changeset()
|
|
402
|
-
label.set_notifier(cls.notifier, Xsd_QName(
|
|
391
|
+
label.set_notifier(cls.notifier, Xsd_QName(RoleAttr.LABEL.value))
|
|
403
392
|
instance = cls(con=con,
|
|
404
|
-
|
|
393
|
+
roleId=Xsd_NCName(_roleId, validate=False),
|
|
405
394
|
creator=creator,
|
|
406
395
|
created=created,
|
|
407
396
|
contributor=contributor,
|
|
408
397
|
modified=modified,
|
|
409
398
|
label=label,
|
|
410
399
|
comment=comment,
|
|
411
|
-
givesPermission=givesPermission,
|
|
412
400
|
definedByProject=Iri(_definedByProject, validate=False))
|
|
413
401
|
cache = CacheSingletonRedis()
|
|
414
|
-
cache.set(instance.
|
|
402
|
+
cache.set(instance.__role_iri, instance)
|
|
415
403
|
return instance
|
|
416
404
|
|
|
417
405
|
@staticmethod
|
|
418
406
|
def search(con: IConnection, *,
|
|
419
|
-
|
|
407
|
+
roleId: str | None = None,
|
|
420
408
|
definedByProject: Iri | str | None = None,
|
|
421
|
-
givesPermission: DataPermission | None = None,
|
|
422
409
|
label: Xsd_string | str | None = None) -> list[Iri | Xsd_QName]:
|
|
423
410
|
"""
|
|
424
411
|
Search for a permission set. At least one of the search criteria is required. Multiple search criteria are
|
|
@@ -426,12 +413,10 @@ class PermissionSet(Model):
|
|
|
426
413
|
|
|
427
414
|
:param con: A valid Connection object.
|
|
428
415
|
:type con: IConnection
|
|
429
|
-
:param
|
|
430
|
-
:type
|
|
416
|
+
:param roleId: Search for the given ID. The given string must be _contained_ in the ID (substring).
|
|
417
|
+
:type roleId: str | None
|
|
431
418
|
:param definedByProject: The project which is responsible for the permission set.
|
|
432
419
|
:type definedByProject: Iri | str | None
|
|
433
|
-
:param givesPermission: The permission that the permission set should grant.
|
|
434
|
-
:type givesPermission: DataPermission | None
|
|
435
420
|
:param label: The label string. The given string must be within at least one language label.
|
|
436
421
|
:type label: Xsd_string | str | None
|
|
437
422
|
:return: A list of permission set IRIs (possibly as Xsd_QName).
|
|
@@ -446,39 +431,32 @@ class PermissionSet(Model):
|
|
|
446
431
|
context = Context(name=con.context_name)
|
|
447
432
|
sparql = context.sparql_context
|
|
448
433
|
if definedByProject:
|
|
449
|
-
sparql += 'SELECT DISTINCT ?
|
|
434
|
+
sparql += 'SELECT DISTINCT ?roleIri ?namespaceIri ?projectShortName'
|
|
450
435
|
context = Context(name=con.context_name)
|
|
451
436
|
else:
|
|
452
|
-
sparql += 'SELECT DISTINCT ?
|
|
437
|
+
sparql += 'SELECT DISTINCT ?roleIri'
|
|
453
438
|
sparql += '\n'
|
|
454
439
|
sparql += 'FROM NAMED oldap:admin\n'
|
|
455
440
|
sparql += 'WHERE {\n'
|
|
456
441
|
sparql += ' GRAPH oldap:admin {\n'
|
|
457
|
-
sparql += ' ?
|
|
442
|
+
sparql += ' ?roleIri rdf:type oldap:Role .\n'
|
|
458
443
|
if definedByProject:
|
|
459
|
-
sparql += ' ?
|
|
444
|
+
sparql += ' ?roleIri oldap:definedByProject ?definedByProject .\n'
|
|
460
445
|
sparql += ' ?definedByProject oldap:namespaceIri ?namespaceIri .\n'
|
|
461
446
|
sparql += ' ?definedByProject oldap:projectShortName ?projectShortName .\n'
|
|
462
|
-
if givesPermission:
|
|
463
|
-
sparql += ' ?permsetIri oldap:givesPermission ?givesPermission .\n'
|
|
464
447
|
if label:
|
|
465
|
-
sparql += ' ?
|
|
466
|
-
if
|
|
448
|
+
sparql += ' ?roleIri rdfs:label ?label .\n'
|
|
449
|
+
if roleId or definedByProject or label:
|
|
467
450
|
sparql += ' FILTER('
|
|
468
451
|
use_and = False
|
|
469
|
-
if
|
|
470
|
-
sparql += f'CONTAINS(STR(?
|
|
452
|
+
if roleId:
|
|
453
|
+
sparql += f'CONTAINS(STR(?roleIri), "{Xsd_string.escaping(roleId)}")'
|
|
471
454
|
use_and = True
|
|
472
455
|
if definedByProject:
|
|
473
456
|
if use_and:
|
|
474
457
|
sparql += ' && '
|
|
475
458
|
sparql += f'?definedByProject = {definedByProject.toRdf}'
|
|
476
459
|
use_and = True
|
|
477
|
-
if givesPermission:
|
|
478
|
-
if use_and:
|
|
479
|
-
sparql += ' && '
|
|
480
|
-
sparql += f'?givesPermission = {givesPermission.toRdf}'
|
|
481
|
-
use_and = True
|
|
482
460
|
if label:
|
|
483
461
|
if use_and:
|
|
484
462
|
sparql += ' && '
|
|
@@ -491,15 +469,15 @@ class PermissionSet(Model):
|
|
|
491
469
|
sparql += '}\n'
|
|
492
470
|
jsonobj = con.query(sparql)
|
|
493
471
|
res = QueryProcessor(context, jsonobj)
|
|
494
|
-
|
|
472
|
+
roles: list[Xsd_QName] = []
|
|
495
473
|
for r in res:
|
|
496
474
|
if definedByProject:
|
|
497
475
|
#context[r['projectShortName']] = r['namespaceIri']
|
|
498
|
-
psqname = r['
|
|
499
|
-
|
|
476
|
+
psqname = r['roleIri'].as_qname or context.iri2qname(str(r['roleIri']), validate=False)
|
|
477
|
+
roles.append(psqname or r['roleIri'])
|
|
500
478
|
else:
|
|
501
|
-
|
|
502
|
-
return
|
|
479
|
+
roles.append(r['roleIri'])
|
|
480
|
+
return roles
|
|
503
481
|
|
|
504
482
|
def update(self, indent: int = 0, indent_inc: int = 4) -> None:
|
|
505
483
|
"""
|
|
@@ -528,20 +506,20 @@ class PermissionSet(Model):
|
|
|
528
506
|
sparql_list = []
|
|
529
507
|
|
|
530
508
|
for attr, change in self._changeset.items():
|
|
531
|
-
if attr ==
|
|
509
|
+
if attr == RoleAttr.LABEL or attr == RoleAttr.COMMENT:
|
|
532
510
|
if change.action == Action.MODIFY:
|
|
533
511
|
sparql_list.extend(self._attributes[attr].update(graph=Xsd_QName('oldap:admin'),
|
|
534
|
-
subject=self.
|
|
512
|
+
subject=self.__role_iri,
|
|
535
513
|
field=attr.value))
|
|
536
514
|
if change.action == Action.DELETE or change.action == Action.REPLACE:
|
|
537
515
|
sparql = self._changeset[attr].old_value.delete(graph=Xsd_QName('oldap:admin'),
|
|
538
|
-
|
|
539
|
-
|
|
516
|
+
subject=self.__role_iri,
|
|
517
|
+
field=attr.value)
|
|
540
518
|
sparql_list.append(sparql)
|
|
541
519
|
if change.action == Action.CREATE or change.action == Action.REPLACE:
|
|
542
520
|
sparql = self._attributes[attr].create(graph=Xsd_QName('oldap:admin'),
|
|
543
|
-
|
|
544
|
-
|
|
521
|
+
subject=self.__role_iri,
|
|
522
|
+
field=attr.value)
|
|
545
523
|
sparql_list.append(sparql)
|
|
546
524
|
continue
|
|
547
525
|
sparql = f'{blank:{indent * indent_inc}}# PermissionSet attribute "{attr.value}" with action "{change.action.value}"\n'
|
|
@@ -555,7 +533,7 @@ class PermissionSet(Model):
|
|
|
555
533
|
sparql += f'{blank:{(indent + 1) * indent_inc}}?project {attr.value} {self._attributes[attr].toRdf} .\n'
|
|
556
534
|
sparql += f'{blank:{indent * indent_inc}}}}\n'
|
|
557
535
|
sparql += f'{blank:{indent * indent_inc}}WHERE {{\n'
|
|
558
|
-
sparql += f'{blank:{(indent + 1) * indent_inc}}BIND({self.
|
|
536
|
+
sparql += f'{blank:{(indent + 1) * indent_inc}}BIND({self.__role_iri.toRdf} as ?project)\n'
|
|
559
537
|
sparql += f'{blank:{(indent + 1) * indent_inc}}?project {attr.value} {change.old_value.toRdf} .\n'
|
|
560
538
|
sparql += f'{blank:{indent * indent_inc}}}}'
|
|
561
539
|
sparql_list.append(sparql)
|
|
@@ -565,8 +543,8 @@ class PermissionSet(Model):
|
|
|
565
543
|
self._con.transaction_start()
|
|
566
544
|
try:
|
|
567
545
|
self._con.transaction_update(sparql)
|
|
568
|
-
self.set_modified_by_iri(Xsd_QName('oldap:admin'), self.
|
|
569
|
-
modtime = self.get_modified_by_iri(Xsd_QName('oldap:admin'), self.
|
|
546
|
+
self.set_modified_by_iri(Xsd_QName('oldap:admin'), self.__role_iri, self._modified, timestamp)
|
|
547
|
+
modtime = self.get_modified_by_iri(Xsd_QName('oldap:admin'), self.__role_iri)
|
|
570
548
|
except OldapError:
|
|
571
549
|
self._con.transaction_abort()
|
|
572
550
|
raise
|
|
@@ -581,7 +559,7 @@ class PermissionSet(Model):
|
|
|
581
559
|
self._modified = timestamp
|
|
582
560
|
self._contributor = self._con.userIri # TODO: move creator, created etc. to Model!
|
|
583
561
|
cache = CacheSingletonRedis()
|
|
584
|
-
cache.set(self.
|
|
562
|
+
cache.set(self.__role_iri, self)
|
|
585
563
|
|
|
586
564
|
|
|
587
565
|
def in_use_queries(self) -> (str, str):
|
|
@@ -608,7 +586,7 @@ class PermissionSet(Model):
|
|
|
608
586
|
ASK FROM oldap:admin
|
|
609
587
|
WHERE {{
|
|
610
588
|
?user a oldap:User ;
|
|
611
|
-
oldap:
|
|
589
|
+
oldap:hasRole {self.__role_iri.toRdf} .
|
|
612
590
|
}}
|
|
613
591
|
"""
|
|
614
592
|
|
|
@@ -619,7 +597,7 @@ class PermissionSet(Model):
|
|
|
619
597
|
query2 += f"""
|
|
620
598
|
ASK {{
|
|
621
599
|
GRAPH ?graph {{
|
|
622
|
-
?instance oldap:
|
|
600
|
+
?instance oldap:attachedToRole {self.__role_iri.toRdf} .
|
|
623
601
|
}}
|
|
624
602
|
}}
|
|
625
603
|
"""
|
|
@@ -671,7 +649,7 @@ class PermissionSet(Model):
|
|
|
671
649
|
:rtype: None
|
|
672
650
|
|
|
673
651
|
:raises OldapErrorNoPermission: Insufficient permissions to perform the update
|
|
674
|
-
:raises OldapErrorInUse:
|
|
652
|
+
:raises OldapErrorInUse: Role is still in use
|
|
675
653
|
:raises OldapError: For any general error encountered during the operation.
|
|
676
654
|
"""
|
|
677
655
|
result, message = self.check_for_permissions()
|
|
@@ -687,7 +665,7 @@ class PermissionSet(Model):
|
|
|
687
665
|
sparql += f"""
|
|
688
666
|
DELETE WHERE {{
|
|
689
667
|
GRAPH oldap:admin {{
|
|
690
|
-
{self.
|
|
668
|
+
{self.__role_iri.toRdf} ?prop ?val .
|
|
691
669
|
}}
|
|
692
670
|
}}
|
|
693
671
|
"""
|
|
@@ -706,5 +684,5 @@ class PermissionSet(Model):
|
|
|
706
684
|
self._con.transaction_abort()
|
|
707
685
|
raise
|
|
708
686
|
cache = CacheSingletonRedis()
|
|
709
|
-
cache.delete(self.
|
|
687
|
+
cache.delete(self.__role_iri)
|
|
710
688
|
|