Skip to content

Commit

Permalink
permissions: Allow record reviewers to also read/update request
Browse files Browse the repository at this point in the history
  • Loading branch information
rekt-hard committed Oct 1, 2024
1 parent 2d5c106 commit cde0aca
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 25 deletions.
40 changes: 32 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,31 @@ Since we only want to change the behaviour of these community submission request

.. code-block:: python
from invenio_curations.requests.curation import CurationRequest
from invenio_curations.services.generators import (
IfCurationRequestAccepted,
IfRequestTypes,
RequestTopicGenerators,
)
from invenio_rdm_records.requests import CommunitySubmission
from invenio_rdm_records.services.permissions import (
RDMRequestsPermissionPolicy,
RDMRecordPermissionPolicy,
)
from invenio_rdm_records.requests import CommunityInclusion, CommunitySubmission
from invenio_rdm_records.services.permissions import RDMRequestsPermissionPolicy
from invenio_requests.services.generators import Creator, Receiver, Status
class CurationRDMRequestsPermissionPolicy(RDMRequestsPermissionPolicy):
"""Customized permission policy for sane handling of curation requests."""
rdm_policy = RDMRecordPermissionPolicy
curation_request_record_review = IfRequestTypes(
[CurationRequest],
then_=[RequestTopicGenerators(generators=rdm_policy.can_review)],
else_=[],
)
# Only allow community-submission requests to be accepted after
# the rdm-curation request has been accepted
can_action_accept = [
Expand All @@ -167,18 +181,28 @@ Since we only want to change the behaviour of these community submission request
]
# Update can read and can comment with new states
can_read = RDMRequestsPermissionPolicy.can_read + [
Status(
["review", "critiqued", "resubmitted"],
[Creator(), Receiver()],
),
can_read = [
IfRequestTypes(
[CurationRequest],
then_=[
Creator(),
Receiver(),
RequestTopicGenerators(generators=rdm_policy.can_review),
],
else_=RDMRequestsPermissionPolicy.can_read,
)
]
can_create_comment = can_read
# Add new actions
can_action_review = RDMRequestsPermissionPolicy.can_action_accept
can_action_critique = RDMRequestsPermissionPolicy.can_action_accept
can_action_resubmit = RDMRequestsPermissionPolicy.can_action_submit
can_action_submit = RDMRequestsPermissionPolicy.can_action_submit + [
curation_request_record_review
]
can_action_resubmit = can_action_submit
REQUESTS_PERMISSION_POLICY = CurationRDMRequestsPermissionPolicy
Expand Down
4 changes: 2 additions & 2 deletions invenio_curations/services/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from invenio_curations.services import facets

from .permissions import CurationRDMRequestPermissionPolicy
from .permissions import CurationRDMRequestsPermissionPolicy


class CurationsSearchOptions(RequestSearchOptions):
Expand Down Expand Up @@ -43,7 +43,7 @@ class CurationsServiceConfig(RecordServiceConfig, ConfiguratorMixin):

# common configuration
permission_policy_cls = FromConfig(
"REQUESTS_PERMISSION_POLICY", default=CurationRDMRequestPermissionPolicy
"REQUESTS_PERMISSION_POLICY", default=CurationRDMRequestsPermissionPolicy
)
# TODO: update search options?
search = CurationsSearchOptions
32 changes: 32 additions & 0 deletions invenio_curations/services/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

"""Curations related generators."""

from itertools import chain

from flask_principal import RoleNeed
from invenio_access.permissions import system_identity
from invenio_records_permissions.generators import ConditionalGenerator, Generator
Expand Down Expand Up @@ -60,6 +62,36 @@ def _condition(self, request=None, **kwargs):
return False


class RequestTopicGenerators(Generator):
"""Request-oriented generator forwarding the request topic to the provided generators.
Knowing what a request topic is, it is possible to perform checks on the topic itself.
Helpful to allow record managers access to a request as well.
"""

def __init__(self, generators=None, **kwargs):
self._generators = generators or set()
super().__init__()

def needs(self, request=None, **kwargs):
"""Set of Needs granting permission."""
if request is None:
return set()

# popping as we will set this ourselves
kwargs.pop("record")

# we could also do: return request.topic.get_needs() but get_needs is not implemented on the RDM Record Proxy
# we could also
# - subclass the rdm record entity resolver
# - implement the get_needs() for our use case
# - register the new resolver for `record` entities in invenio.cfg
needs = [
g.needs(record=request.topic.resolve(), **kwargs) for g in self._generators
]
return set(chain.from_iterable(needs))


class CurationModerators(Generator):
"""Permission generator that allows users with the `moderation` role."""

Expand Down
70 changes: 56 additions & 14 deletions invenio_curations/services/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@

"""Curations permissions."""

from invenio_rdm_records.requests import CommunitySubmission
from invenio_rdm_records.services.generators import IfFileIsLocal
from invenio_rdm_records.services.permissions import RDMRecordPermissionPolicy
from invenio_rdm_records.services.permissions import (
RDMRecordPermissionPolicy,
RDMRequestsPermissionPolicy,
)
from invenio_records_permissions.generators import SystemProcess
from invenio_requests.services.generators import Creator, Receiver, Status
from invenio_requests.services.permissions import (
PermissionPolicy as RequestPermissionPolicy,
)

from invenio_curations.requests.curation import CurationRequest
from invenio_curations.services.generators import (
CurationModerators,
IfCurationRequestAccepted,
IfCurationRequestExists,
IfRequestTypes,
RequestTopicGenerators,
)


Expand Down Expand Up @@ -71,16 +76,53 @@ class CurationRDMRecordPermissionPolicy(RDMRecordPermissionPolicy):
)


class CurationRDMRequestPermissionPolicy(RequestPermissionPolicy):
"""Request permission policy for curations."""
class CurationRDMRequestsPermissionPolicy(RDMRequestsPermissionPolicy):
"""Customized permission policy for sane handling of curation requests."""

can_read = RequestPermissionPolicy.can_read + [
Status(
["review", "critiqued", "resubmitted"],
[Creator(), Receiver()],
),
# specifying the RDM policy as we use the `can_review` permission for viewing a request.
# if needs for viewing request.topic record can be resolved otherwise, it would be great (maybe through EntityNeeds/EntityGrants as is done for Creator/Receiver)
rdm_policy = RDMRecordPermissionPolicy
curation_request_record_review = IfRequestTypes(
[CurationRequest],
then_=[RequestTopicGenerators(generators=rdm_policy.can_review)],
else_=[],
)

# Only allow community-submission requests to be accepted after
# the rdm-curation request has been accepted
can_action_accept = [
IfRequestTypes(
request_types=[
CommunitySubmission,
],
then_=[
IfCurationRequestAccepted(
then_=RDMRequestsPermissionPolicy.can_action_accept, else_=[]
)
],
else_=RDMRequestsPermissionPolicy.can_action_accept,
)
]

# Update can read and can comment with new states
can_read = [
IfRequestTypes(
[CurationRequest],
then_=[
Creator(),
Receiver(),
RequestTopicGenerators(generators=rdm_policy.can_review),
],
else_=RDMRequestsPermissionPolicy.can_read,
)
]

can_create_comment = can_read
can_action_review = RequestPermissionPolicy.can_action_accept
can_action_critique = RequestPermissionPolicy.can_action_accept
can_action_resubmit = RequestPermissionPolicy.can_action_cancel

# Add new actions
can_action_review = RDMRequestsPermissionPolicy.can_action_accept
can_action_critique = RDMRequestsPermissionPolicy.can_action_accept
can_action_submit = RDMRequestsPermissionPolicy.can_action_submit + [
curation_request_record_review
]
can_action_resubmit = can_action_submit
3 changes: 2 additions & 1 deletion invenio_curations/services/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ def create(self, identity, data=None, uow=None, **kwargs):
),
}

if self.get_review(identity, topic):
# using system identity to ensure a request is fetched, if it exists. Even if the user would not have access.
if self.get_review(system_identity, topic):
raise OpenRecordCurationRequestAlreadyExists()

if data:
Expand Down

0 comments on commit cde0aca

Please sign in to comment.