From 0ad6cf858d932ae260ec18e99566786a245895f2 Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Tue, 26 Sep 2023 14:55:34 +0200 Subject: [PATCH 1/8] apply stash --- dsp_permissions_scripts/main.py | 18 +++++----- dsp_permissions_scripts/models/permission.py | 7 ++++ dsp_permissions_scripts/utils/permissions.py | 16 +++++++++ dsp_permissions_scripts/utils/project.py | 37 ++++++++++++-------- 4 files changed, 54 insertions(+), 24 deletions(-) diff --git a/dsp_permissions_scripts/main.py b/dsp_permissions_scripts/main.py index 5aa8af40..401d1fb2 100644 --- a/dsp_permissions_scripts/main.py +++ b/dsp_permissions_scripts/main.py @@ -11,7 +11,7 @@ update_permissions_for_resources_and_values, ) from dsp_permissions_scripts.utils.project import ( - get_all_resource_iris_of_project, + get_all_resources_of_project, get_project_iri_by_shortcode, ) @@ -42,14 +42,14 @@ def main() -> None: host=host, shortcode=shortcode, ) - set_doaps_of_groups( - scope=new_scope, - groups=groups, - host=host, - shortcode=shortcode, - token=token, - ) - resource_iris = get_all_resource_iris_of_project( + # set_doaps_of_groups( + # scope=new_scope, + # groups=groups, + # host=host, + # shortcode=shortcode, + # token=token, + # ) + resources = get_all_resources_of_project( project_iri=project_iri, host=host, token=token, diff --git a/dsp_permissions_scripts/models/permission.py b/dsp_permissions_scripts/models/permission.py index b47021c4..907468dd 100644 --- a/dsp_permissions_scripts/models/permission.py +++ b/dsp_permissions_scripts/models/permission.py @@ -52,3 +52,10 @@ class DoapTargetType(Enum): GROUP = "group" RESOURCE_CLASS = "resource_class" PROPERTY = "property" + + +class Oap(BaseModel): + """Model representing an object access permission, containing a scope and the IRI of the resource/value""" + + scope: list[PermissionScopeElement] + object_iri: str diff --git a/dsp_permissions_scripts/utils/permissions.py b/dsp_permissions_scripts/utils/permissions.py index 1547e455..82fe1a36 100644 --- a/dsp_permissions_scripts/utils/permissions.py +++ b/dsp_permissions_scripts/utils/permissions.py @@ -112,6 +112,22 @@ def __marshal_scope_as_permission_string(scope: list[PermissionScopeElement]) -> return "|".join(strs) +def permission_string_as_marshal_scope(perm_string: str) -> list[PermissionScopeElement]: + """ + Deserializes a permissions string as used by /v2 routes to a permission scope. + """ + res = [] + scopes = perm_string.split("|") + for scope in scopes: + code, groups_as_str = scope.split(" ") + groups = groups_as_str.split(",") + groups = [g.replace("knora-admin:", "http://www.knora.org/ontology/knora-admin#") for g in groups] + for group in groups: + res.append(PermissionScopeElement(info=group, name=code)) + return res + + + def __get_scope_element(scope: dict[str, Any]) -> PermissionScopeElement: """ turns permissions JSON as returned by /admin/permissions routes into a PermissionScopeElement object. diff --git a/dsp_permissions_scripts/utils/project.py b/dsp_permissions_scripts/utils/project.py index b764f89a..a07c2a1d 100644 --- a/dsp_permissions_scripts/utils/project.py +++ b/dsp_permissions_scripts/utils/project.py @@ -2,7 +2,9 @@ import requests +from dsp_permissions_scripts.models.permission import Oap from dsp_permissions_scripts.utils.authentication import get_protocol +from dsp_permissions_scripts.utils.permissions import permission_string_as_marshal_scope def get_project_iri_by_shortcode(shortcode: str, host: str) -> str: @@ -17,29 +19,29 @@ def get_project_iri_by_shortcode(shortcode: str, host: str) -> str: return iri -def get_all_resource_iris_of_project( +def get_all_resources_of_project( project_iri: str, host: str, token: str, -) -> list[str]: - all_resource_iris = [] - resclasses = __get_all_resource_class_iris_of_project( +) -> list[Oap]: + all_resources = [] + resclasses = __get_all_resource_classes_of_project( project_iri=project_iri, host=host, token=token, ) for resclass in resclasses: - resource_iris = __get_all_resource_iris_of_resclass( + resources = __get_all_resources_of_resclass( host=host, resclass=resclass, project_iri=project_iri, token=token, ) - all_resource_iris.extend(resource_iris) - return all_resource_iris + all_resources.extend(resources) + return all_resources -def __get_all_resource_class_iris_of_project( +def __get_all_resource_classes_of_project( project_iri: str, host: str, token: str, @@ -97,15 +99,15 @@ def __dereference_prefix(identifier: str, context: dict[str, str]) -> str: return context[prefix] + actual_id -def __get_all_resource_iris_of_resclass( +def __get_all_resources_of_resclass( host: str, resclass: str, project_iri: str, token: str, -) -> list[str]: +) -> list[Oap]: protocol = get_protocol(host) headers = {"X-Knora-Accept-Project": project_iri, "Authorization": f"Bearer {token}"} - resource_iris = [] + resources: list[str] = [] page = 0 more = True while more: @@ -116,9 +118,9 @@ def __get_all_resource_iris_of_resclass( page=page, headers=headers, ) - resource_iris.extend(iris) + resources.extend(iris) page += 1 - return resource_iris + return resources def __get_next_page( @@ -143,10 +145,15 @@ def __get_next_page( result = response.json() if "@graph" in result: # result contains several resources: return them, then continue with next page - return True, [r["@id"] for r in result["@graph"]] + oaps = [] + for r in result["@graph"]: + scope=permission_string_as_marshal_scope(r["knora-api:hasPermissions"]) + oaps.append(Oap(scope=scope, object_iri=r["@id"])) + return True, oaps elif "@id" in result: # result contains only 1 resource: return it, then stop (there will be no more resources) - return False, [result["@id"], ] + scope=permission_string_as_marshal_scope(result["knora-api:hasPermissions"]) + return False, [Oap(scope=scope, object_iri=result["@id"]), ] else: # there are no more resources return False, [] From b9810adada2b3e0f751c9c9eab7959f06ad4f698 Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Tue, 26 Sep 2023 15:47:37 +0200 Subject: [PATCH 2/8] nachbesserung von apply stash --- dsp_permissions_scripts/utils/permissions.py | 2 +- dsp_permissions_scripts/utils/project.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/dsp_permissions_scripts/utils/permissions.py b/dsp_permissions_scripts/utils/permissions.py index 82fe1a36..5c27a4f5 100644 --- a/dsp_permissions_scripts/utils/permissions.py +++ b/dsp_permissions_scripts/utils/permissions.py @@ -112,7 +112,7 @@ def __marshal_scope_as_permission_string(scope: list[PermissionScopeElement]) -> return "|".join(strs) -def permission_string_as_marshal_scope(perm_string: str) -> list[PermissionScopeElement]: +def __unmarshal_permission_string_to_scope(perm_string: str) -> list[PermissionScopeElement]: """ Deserializes a permissions string as used by /v2 routes to a permission scope. """ diff --git a/dsp_permissions_scripts/utils/project.py b/dsp_permissions_scripts/utils/project.py index a07c2a1d..0af91493 100644 --- a/dsp_permissions_scripts/utils/project.py +++ b/dsp_permissions_scripts/utils/project.py @@ -4,7 +4,9 @@ from dsp_permissions_scripts.models.permission import Oap from dsp_permissions_scripts.utils.authentication import get_protocol -from dsp_permissions_scripts.utils.permissions import permission_string_as_marshal_scope +from dsp_permissions_scripts.utils.permissions import ( + __unmarshal_permission_string_to_scope, +) def get_project_iri_by_shortcode(shortcode: str, host: str) -> str: @@ -107,7 +109,7 @@ def __get_all_resources_of_resclass( ) -> list[Oap]: protocol = get_protocol(host) headers = {"X-Knora-Accept-Project": project_iri, "Authorization": f"Bearer {token}"} - resources: list[str] = [] + resources: list[Oap] = [] page = 0 more = True while more: @@ -129,7 +131,7 @@ def __get_next_page( resclass: str, page: int, headers: dict[str, str], -) -> tuple[bool, list[str]]: +) -> tuple[bool, list[Oap]]: """ Get the resource IRIs of a resource class, one page at a time. DSP-API returns results page-wise: @@ -147,12 +149,12 @@ def __get_next_page( # result contains several resources: return them, then continue with next page oaps = [] for r in result["@graph"]: - scope=permission_string_as_marshal_scope(r["knora-api:hasPermissions"]) + scope=__unmarshal_permission_string_to_scope(r["knora-api:hasPermissions"]) oaps.append(Oap(scope=scope, object_iri=r["@id"])) return True, oaps elif "@id" in result: # result contains only 1 resource: return it, then stop (there will be no more resources) - scope=permission_string_as_marshal_scope(result["knora-api:hasPermissions"]) + scope=__unmarshal_permission_string_to_scope(result["knora-api:hasPermissions"]) return False, [Oap(scope=scope, object_iri=result["@id"]), ] else: # there are no more resources From fc17aeebea5cc25641951e2c42a7d46515934204 Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Mon, 2 Oct 2023 12:23:54 +0200 Subject: [PATCH 3/8] revert permissions.py --- dsp_permissions_scripts/utils/permissions.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/dsp_permissions_scripts/utils/permissions.py b/dsp_permissions_scripts/utils/permissions.py index 5c27a4f5..1547e455 100644 --- a/dsp_permissions_scripts/utils/permissions.py +++ b/dsp_permissions_scripts/utils/permissions.py @@ -112,22 +112,6 @@ def __marshal_scope_as_permission_string(scope: list[PermissionScopeElement]) -> return "|".join(strs) -def __unmarshal_permission_string_to_scope(perm_string: str) -> list[PermissionScopeElement]: - """ - Deserializes a permissions string as used by /v2 routes to a permission scope. - """ - res = [] - scopes = perm_string.split("|") - for scope in scopes: - code, groups_as_str = scope.split(" ") - groups = groups_as_str.split(",") - groups = [g.replace("knora-admin:", "http://www.knora.org/ontology/knora-admin#") for g in groups] - for group in groups: - res.append(PermissionScopeElement(info=group, name=code)) - return res - - - def __get_scope_element(scope: dict[str, Any]) -> PermissionScopeElement: """ turns permissions JSON as returned by /admin/permissions routes into a PermissionScopeElement object. From b5b85683558a0fe962dc1ac245d3db3676c1554d Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Mon, 2 Oct 2023 17:46:30 +0200 Subject: [PATCH 4/8] small fixes & improvements --- dsp_permissions_scripts/main.py | 16 ++++++++-------- dsp_permissions_scripts/models/permission.py | 4 ++-- dsp_permissions_scripts/utils/permissions.py | 4 ++-- tests/test_scope_serialization.py | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/dsp_permissions_scripts/main.py b/dsp_permissions_scripts/main.py index f5a65891..ee194806 100644 --- a/dsp_permissions_scripts/main.py +++ b/dsp_permissions_scripts/main.py @@ -42,14 +42,14 @@ def main() -> None: host=host, shortcode=shortcode, ) - # set_doaps_of_groups( - # scope=new_scope, - # groups=groups, - # host=host, - # shortcode=shortcode, - # token=token, - # ) - resources = get_all_resources_of_project( + set_doaps_of_groups( + scope=new_scope, + groups=groups, + host=host, + shortcode=shortcode, + token=token, + ) + resource_oaps = get_all_resources_of_project( project_iri=project_iri, host=host, token=token, diff --git a/dsp_permissions_scripts/models/permission.py b/dsp_permissions_scripts/models/permission.py index fb471ef2..aa639c45 100644 --- a/dsp_permissions_scripts/models/permission.py +++ b/dsp_permissions_scripts/models/permission.py @@ -33,7 +33,7 @@ class Doap(BaseModel): target: DoapTarget scope: PermissionScope - iri: str + doap_iri: str class DoapTargetType(Enum): @@ -46,5 +46,5 @@ class DoapTargetType(Enum): class Oap(BaseModel): """Model representing an object access permission, containing a scope and the IRI of the resource/value""" - scope: list[PermissionScopeElement] + scope: PermissionScope object_iri: str diff --git a/dsp_permissions_scripts/utils/permissions.py b/dsp_permissions_scripts/utils/permissions.py index ca6d79df..d811536f 100644 --- a/dsp_permissions_scripts/utils/permissions.py +++ b/dsp_permissions_scripts/utils/permissions.py @@ -77,7 +77,7 @@ def set_doaps_of_groups( print("Old DOAP:\n=========") print(d.model_dump_json(indent=2)) new_doap = update_doap_scope( - doap_iri=d.iri, + doap_iri=d.doap_iri, scope=scope, host=host, token=token, @@ -101,7 +101,7 @@ def __get_doap(permission: dict[str, Any]) -> Doap: property=permission["forProperty"], ), scope=scope, - iri=permission["iri"], + doap_iri=permission["iri"], ) return doap diff --git a/tests/test_scope_serialization.py b/tests/test_scope_serialization.py index 920949aa..41ecc542 100644 --- a/tests/test_scope_serialization.py +++ b/tests/test_scope_serialization.py @@ -1,5 +1,5 @@ -from typing import Any import unittest +from typing import Any from dsp_permissions_scripts.models.groups import BuiltinGroup from dsp_permissions_scripts.models.scope import PermissionScope From 183145ca66d1c7d72ffdd03e1a1f6190c7d3e7b7 Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Mon, 2 Oct 2023 17:59:16 +0200 Subject: [PATCH 5/8] improve naming --- dsp_permissions_scripts/main.py | 6 +++--- dsp_permissions_scripts/utils/project.py | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dsp_permissions_scripts/main.py b/dsp_permissions_scripts/main.py index ee194806..37c50f21 100644 --- a/dsp_permissions_scripts/main.py +++ b/dsp_permissions_scripts/main.py @@ -11,7 +11,7 @@ update_permissions_for_resources_and_values, ) from dsp_permissions_scripts.utils.project import ( - get_all_resources_of_project, + get_all_resource_oaps_of_project, get_project_iri_by_shortcode, ) @@ -49,13 +49,13 @@ def main() -> None: shortcode=shortcode, token=token, ) - resource_oaps = get_all_resources_of_project( + resource_oaps = get_all_resource_oaps_of_project( project_iri=project_iri, host=host, token=token, ) update_permissions_for_resources_and_values( - resource_iris=resource_iris, + resource_iris=resource_oaps_updated, scope=new_scope, host=host, token=token, diff --git a/dsp_permissions_scripts/utils/project.py b/dsp_permissions_scripts/utils/project.py index 385f6c38..ebd6ec29 100644 --- a/dsp_permissions_scripts/utils/project.py +++ b/dsp_permissions_scripts/utils/project.py @@ -19,29 +19,29 @@ def get_project_iri_by_shortcode(shortcode: str, host: str) -> str: return iri -def get_all_resources_of_project( +def get_all_resource_oaps_of_project( project_iri: str, host: str, token: str, ) -> list[Oap]: - all_resources = [] - resclasses = __get_all_resource_classes_of_project( + all_resource_oaps = [] + resclass_iris = __get_all_resource_class_iris_of_project( project_iri=project_iri, host=host, token=token, ) - for resclass in resclasses: - resources = __get_all_resources_of_resclass( + for resclass_iri in resclass_iris: + resource_oaps = __get_all_resource_oaps_of_resclass( host=host, - resclass=resclass, + resclass_iri=resclass_iri, project_iri=project_iri, token=token, ) - all_resources.extend(resources) - return all_resources + all_resource_oaps.extend(resource_oaps) + return all_resource_oaps -def __get_all_resource_classes_of_project( +def __get_all_resource_class_iris_of_project( project_iri: str, host: str, token: str, @@ -99,9 +99,9 @@ def __dereference_prefix(identifier: str, context: dict[str, str]) -> str: return context[prefix] + actual_id -def __get_all_resources_of_resclass( +def __get_all_resource_oaps_of_resclass( host: str, - resclass: str, + resclass_iri: str, project_iri: str, token: str, ) -> list[Oap]: @@ -114,7 +114,7 @@ def __get_all_resources_of_resclass( more, iris = __get_next_page( protocol=protocol, host=host, - resclass=resclass, + resclass=resclass_iri, page=page, headers=headers, ) From 171bef0423640aaa31c10e9aab4439d4db2a3faf Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Tue, 3 Oct 2023 07:21:13 +0200 Subject: [PATCH 6/8] implement modify_oaps() --- dsp_permissions_scripts/main.py | 15 +++++++++++---- dsp_permissions_scripts/utils/permissions.py | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/dsp_permissions_scripts/main.py b/dsp_permissions_scripts/main.py index 37c50f21..ebd8d56e 100644 --- a/dsp_permissions_scripts/main.py +++ b/dsp_permissions_scripts/main.py @@ -2,13 +2,14 @@ from dsp_permissions_scripts.models.groups import BuiltinGroup from dsp_permissions_scripts.models.host import Hosts +from dsp_permissions_scripts.models.permission import Oap from dsp_permissions_scripts.models.scope import PUBLIC from dsp_permissions_scripts.utils.authentication import login from dsp_permissions_scripts.utils.permissions import ( + apply_updated_oaps_on_server, get_doaps_of_project, print_doaps_of_project, set_doaps_of_groups, - update_permissions_for_resources_and_values, ) from dsp_permissions_scripts.utils.project import ( get_all_resource_oaps_of_project, @@ -16,6 +17,12 @@ ) +def modify_oaps(oaps: list[Oap]) -> list[Oap]: + for oap in oaps: + oap.scope.D.append(BuiltinGroup.PROJECT_MEMBER) + return oaps + + def main() -> None: """ The main method assembles a sample call of all available high-level functions. @@ -54,9 +61,9 @@ def main() -> None: host=host, token=token, ) - update_permissions_for_resources_and_values( - resource_iris=resource_oaps_updated, - scope=new_scope, + resource_oaps_updated = modify_oaps(oaps=resource_oaps) + apply_updated_oaps_on_server( + resource_oaps=resource_oaps_updated, host=host, token=token, ) diff --git a/dsp_permissions_scripts/utils/permissions.py b/dsp_permissions_scripts/utils/permissions.py index d811536f..2059a9af 100644 --- a/dsp_permissions_scripts/utils/permissions.py +++ b/dsp_permissions_scripts/utils/permissions.py @@ -9,6 +9,7 @@ Doap, DoapTarget, DoapTargetType, + Oap, PermissionScope, ) from dsp_permissions_scripts.models.value import ValueUpdate @@ -233,6 +234,21 @@ def update_doap_scope( return new_doap +def apply_updated_oaps_on_server( + resource_oaps: list[Oap], + host: str, + token: str, +) -> None: + """Applies object access permissions on a DSP server.""" + for resource_oap in resource_oaps: + update_permissions_for_resources_and_values( + resource_iris=[resource_oap.object_iri], + scope=resource_oap.scope, + host=host, + token=token, + ) + + def update_permissions_for_resources_and_values( resource_iris: list[str], scope: PermissionScope, From 348737d25ee671509a2ddb11d9ace1f622a553c4 Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Tue, 3 Oct 2023 07:45:00 +0200 Subject: [PATCH 7/8] blacken --- dsp_permissions_scripts/utils/project.py | 12 ++++++------ tests/test_scope_serialization.py | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/dsp_permissions_scripts/utils/project.py b/dsp_permissions_scripts/utils/project.py index ebd6ec29..3c474fd3 100644 --- a/dsp_permissions_scripts/utils/project.py +++ b/dsp_permissions_scripts/utils/project.py @@ -20,7 +20,7 @@ def get_project_iri_by_shortcode(shortcode: str, host: str) -> str: def get_all_resource_oaps_of_project( - project_iri: str, + project_iri: str, host: str, token: str, ) -> list[Oap]: @@ -42,7 +42,7 @@ def get_all_resource_oaps_of_project( def __get_all_resource_class_iris_of_project( - project_iri: str, + project_iri: str, host: str, token: str, ) -> list[str]: @@ -100,7 +100,7 @@ def __dereference_prefix(identifier: str, context: dict[str, str]) -> str: def __get_all_resource_oaps_of_resclass( - host: str, + host: str, resclass_iri: str, project_iri: str, token: str, @@ -147,13 +147,13 @@ def __get_next_page( # result contains several resources: return them, then continue with next page oaps = [] for r in result["@graph"]: - scope=create_scope_from_string(r["knora-api:hasPermissions"]) + scope = create_scope_from_string(r["knora-api:hasPermissions"]) oaps.append(Oap(scope=scope, object_iri=r["@id"])) return True, oaps elif "@id" in result: # result contains only 1 resource: return it, then stop (there will be no more resources) - scope=create_scope_from_string(result["knora-api:hasPermissions"]) - return False, [Oap(scope=scope, object_iri=result["@id"]), ] + scope = create_scope_from_string(result["knora-api:hasPermissions"]) + return False, [Oap(scope=scope, object_iri=result["@id"])] else: # there are no more resources return False, [] diff --git a/tests/test_scope_serialization.py b/tests/test_scope_serialization.py index 41ecc542..858981d8 100644 --- a/tests/test_scope_serialization.py +++ b/tests/test_scope_serialization.py @@ -101,9 +101,10 @@ def _resolve_prefixes_of_admin_route_object(self, admin_route_object: list[dict[ "knora-admin:", "http://www.knora.org/ontology/knora-admin#" ) return admin_route_object - + def _resolve_prefixes_of_perm_string(self, perm_string: str) -> str: return perm_string.replace("knora-admin:", "http://www.knora.org/ontology/knora-admin#") + if __name__ == "__main__": unittest.main() From 9fc3287c9147d9f7def55226b07e96298d2399ce Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Tue, 3 Oct 2023 16:38:48 +0200 Subject: [PATCH 8/8] rename main.py to template.py --- dsp_permissions_scripts/{main.py => template.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dsp_permissions_scripts/{main.py => template.py} (100%) diff --git a/dsp_permissions_scripts/main.py b/dsp_permissions_scripts/template.py similarity index 100% rename from dsp_permissions_scripts/main.py rename to dsp_permissions_scripts/template.py