From d1ed804e85495b464138fea63beee34aea2ebd5f Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum <39048939+jnussbaum@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:09:24 +0200 Subject: [PATCH] refactor: remodel DoapTarget (#130) --- dsp_permissions_scripts/doap/doap_get.py | 21 +++++----- dsp_permissions_scripts/doap/doap_model.py | 45 ++++++++++------------ dsp_permissions_scripts/doap/doap_set.py | 11 +++--- dsp_permissions_scripts/template.py | 7 ++-- tests/test_doap_serialization.py | 6 +-- tests/test_doap_set.py | 4 +- 6 files changed, 47 insertions(+), 47 deletions(-) diff --git a/dsp_permissions_scripts/doap/doap_get.py b/dsp_permissions_scripts/doap/doap_get.py index d6dbf09d..ff5b7579 100644 --- a/dsp_permissions_scripts/doap/doap_get.py +++ b/dsp_permissions_scripts/doap/doap_get.py @@ -2,7 +2,8 @@ from urllib.parse import quote_plus from dsp_permissions_scripts.doap.doap_model import Doap -from dsp_permissions_scripts.doap.doap_model import DoapTarget +from dsp_permissions_scripts.doap.doap_model import EntityDoapTarget +from dsp_permissions_scripts.doap.doap_model import GroupDoapTarget from dsp_permissions_scripts.models.errors import ApiError from dsp_permissions_scripts.models.group import Group from dsp_permissions_scripts.utils.dsp_client import DspClient @@ -28,17 +29,19 @@ def _get_all_doaps_of_project(project_iri: str, dsp_client: DspClient) -> list[D def create_doap_from_admin_route_response(permission: dict[str, Any]) -> Doap: """Deserializes a DOAP from JSON as returned by /admin/permissions/doap/{project_iri}""" scope = create_scope_from_admin_route_object(permission["hasPermissions"]) - doap = Doap( - target=DoapTarget( - project_iri=permission["forProject"], - group=Group(val=permission["forGroup"]) if permission.get("forGroup") else None, - resource_class=permission.get("forResourceClass"), - property=permission.get("forProperty"), - ), + target: GroupDoapTarget | EntityDoapTarget + match permission: + case {"forProject": project_iri, "forGroup": group}: + target = GroupDoapTarget(project_iri=project_iri, group=Group(val=group)) + case {"forProject": project_iri, **p}: + target = EntityDoapTarget( + project_iri=project_iri, resource_class=p.get("forResourceClass"), property=p.get("forProperty") + ) + return Doap( + target=target, scope=scope, doap_iri=permission["iri"], ) - return doap def get_doaps_of_project(shortcode: str, dsp_client: DspClient) -> list[Doap]: diff --git a/dsp_permissions_scripts/doap/doap_model.py b/dsp_permissions_scripts/doap/doap_model.py index a2f7a777..bb8e8101 100644 --- a/dsp_permissions_scripts/doap/doap_model.py +++ b/dsp_permissions_scripts/doap/doap_model.py @@ -12,47 +12,42 @@ class Doap(BaseModel): """Model representing a DOAP, containing the target, the scope and the IRI of the DOAP.""" - target: DoapTarget + target: GroupDoapTarget | EntityDoapTarget scope: PermissionScope doap_iri: str -class DoapTarget(BaseModel): +class GroupDoapTarget(BaseModel): + project_iri: str + group: Group + + +class EntityDoapTarget(BaseModel): project_iri: str - group: Group | None = None resource_class: str | None = None property: str | None = None @model_validator(mode="after") - def assert_correct_combination(self) -> Self: - # asserts that DOAP is only defined for Group or ResourceClass or Property - # or a combination of ResourceClass and Property - match (self.group, self.resource_class, self.property): - case (None, None, None): - raise ValueError("At least one of group, resource_class or property must be set") - case (_, None, None) | (None, _, _): - pass - case _: - raise ValueError("Invalid combination of group, resource_class and property") + def _validate(self) -> Self: + if self.resource_class is None and self.property is None: + raise ValueError("At least one of resource_class or property must be set") return self -class NewDoapTarget(BaseModel): +class NewGroupDoapTarget(BaseModel): + """Represents the target of a DOAP that is yet to be created.""" + + group: Group + + +class NewEntityDoapTarget(BaseModel): """Represents the target of a DOAP that is yet to be created.""" - group: Group | None = None resource_class: str | None = None property: str | None = None @model_validator(mode="after") - def assert_correct_combination(self) -> Self: - # asserts that DOAP is only defined for Group or ResourceClass or Property - # or a combination of ResourceClass and Property - match (self.group, self.resource_class, self.property): - case (None, None, None): - raise ValueError("At least one of group, resource_class or property must be set") - case (_, None, None) | (None, _, _): - pass - case _: - raise ValueError("Invalid combination of group, resource_class and property") + def _validate(self) -> Self: + if self.resource_class is None and self.property is None: + raise ValueError("At least one of resource_class or property must be set") return self diff --git a/dsp_permissions_scripts/doap/doap_set.py b/dsp_permissions_scripts/doap/doap_set.py index 52c70687..71e2505b 100644 --- a/dsp_permissions_scripts/doap/doap_set.py +++ b/dsp_permissions_scripts/doap/doap_set.py @@ -2,7 +2,8 @@ from dsp_permissions_scripts.doap.doap_get import create_doap_from_admin_route_response from dsp_permissions_scripts.doap.doap_model import Doap -from dsp_permissions_scripts.doap.doap_model import NewDoapTarget +from dsp_permissions_scripts.doap.doap_model import NewEntityDoapTarget +from dsp_permissions_scripts.doap.doap_model import NewGroupDoapTarget from dsp_permissions_scripts.models.errors import ApiError from dsp_permissions_scripts.models.scope import PermissionScope from dsp_permissions_scripts.utils.dsp_client import DspClient @@ -40,17 +41,17 @@ def apply_updated_scopes_of_doaps_on_server(doaps: list[Doap], host: str, dsp_cl def create_new_doap_on_server( - target: NewDoapTarget, + target: NewGroupDoapTarget | NewEntityDoapTarget, shortcode: str, scope: PermissionScope, dsp_client: DspClient, ) -> Doap | None: proj_iri, _ = get_project_iri_and_onto_iris_by_shortcode(shortcode, dsp_client) payload = { - "forGroup": target.group.full_iri() if target.group else None, + "forGroup": target.group.full_iri() if isinstance(target, NewGroupDoapTarget) else None, "forProject": proj_iri, - "forProperty": target.property, - "forResourceClass": target.resource_class, + "forProperty": target.property if isinstance(target, NewEntityDoapTarget) else None, + "forResourceClass": target.resource_class if isinstance(target, NewEntityDoapTarget) else None, "hasPermissions": create_admin_route_object_from_scope(scope), } try: diff --git a/dsp_permissions_scripts/template.py b/dsp_permissions_scripts/template.py index 401dcd09..99bf9dbc 100644 --- a/dsp_permissions_scripts/template.py +++ b/dsp_permissions_scripts/template.py @@ -9,7 +9,8 @@ from dsp_permissions_scripts.ap.ap_set import create_new_ap_on_server from dsp_permissions_scripts.doap.doap_get import get_doaps_of_project from dsp_permissions_scripts.doap.doap_model import Doap -from dsp_permissions_scripts.doap.doap_model import NewDoapTarget +from dsp_permissions_scripts.doap.doap_model import GroupDoapTarget +from dsp_permissions_scripts.doap.doap_model import NewGroupDoapTarget from dsp_permissions_scripts.doap.doap_serialize import serialize_doaps_of_project from dsp_permissions_scripts.doap.doap_set import apply_updated_scopes_of_doaps_on_server from dsp_permissions_scripts.doap.doap_set import create_new_doap_on_server @@ -47,7 +48,7 @@ def modify_doaps(doaps: list[Doap]) -> list[Doap]: """Adapt this sample to your needs.""" modified_doaps = [] for doap in copy.deepcopy(doaps): - if doap.target.group == group.PROJECT_ADMIN: + if isinstance(doap.target, GroupDoapTarget) and doap.target.group == group.PROJECT_ADMIN: doap.scope = PUBLIC modified_doaps.append(doap) return modified_doaps @@ -112,7 +113,7 @@ def update_doaps(host: str, shortcode: str, dsp_client: DspClient) -> None: host=host, ) _ = create_new_doap_on_server( - target=NewDoapTarget(group=group.CREATOR), + target=NewGroupDoapTarget(group=group.CREATOR), shortcode=shortcode, scope=PermissionScope.create(CR=[group.SYSTEM_ADMIN]), dsp_client=dsp_client, diff --git a/tests/test_doap_serialization.py b/tests/test_doap_serialization.py index 52d17dd0..9b102aa6 100644 --- a/tests/test_doap_serialization.py +++ b/tests/test_doap_serialization.py @@ -5,7 +5,7 @@ import pytest from dsp_permissions_scripts.doap.doap_model import Doap -from dsp_permissions_scripts.doap.doap_model import DoapTarget +from dsp_permissions_scripts.doap.doap_model import GroupDoapTarget from dsp_permissions_scripts.doap.doap_serialize import deserialize_doaps_of_project from dsp_permissions_scripts.doap.doap_serialize import serialize_doaps_of_project from dsp_permissions_scripts.models import group @@ -25,7 +25,7 @@ def _setup_teardown(self) -> Iterator[None]: def test_doap_serialization(self) -> None: doap1 = Doap( - target=DoapTarget( + target=GroupDoapTarget( project_iri="http://rdfh.ch/projects/MsOaiQkcQ7-QPxsYBKckfQ", group=group.PROJECT_ADMIN, ), @@ -36,7 +36,7 @@ def test_doap_serialization(self) -> None: doap_iri="http://rdfh.ch/doap-1", ) doap2 = Doap( - target=DoapTarget( + target=GroupDoapTarget( project_iri="http://rdfh.ch/projects/MsOaiQkcQ7-QPxsYBKckfQ", group=group.PROJECT_MEMBER, ), diff --git a/tests/test_doap_set.py b/tests/test_doap_set.py index 246e4830..50926097 100644 --- a/tests/test_doap_set.py +++ b/tests/test_doap_set.py @@ -4,7 +4,7 @@ import pytest from dsp_permissions_scripts.doap import doap_set -from dsp_permissions_scripts.doap.doap_model import NewDoapTarget +from dsp_permissions_scripts.doap.doap_model import NewGroupDoapTarget from dsp_permissions_scripts.doap.doap_set import create_new_doap_on_server from dsp_permissions_scripts.models import group from dsp_permissions_scripts.models.scope import PermissionScope @@ -55,7 +55,7 @@ def test_create_new_doap_on_server( dsp_client = Mock() dsp_client.post = Mock(return_value=create_new_doap_response) _ = create_new_doap_on_server( - target=NewDoapTarget(group=group.KNOWN_USER), + target=NewGroupDoapTarget(group=group.KNOWN_USER), shortcode="0000", scope=PermissionScope.create(V={group.UNKNOWN_USER}), dsp_client=dsp_client,