From 375805f137537d3e60229f87849838e617fd58a8 Mon Sep 17 00:00:00 2001 From: Ronald Krist Date: Fri, 11 Oct 2024 09:55:44 +0200 Subject: [PATCH 1/4] community role identity to entity references --- .../identity_to_entity_references.py | 4 ++ setup.cfg | 3 + tests/test_communities/conftest.py | 63 ++++++++++++++++++- .../test_param_interpreters.py | 42 +++++++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 oarepo_communities/identity_to_entity_references.py create mode 100644 tests/test_communities/test_param_interpreters.py diff --git a/oarepo_communities/identity_to_entity_references.py b/oarepo_communities/identity_to_entity_references.py new file mode 100644 index 0000000..1e8acaa --- /dev/null +++ b/oarepo_communities/identity_to_entity_references.py @@ -0,0 +1,4 @@ + +def community_role_mappings(identity): + community_roles = [(n.value, n.role) for n in identity.provides if n.method == "community"] + return [{"community_role":f"{community_role[0]}:{community_role[1]}"} for community_role in community_roles] diff --git a/setup.cfg b/setup.cfg index 130ed27..ad53c1d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -54,3 +54,6 @@ invenio_assets.webpack = invenio_i18n.translations = oarepo_communities_messages = oarepo_communities.i18n +oarepo_requests.identity_to_entity_references = + community_role = oarepo_communities.identity_to_entity_references:community_role_mappings + diff --git a/tests/test_communities/conftest.py b/tests/test_communities/conftest.py index f6a88d8..2a4008d 100644 --- a/tests/test_communities/conftest.py +++ b/tests/test_communities/conftest.py @@ -32,6 +32,8 @@ WorkflowRequestPolicy, WorkflowTransitions, ) + +from tests.test_communities.utils import link_api2testclient from thesis.records.api import ThesisDraft from oarepo_communities.proxies import current_oarepo_communities @@ -228,6 +230,8 @@ class DefaultRequests(WorkflowRequestPolicy): ) + + class PublishRequestsRecordOwnerInRecordCommunity(DefaultRequests): publish_draft = WorkflowRequest( requesters=[IfInState("draft", [RecordOwnerInRecordCommunity()])], @@ -284,6 +288,15 @@ class NoRequests(WorkflowRequestPolicy): transitions=WorkflowTransitions(), ) +class CuratorPublishRequests(DefaultRequests): + publish_draft = WorkflowRequest( + requesters=[IfInState("draft", [CommunityRole("owner")])], + recipients=[DefaultCommunityRole("curator")], + transitions=WorkflowTransitions( + submitted="publishing", accepted="published", declined="draft" + ), + ) + WORKFLOWS = { "default": Workflow( @@ -311,6 +324,11 @@ class NoRequests(WorkflowRequestPolicy): permission_policy_cls=TestCommunityWorkflowPermissions, request_policy_cls=NoRequests, ), + "curator_publish": Workflow( + label=_("For testing assigned param filter."), + permission_policy_cls=TestCommunityWorkflowPermissions, + request_policy_cls=CuratorPublishRequests, + ) } @@ -637,16 +655,55 @@ def default_workflow_json(): @pytest.fixture() -def create_draft_via_resource(default_workflow_json, urls): +def create_draft_via_resource(default_workflow_json): def _create_draft( - client, expand=True, custom_workflow=None, additional_data=None, **kwargs + client, community, expand=True, custom_workflow=None, additional_data=None, **kwargs ): json = copy.deepcopy(default_workflow_json) if custom_workflow: json["parent"]["workflow"] = custom_workflow if additional_data: json |= additional_data - url = urls["BASE_URL"] + "?expand=true" if expand else urls["BASE_URL"] + #url = "/thesis/" + "?expand=true" if expand else "/thesis/" + url=f"/communities/{community.id}/thesis" return client.post(url, json=json, **kwargs) return _create_draft + +@pytest.fixture() +def get_request_type(): + """ + gets request create link from serialized request types + """ + + def _get_request_type(request_types_json, request_type): + selected_entry = [ + entry for entry in request_types_json if entry["type_id"] == request_type + ][0] + return selected_entry + + return _get_request_type + + +@pytest.fixture() +def get_request_link(get_request_type): + """ + gets request create link from serialized request types + """ + + def _create_request_from_link(request_types_json, request_type): + selected_entry = get_request_type(request_types_json, request_type) + return selected_entry["links"]["actions"]["create"] + + return _create_request_from_link + +@pytest.fixture +def submit_request(get_request_link): + def _submit_request(client, record, request_type): + applicable_requests = client.get(link_api2testclient(record.json["links"]["applicable-requests"])).json["hits"]["hits"] + approve_link = link_api2testclient(get_request_link(applicable_requests, request_type)) + create_approve_response = client.post(approve_link) + submit_approve_response = client.post( + link_api2testclient(create_approve_response.json["links"]["actions"]["submit"])) + return submit_approve_response + return _submit_request diff --git a/tests/test_communities/test_param_interpreters.py b/tests/test_communities/test_param_interpreters.py new file mode 100644 index 0000000..48fc146 --- /dev/null +++ b/tests/test_communities/test_param_interpreters.py @@ -0,0 +1,42 @@ + + +def test_community_role_param_interpreter( + logged_client, + community_owner, + community_reader, + community_curator, + community_with_workflow_factory, + record_service, + create_draft_via_resource, + submit_request, + inviter, + search_clear, +): + owner_client = logged_client(community_owner) + curator_client = logged_client(community_curator) + reader_client = logged_client(community_reader) + + community_1 = community_with_workflow_factory("comm1", community_owner) + community_2 = community_with_workflow_factory("comm2", community_owner) + community_3 = community_with_workflow_factory("comm3", community_curator) + inviter("2", community_1.id, "reader") + inviter("2", community_2.id, "reader") + inviter("2", community_3.id, "reader") + + + record1 = create_draft_via_resource(owner_client, community=community_1) + record2 = create_draft_via_resource(owner_client, community=community_2) + record3 = create_draft_via_resource(curator_client, community=community_3, custom_workflow="curator_publish") + + + response_1 = submit_request(reader_client, record1, "publish_draft") + response_2 = submit_request(reader_client, record2, "publish_draft") + response_3 = submit_request(owner_client, record3, "publish_draft") + + + search_unfiltered = owner_client.get("/requests/") + assert len(search_unfiltered.json["hits"]["hits"]) == 3 + + search_filtered = owner_client.get("/requests/?assigned=true") + + assert len(search_filtered.json["hits"]["hits"]) == 2 \ No newline at end of file From 9b7ebef75f2cf669f97de3aaa194cedcd1a10ca4 Mon Sep 17 00:00:00 2001 From: Ronald Krist Date: Fri, 11 Oct 2024 09:56:03 +0200 Subject: [PATCH 2/4] format --- oarepo_communities/identity_to_entity_references.py | 10 +++++++--- tests/test_communities/test_param_interpreters.py | 11 ++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/oarepo_communities/identity_to_entity_references.py b/oarepo_communities/identity_to_entity_references.py index 1e8acaa..eca5e6d 100644 --- a/oarepo_communities/identity_to_entity_references.py +++ b/oarepo_communities/identity_to_entity_references.py @@ -1,4 +1,8 @@ - def community_role_mappings(identity): - community_roles = [(n.value, n.role) for n in identity.provides if n.method == "community"] - return [{"community_role":f"{community_role[0]}:{community_role[1]}"} for community_role in community_roles] + community_roles = [ + (n.value, n.role) for n in identity.provides if n.method == "community" + ] + return [ + {"community_role": f"{community_role[0]}:{community_role[1]}"} + for community_role in community_roles + ] diff --git a/tests/test_communities/test_param_interpreters.py b/tests/test_communities/test_param_interpreters.py index 48fc146..96fd469 100644 --- a/tests/test_communities/test_param_interpreters.py +++ b/tests/test_communities/test_param_interpreters.py @@ -1,5 +1,3 @@ - - def test_community_role_param_interpreter( logged_client, community_owner, @@ -23,20 +21,19 @@ def test_community_role_param_interpreter( inviter("2", community_2.id, "reader") inviter("2", community_3.id, "reader") - record1 = create_draft_via_resource(owner_client, community=community_1) record2 = create_draft_via_resource(owner_client, community=community_2) - record3 = create_draft_via_resource(curator_client, community=community_3, custom_workflow="curator_publish") - + record3 = create_draft_via_resource( + curator_client, community=community_3, custom_workflow="curator_publish" + ) response_1 = submit_request(reader_client, record1, "publish_draft") response_2 = submit_request(reader_client, record2, "publish_draft") response_3 = submit_request(owner_client, record3, "publish_draft") - search_unfiltered = owner_client.get("/requests/") assert len(search_unfiltered.json["hits"]["hits"]) == 3 search_filtered = owner_client.get("/requests/?assigned=true") - assert len(search_filtered.json["hits"]["hits"]) == 2 \ No newline at end of file + assert len(search_filtered.json["hits"]["hits"]) == 2 From d5f2778bc046377d93cf85682620f26e01b6c267 Mon Sep 17 00:00:00 2001 From: Ronald Krist Date: Fri, 11 Oct 2024 09:56:20 +0200 Subject: [PATCH 3/4] version bump --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index ad53c1d..206a3f5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = oarepo-communities -version = 5.0.16 +version = 5.0.17 description = authors = Ronald Krist readme = README.md From f4a6e4b9621363de23645d2ba1c9ad7db10aa4c0 Mon Sep 17 00:00:00 2001 From: Ronald Krist Date: Thu, 17 Oct 2024 09:20:22 +0200 Subject: [PATCH 4/4] tests fix --- tests/test_communities/conftest.py | 66 +++++++++++-------- .../test_community_requests.py | 6 -- .../test_param_interpreters.py | 16 +++-- tests/test_communities/test_permissions.py | 1 - 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/tests/test_communities/conftest.py b/tests/test_communities/conftest.py index 2a4008d..e399ef8 100644 --- a/tests/test_communities/conftest.py +++ b/tests/test_communities/conftest.py @@ -32,8 +32,6 @@ WorkflowRequestPolicy, WorkflowTransitions, ) - -from tests.test_communities.utils import link_api2testclient from thesis.records.api import ThesisDraft from oarepo_communities.proxies import current_oarepo_communities @@ -49,20 +47,8 @@ from oarepo_communities.services.permissions.policy import ( CommunityDefaultWorkflowPermissions, ) - - -@pytest.fixture() -def scenario_permissions(): - - return CreatorsFromWorkflowRequestsPermissionPolicy - - -@pytest.fixture -def patch_requests_permissions( - requests_service_config, - scenario_permissions, -): - setattr(requests_service_config, "permission_policy_cls", scenario_permissions) +from tests.test_communities.utils import link_api2testclient +from oarepo_requests.services.permissions.workflow_policies import CreatorsFromWorkflowRequestsPermissionPolicy @pytest.fixture(scope="function") @@ -230,8 +216,6 @@ class DefaultRequests(WorkflowRequestPolicy): ) - - class PublishRequestsRecordOwnerInRecordCommunity(DefaultRequests): publish_draft = WorkflowRequest( requesters=[IfInState("draft", [RecordOwnerInRecordCommunity()])], @@ -288,6 +272,7 @@ class NoRequests(WorkflowRequestPolicy): transitions=WorkflowTransitions(), ) + class CuratorPublishRequests(DefaultRequests): publish_draft = WorkflowRequest( requesters=[IfInState("draft", [CommunityRole("owner")])], @@ -328,7 +313,7 @@ class CuratorPublishRequests(DefaultRequests): label=_("For testing assigned param filter."), permission_policy_cls=TestCommunityWorkflowPermissions, request_policy_cls=CuratorPublishRequests, - ) + ), } @@ -420,6 +405,7 @@ def app_config(app_config): app_config["COMMUNITIES_CUSTOM_FIELDS"] = [WorkflowCF(name="workflow")] app_config["COMMUNITIES_CUSTOM_FIELDS_UI"] = [] + app_config["REQUESTS_PERMISSION_POLICY"] = CreatorsFromWorkflowRequestsPermissionPolicy return app_config @@ -657,19 +643,25 @@ def default_workflow_json(): @pytest.fixture() def create_draft_via_resource(default_workflow_json): def _create_draft( - client, community, expand=True, custom_workflow=None, additional_data=None, **kwargs + client, + community, + expand=True, + custom_workflow=None, + additional_data=None, + **kwargs, ): json = copy.deepcopy(default_workflow_json) if custom_workflow: json["parent"]["workflow"] = custom_workflow if additional_data: json |= additional_data - #url = "/thesis/" + "?expand=true" if expand else "/thesis/" - url=f"/communities/{community.id}/thesis" + # url = "/thesis/" + "?expand=true" if expand else "/thesis/" + url = f"/communities/{community.id}/thesis" return client.post(url, json=json, **kwargs) return _create_draft + @pytest.fixture() def get_request_type(): """ @@ -697,13 +689,29 @@ def _create_request_from_link(request_types_json, request_type): return _create_request_from_link + @pytest.fixture -def submit_request(get_request_link): +def create_request_by_link(get_request_link): + def _create_request(client, record, request_type): + applicable_requests = client.get( + link_api2testclient(record.json["links"]["applicable-requests"]) + ).json["hits"]["hits"] + create_link = link_api2testclient( + get_request_link(applicable_requests, request_type) + ) + create_response = client.post(create_link) + return create_response + + return _create_request + + +@pytest.fixture +def submit_request_by_link(create_request_by_link): def _submit_request(client, record, request_type): - applicable_requests = client.get(link_api2testclient(record.json["links"]["applicable-requests"])).json["hits"]["hits"] - approve_link = link_api2testclient(get_request_link(applicable_requests, request_type)) - create_approve_response = client.post(approve_link) - submit_approve_response = client.post( - link_api2testclient(create_approve_response.json["links"]["actions"]["submit"])) - return submit_approve_response + create_response = create_request_by_link(client, record, request_type) + submit_response = client.post( + link_api2testclient(create_response.json["links"]["actions"]["submit"]) + ) + return submit_response + return _submit_request diff --git a/tests/test_communities/test_community_requests.py b/tests/test_communities/test_community_requests.py index 6470838..cffaace 100644 --- a/tests/test_communities/test_community_requests.py +++ b/tests/test_communities/test_community_requests.py @@ -122,7 +122,6 @@ def test_community_publish( community, request_data_factory, record_service, - patch_requests_permissions, search_clear, ): reader_client = logged_client(community_reader) @@ -163,7 +162,6 @@ def test_community_delete( community, request_data_factory, record_service, - patch_requests_permissions, search_clear, ): reader_client = logged_client(community_reader) @@ -210,7 +208,6 @@ def test_community_migration( request_data_factory, record_service, inviter, - patch_requests_permissions, search_clear, ): reader_client, owner_client, community_1, community_2 = _init_env( @@ -269,7 +266,6 @@ def test_community_submission_secondary( inviter, request_data_factory, record_service, - patch_requests_permissions, search_clear, ): reader_client, owner_client, community_1, community_2 = _init_env( @@ -332,7 +328,6 @@ def test_remove_secondary( inviter, request_data_factory, record_service, - patch_requests_permissions, search_clear, ): reader_client, owner_client, community_1, community_2 = _init_env( @@ -420,7 +415,6 @@ def test_community_role_ui_serialization( request_data_factory, record_service, ui_serialized_community_role, - patch_requests_permissions, search_clear, ): reader_client = logged_client(community_reader) diff --git a/tests/test_communities/test_param_interpreters.py b/tests/test_communities/test_param_interpreters.py index 96fd469..7776004 100644 --- a/tests/test_communities/test_param_interpreters.py +++ b/tests/test_communities/test_param_interpreters.py @@ -1,3 +1,5 @@ + + def test_community_role_param_interpreter( logged_client, community_owner, @@ -6,13 +8,12 @@ def test_community_role_param_interpreter( community_with_workflow_factory, record_service, create_draft_via_resource, - submit_request, + create_request_by_link, + submit_request_by_link, inviter, search_clear, ): owner_client = logged_client(community_owner) - curator_client = logged_client(community_curator) - reader_client = logged_client(community_reader) community_1 = community_with_workflow_factory("comm1", community_owner) community_2 = community_with_workflow_factory("comm2", community_owner) @@ -24,16 +25,17 @@ def test_community_role_param_interpreter( record1 = create_draft_via_resource(owner_client, community=community_1) record2 = create_draft_via_resource(owner_client, community=community_2) record3 = create_draft_via_resource( - curator_client, community=community_3, custom_workflow="curator_publish" + owner_client, community=community_2, custom_workflow="curator_publish" # owner is creator but not receiver of the third request ) - response_1 = submit_request(reader_client, record1, "publish_draft") - response_2 = submit_request(reader_client, record2, "publish_draft") - response_3 = submit_request(owner_client, record3, "publish_draft") + response_1 = submit_request_by_link(owner_client, record1, "publish_draft") + response_2 = create_request_by_link(owner_client, record2, "publish_draft") + response_3 = submit_request_by_link(owner_client, record3, "publish_draft") search_unfiltered = owner_client.get("/requests/") assert len(search_unfiltered.json["hits"]["hits"]) == 3 search_filtered = owner_client.get("/requests/?assigned=true") + assert len(search_filtered.json["hits"]["hits"]) == 2 diff --git a/tests/test_communities/test_permissions.py b/tests/test_communities/test_permissions.py index 6b850e9..f20d76f 100644 --- a/tests/test_communities/test_permissions.py +++ b/tests/test_communities/test_permissions.py @@ -61,7 +61,6 @@ def test_scenario_change( inviter, set_community_workflow, service_config, - patch_requests_permissions, search_clear, ): owner_client = logged_client(community_owner)