Skip to content

Commit

Permalink
Merge branch 'main' into stojanovic/fe-251-deposit-form-publish
Browse files Browse the repository at this point in the history
  • Loading branch information
mirekys authored Oct 29, 2024
2 parents e6fd03e + c6e9b46 commit 7ed263d
Show file tree
Hide file tree
Showing 23 changed files with 399 additions and 146 deletions.
80 changes: 80 additions & 0 deletions oarepo_requests/actions/cascade_events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from invenio_access.permissions import system_identity
from invenio_requests import (
current_events_service,
current_request_type_registry,
current_requests_service,
)
from invenio_requests.records import Request
from invenio_requests.resolvers.registry import ResolverRegistry

from oarepo_requests.utils import _reference_query_term


def _str_from_ref(ref):
k, v = list(ref.items())[0]
return f"{k}.{v}"


def _get_topic_ref_with_requests(topic):
topic_ref = ResolverRegistry.reference_entity(topic)
requests_with_topic = current_requests_service.scan(
system_identity, extra_filter=_reference_query_term("topic", topic_ref)
)
return requests_with_topic, topic_ref


def _create_event(cur_request, payload, event_type, uow):
data = {"payload": payload}
current_events_service.create(
system_identity,
cur_request.id,
data,
event_type=event_type,
uow=uow,
)


def update_topic(request, old_topic, new_topic, uow):
from oarepo_requests.types.events import TopicUpdateEventType

requests_with_topic, old_topic_ref = _get_topic_ref_with_requests(old_topic)
new_topic_ref = ResolverRegistry.reference_entity(new_topic)
for request_from_search in requests_with_topic:
request_type = current_request_type_registry.lookup(
request_from_search["type"], quiet=True
)
if hasattr(request_type, "topic_change"):
cur_request = (
Request.get_record(request_from_search["id"])
if request_from_search["id"] != str(request.id)
else request
) # request on which the action is executed is recommited later, the change must be done on the same instance
request_type.topic_change(cur_request, new_topic_ref, uow)
if (
cur_request.topic.reference_dict != old_topic_ref
): # what if we don't change topic but still do some event we want to log, ie. cancelling the request because it does not apply to published record
payload = {
"old_topic": _str_from_ref(old_topic_ref),
"new_topic": _str_from_ref(new_topic_ref),
}
_create_event(cur_request, payload, TopicUpdateEventType, uow)


def cancel_requests_on_topic_delete(request, topic, uow):
from oarepo_requests.types.events import TopicDeleteEventType

requests_with_topic, topic_ref = _get_topic_ref_with_requests(topic)
for request_from_search in requests_with_topic:
request_type = current_request_type_registry.lookup(
request_from_search["type"], quiet=True
)
if hasattr(request_type, "on_topic_delete"):
if request_from_search["id"] == str(request.id):
continue
cur_request = Request.get_record(request_from_search["id"])
if cur_request.is_open:
request_type.on_topic_delete(
cur_request, uow
) # possibly return message to save on event payload?
payload = {"topic": _str_from_ref(topic_ref)}
_create_event(cur_request, payload, TopicDeleteEventType, uow)
2 changes: 2 additions & 0 deletions oarepo_requests/actions/delete_draft.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from oarepo_runtime.datastreams.utils import get_record_service_for_record

from .cascade_events import cancel_requests_on_topic_delete
from .generic import OARepoAcceptAction


Expand All @@ -9,3 +10,4 @@ def apply(self, identity, request_type, topic, uow, *args, **kwargs):
if not topic_service:
raise KeyError(f"topic {topic} service not found")
topic_service.delete_draft(identity, topic["id"], uow=uow, *args, **kwargs)
cancel_requests_on_topic_delete(self.request, topic, uow)
11 changes: 10 additions & 1 deletion oarepo_requests/actions/delete_published_record.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
from oarepo_runtime.datastreams.utils import get_record_service_for_record
from oarepo_runtime.i18n import lazy_gettext as _

from .generic import OARepoAcceptAction
from .cascade_events import cancel_requests_on_topic_delete
from .generic import OARepoAcceptAction, OARepoDeclineAction


class DeletePublishedRecordAcceptAction(OARepoAcceptAction):
name = _("Permanently delete")

def apply(self, identity, request_type, topic, uow, *args, **kwargs):
topic_service = get_record_service_for_record(topic)
if not topic_service:
raise KeyError(f"topic {topic} service not found")
topic_service.delete(identity, topic["id"], uow=uow, *args, **kwargs)
cancel_requests_on_topic_delete(self.request, topic, uow)


class DeletePublishedRecordDeclineAction(OARepoDeclineAction):
name = _("Keep the record")
3 changes: 2 additions & 1 deletion oarepo_requests/actions/edit_topic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from oarepo_runtime.datastreams.utils import get_record_service_for_record

from .generic import AddTopicLinksOnPayloadMixin, OARepoAcceptAction, update_topic
from .cascade_events import update_topic
from .generic import AddTopicLinksOnPayloadMixin, OARepoAcceptAction


class EditTopicAcceptAction(AddTopicLinksOnPayloadMixin, OARepoAcceptAction):
Expand Down
57 changes: 11 additions & 46 deletions oarepo_requests/actions/generic.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
from functools import cached_property

from invenio_access.permissions import system_identity
from invenio_requests import (
current_events_service,
current_request_type_registry,
current_requests_service,
)
from invenio_requests.customizations import actions
from invenio_requests.records.api import Request
from invenio_requests.resolvers.registry import ResolverRegistry
from oarepo_runtime.i18n import lazy_gettext as _

from oarepo_requests.proxies import current_oarepo_requests

from ..utils import _reference_query_term


class OARepoGenericActionMixin:
@classmethod
def stateful_name(cls, identity, **kwargs):
return cls.name

def apply(self, identity, request_type, topic, uow, *args, **kwargs):
pass

Expand Down Expand Up @@ -67,50 +62,20 @@ def apply(self, identity, request_type, topic, uow, *args, **kwargs):


class OARepoSubmitAction(OARepoGenericActionMixin, actions.SubmitAction):
name = _("Submit")
""""""


class OARepoDeclineAction(OARepoGenericActionMixin, actions.DeclineAction):
name = _("Decline")
""""""


class OARepoAcceptAction(OARepoGenericActionMixin, actions.AcceptAction):
name = _("Accept")
""""""


def _str_from_ref(ref):
k, v = list(ref.items())[0]
return f"{k}.{v}"


def update_topic(request, old_topic, new_topic, uow):
from oarepo_requests.types.events import TopicUpdateEventType

old_topic_ref = ResolverRegistry.reference_entity(old_topic)
new_topic_ref = ResolverRegistry.reference_entity(new_topic)

requests_with_topic = current_requests_service.scan(
system_identity, extra_filter=_reference_query_term("topic", old_topic_ref)
)
for request_from_search in requests_with_topic:
request_type = current_request_type_registry.lookup(
request_from_search["type"], quiet=True
)
if hasattr(request_type, "topic_change"):
cur_request = (
Request.get_record(request_from_search["id"])
if request_from_search["id"] != str(request.id)
else request
) # request on which the action is executed is recommited later, the change must be done on the same instance
request_type.topic_change(cur_request, new_topic_ref, uow)
if cur_request.topic.reference_dict != old_topic_ref:
event = TopicUpdateEventType(
payload=dict(
old_topic=_str_from_ref(old_topic_ref),
new_topic=_str_from_ref(new_topic_ref),
) # event jsonschema requires string
)
_data = dict(payload=event.payload)
current_events_service.create(
system_identity, cur_request.id, _data, event, uow=uow
)
class OARepoCancelAction(actions.CancelAction):
status_from = ["created", "submitted"]
status_to = "cancelled"
3 changes: 2 additions & 1 deletion oarepo_requests/actions/new_version.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from oarepo_runtime.datastreams.utils import get_record_service_for_record

from .generic import AddTopicLinksOnPayloadMixin, OARepoAcceptAction, update_topic
from .cascade_events import update_topic
from .generic import AddTopicLinksOnPayloadMixin, OARepoAcceptAction


class NewVersionAcceptAction(AddTopicLinksOnPayloadMixin, OARepoAcceptAction):
Expand Down
10 changes: 9 additions & 1 deletion oarepo_requests/actions/publish_draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
from invenio_records_resources.services.uow import RecordCommitOp
from marshmallow import ValidationError
from oarepo_runtime.datastreams.utils import get_record_service_for_record
from oarepo_runtime.i18n import lazy_gettext as _

from .cascade_events import update_topic
from .generic import (
AddTopicLinksOnPayloadMixin,
OARepoAcceptAction,
OARepoDeclineAction,
OARepoSubmitAction,
update_topic,
)


Expand All @@ -31,6 +33,8 @@ class PublishDraftAcceptAction(AddTopicLinksOnPayloadMixin, OARepoAcceptAction):
self_link = "published_record:links:self"
self_html_link = "published_record:links:self_html"

name = _("Publish")

def apply(self, identity, request_type, topic, uow, *args, **kwargs):
topic_service = get_record_service_for_record(topic)
if not topic_service:
Expand All @@ -48,3 +52,7 @@ def apply(self, identity, request_type, topic, uow, *args, **kwargs):
return super().apply(
identity, request_type, published_topic, uow, *args, **kwargs
)


class PublishDraftDeclineAction(OARepoDeclineAction):
name = _("Return for correction")
2 changes: 2 additions & 0 deletions oarepo_requests/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
AutoAcceptComponent,
RequestIdentityComponent,
)
from oarepo_requests.types.events import TopicDeleteEventType
from oarepo_requests.types.events.topic_update import TopicUpdateEventType

try:
Expand Down Expand Up @@ -40,6 +41,7 @@

REQUESTS_REGISTERED_EVENT_TYPES = [
TopicUpdateEventType(),
TopicDeleteEventType(),
] + invenio_requests.config.REQUESTS_REGISTERED_EVENT_TYPES

REQUESTS_ALLOWED_RECEIVERS = ["user", "group", "auto_approve"]
Expand Down
2 changes: 2 additions & 0 deletions oarepo_requests/types/delete_published_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from oarepo_requests.actions.delete_published_record import (
DeletePublishedRecordAcceptAction,
DeletePublishedRecordDeclineAction,
)

from ..utils import is_auto_approved, request_identity_matches
Expand All @@ -22,6 +23,7 @@ def available_actions(cls):
return {
**super().available_actions,
"accept": DeletePublishedRecordAcceptAction,
"decline": DeletePublishedRecordDeclineAction,
}

description = _("Request deletion of published record")
Expand Down
5 changes: 2 additions & 3 deletions oarepo_requests/types/events/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from .topic_delete import TopicDeleteEventType
from .topic_update import TopicUpdateEventType

__all__ = [
"TopicUpdateEventType",
]
__all__ = ["TopicUpdateEventType", "TopicDeleteEventType"]
16 changes: 16 additions & 0 deletions oarepo_requests/types/events/topic_delete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from invenio_requests.customizations.event_types import EventType
from marshmallow import fields

from oarepo_requests.types.events.validation import _serialized_topic_validator


class TopicDeleteEventType(EventType):
"""Comment event type."""

type_id = "D"

payload_schema = dict(
topic=fields.Str(validate=[_serialized_topic_validator]),
)

payload_required = True
8 changes: 1 addition & 7 deletions oarepo_requests/types/events/topic_update.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
from invenio_requests.customizations.event_types import EventType
from marshmallow import fields


def _serialized_topic_validator(value):
if len(value.split(".")) != 2:
raise ValueError(
"Serialized topic must be a string with model and id separated by a single dot."
)
return value
from oarepo_requests.types.events.validation import _serialized_topic_validator


class TopicUpdateEventType(EventType):
Expand Down
6 changes: 6 additions & 0 deletions oarepo_requests/types/events/validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def _serialized_topic_validator(value):
if len(value.split(".")) != 2:
raise ValueError(
"Serialized topic must be a string with model and id separated by a single dot."
)
return value
6 changes: 6 additions & 0 deletions oarepo_requests/types/generic.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from invenio_access.permissions import system_identity
from invenio_records_resources.services.errors import PermissionDeniedError
from invenio_requests.customizations import RequestType
from invenio_requests.customizations.states import RequestState
Expand All @@ -8,6 +9,7 @@

from ..actions.generic import (
OARepoAcceptAction,
OARepoCancelAction,
OARepoDeclineAction,
OARepoSubmitAction,
)
Expand All @@ -19,6 +21,9 @@ class OARepoRequestType(RequestType):

dangerous = False

def on_topic_delete(self, request, topic):
current_requests_service.execute_action(system_identity, request.id, "cancel")

@classmethod
@property
def available_statuses(cls):
Expand Down Expand Up @@ -67,6 +72,7 @@ def available_actions(cls):
"submit": OARepoSubmitAction,
"accept": OARepoAcceptAction,
"decline": OARepoDeclineAction,
"cancel": OARepoCancelAction,
}

def stateful_name(self, *, identity, topic, request=None, **kwargs):
Expand Down
2 changes: 2 additions & 0 deletions oarepo_requests/types/publish_draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from oarepo_requests.actions.publish_draft import (
PublishDraftAcceptAction,
PublishDraftDeclineAction,
PublishDraftSubmitAction,
)

Expand Down Expand Up @@ -51,6 +52,7 @@ def available_actions(cls):
**super().available_actions,
"submit": PublishDraftSubmitAction,
"accept": PublishDraftAcceptAction,
"decline": PublishDraftDeclineAction,
}

description = _("Request publishing of a draft")
Expand Down
2 changes: 2 additions & 0 deletions oarepo_requests/ui/components/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from oarepo_requests.ui.components.action_labels import ActionLabelsComponent
from oarepo_requests.ui.components.custom_fields import (
FormConfigCustomFieldsComponent,
FormConfigRequestTypePropertiesComponent,
Expand All @@ -6,4 +7,5 @@
__all__ = (
"FormConfigCustomFieldsComponent",
"FormConfigRequestTypePropertiesComponent",
"ActionLabelsComponent",
)
Loading

0 comments on commit 7ed263d

Please sign in to comment.