Skip to content

Commit

Permalink
delete published record notifications and refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
Ronald Krist committed Jan 27, 2025
1 parent 7afbe34 commit 279623c
Show file tree
Hide file tree
Showing 17 changed files with 314 additions and 115 deletions.
61 changes: 59 additions & 2 deletions oarepo_requests/actions/delete_published_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,43 @@
# modify it under the terms of the MIT License; see LICENSE file for more
# details.
#
"""Actions for delete published record request."""
"""Actions for delete published record requests."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, override

from invenio_notifications.services.uow import NotificationOp
from invenio_records_resources.services.uow import UnitOfWork
from oarepo_runtime.datastreams.utils import get_record_service_for_record
from oarepo_runtime.i18n import lazy_gettext as _

from ..notifications.builders.delete_published_record import (
DeletePublishedRecordRequestAcceptNotificationBuilder,
DeletePublishedRecordRequestSubmitNotificationBuilder,
)
from .cascade_events import cancel_requests_on_topic_delete
from .generic import OARepoAcceptAction, OARepoDeclineAction
from .generic import OARepoAcceptAction, OARepoDeclineAction, OARepoSubmitAction

if TYPE_CHECKING:
from flask_principal import Identity
from invenio_drafts_resources.records import Record
from invenio_requests.customizations import RequestType

from typing import TYPE_CHECKING, Any

from invenio_notifications.services.uow import NotificationOp
from invenio_records_resources.services.uow import UnitOfWork
from oarepo_runtime.datastreams.utils import get_record_service_for_record
from oarepo_runtime.i18n import lazy_gettext as _

from .generic import OARepoAcceptAction, OARepoDeclineAction, OARepoSubmitAction

if TYPE_CHECKING:
from flask_principal import Identity
from invenio_drafts_resources.records import Record
from invenio_requests.customizations import RequestType


if TYPE_CHECKING:
from flask_principal import Identity
Expand All @@ -24,6 +50,30 @@
from invenio_requests.customizations import RequestType


class DeletePublishedRecordSubmitAction(OARepoSubmitAction):
"""Submit action for publishing draft requests."""

def apply(
self,
identity: Identity,
request_type: RequestType,
topic: Record,
uow: UnitOfWork,
*args: Any,
**kwargs: Any,
) -> Record:
"""Publish the draft."""

uow.register(
NotificationOp(
DeletePublishedRecordRequestSubmitNotificationBuilder.build(
request=self.request
)
)
)
return super().apply(identity, request_type, topic, uow, *args, **kwargs)


class DeletePublishedRecordAcceptAction(OARepoAcceptAction):
"""Accept request for deletion of a published record and delete the record."""

Expand All @@ -43,6 +93,13 @@ def apply(
if not topic_service:
raise KeyError(f"topic {topic} service not found")
topic_service.delete(identity, topic["id"], *args, uow=uow, **kwargs)
uow.register(
NotificationOp(
DeletePublishedRecordRequestAcceptNotificationBuilder.build(
request=self.request
)
)
)
cancel_requests_on_topic_delete(self.request, topic, uow)


Expand Down
22 changes: 9 additions & 13 deletions oarepo_requests/actions/publish_draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,22 @@
from typing import TYPE_CHECKING, Any

from invenio_access.permissions import system_identity
from invenio_notifications.services.uow import NotificationOp
from invenio_records_resources.services.uow import RecordCommitOp, UnitOfWork
from oarepo_runtime.datastreams.utils import get_record_service_for_record
from oarepo_runtime.i18n import lazy_gettext as _

from ..notifications.builders.publish import (
PublishDraftRequestAcceptNotificationBuilder,
PublishDraftRequestSubmitNotificationBuilder,
)
from .cascade_events import update_topic
from .generic import (
AddTopicLinksOnPayloadMixin,
OARepoAcceptAction,
OARepoDeclineAction,
OARepoSubmitAction,
)
from invenio_notifications.services.uow import NotificationOp

from ..notifications.builders.publish import PublishDraftRequestAcceptNotificationBuilder, \
PublishDraftRequestSubmitNotificationBuilder

if TYPE_CHECKING:
from flask_principal import Identity
Expand Down Expand Up @@ -55,6 +56,7 @@ def can_execute(self: RequestAction) -> bool:

class PublishDraftSubmitAction(PublishMixin, OARepoSubmitAction):
"""Submit action for publishing draft requests."""

def apply(
self,
identity: Identity,
Expand All @@ -68,14 +70,10 @@ def apply(

uow.register(
NotificationOp(
PublishDraftRequestSubmitNotificationBuilder.build(
request=self.request
)
PublishDraftRequestSubmitNotificationBuilder.build(request=self.request)
)
)
return super().apply(
identity, request_type, topic, uow, *args, **kwargs
)
return super().apply(identity, request_type, topic, uow, *args, **kwargs)


class PublishDraftAcceptAction(
Expand Down Expand Up @@ -113,9 +111,7 @@ def apply(
update_topic(self.request, topic, published_topic._record, uow)
uow.register(
NotificationOp(
PublishDraftRequestAcceptNotificationBuilder.build(
request=self.request
)
PublishDraftRequestAcceptNotificationBuilder.build(request=self.request)
)
)
return super().apply(
Expand Down
9 changes: 3 additions & 6 deletions oarepo_requests/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
RequestIdentityComponent,
WorkflowTransitionComponent,
)
from oarepo_requests.notifications.generators import UserEmailRecipient
from oarepo_requests.resolvers.ui import (
AutoApproveUIEntityResolver,
FallbackEntityReferenceUIResolver,
Expand All @@ -35,7 +36,7 @@
)
from oarepo_requests.types.events import TopicDeleteEventType
from oarepo_requests.types.events.topic_update import TopicUpdateEventType
from oarepo_requests.notifications.generators import UserEmailRecipient

REQUESTS_REGISTERED_TYPES = [
DeletePublishedRecordRequestType(),
EditPublishedRecordRequestType(),
Expand Down Expand Up @@ -97,8 +98,4 @@
],
}

NOTIFICATION_RECIPIENTS_RESOLVERS = {
"user": {
"email": UserEmailRecipient
}
}
NOTIFICATION_RECIPIENTS_RESOLVERS = {"user": {"email": UserEmailRecipient}}
17 changes: 6 additions & 11 deletions oarepo_requests/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@
from invenio_base.utils import obj_or_import_string
from invenio_requests.proxies import current_events_service

from oarepo_requests.resolvers.user import OARepoUserResolver
from oarepo_requests.resources.events.config import OARepoRequestsCommentsResourceConfig
from oarepo_requests.resources.events.resource import OARepoRequestsCommentsResource
from oarepo_requests.resources.oarepo.config import OARepoRequestsResourceConfig
from oarepo_requests.resources.oarepo.resource import OARepoRequestsResource
from oarepo_requests.services.oarepo.config import OARepoRequestsServiceConfig
from oarepo_requests.services.oarepo.service import OARepoRequestsService
from invenio_requests.registry import TypeRegistry

if TYPE_CHECKING:
from flask import Flask
Expand Down Expand Up @@ -212,15 +210,16 @@ def init_config(self, app: Flask) -> None:
app_registered_event_types = app.config.setdefault(
"REQUESTS_REGISTERED_EVENT_TYPES", []
)

for event_type in config.REQUESTS_REGISTERED_EVENT_TYPES:
if event_type not in app_registered_event_types:
app_registered_event_types.append(event_type)

app_registered_event_types = app.config.setdefault(
"NOTIFICATION_RECIPIENTS_RESOLVERS", {}
)
app.config["NOTIFICATION_RECIPIENTS_RESOLVERS"] |= config.NOTIFICATION_RECIPIENTS_RESOLVERS
app.config[
"NOTIFICATION_RECIPIENTS_RESOLVERS"
] |= config.NOTIFICATION_RECIPIENTS_RESOLVERS


def api_finalize_app(app: Flask) -> None:
Expand Down Expand Up @@ -249,10 +248,6 @@ def finalize_app(app: Flask) -> None:
for type in app.config["REQUESTS_REGISTERED_EVENT_TYPES"]:
current_event_type_registry.register_type(type)

from invenio_requests.proxies import current_requests

registry = current_requests.entity_resolvers_registry
registered_resolvers = registry._registered_types
registered_resolvers["user"] = OARepoUserResolver()

ext.notification_recipients_resolvers_registry = app.config["NOTIFICATION_RECIPIENTS_RESOLVERS"]
ext.notification_recipients_resolvers_registry = app.config[
"NOTIFICATION_RECIPIENTS_RESOLVERS"
]
18 changes: 18 additions & 0 deletions oarepo_requests/notifications/builders/delete_published_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from ..generators import EntityRecipient
from .oarepo import OARepoRequestActionNotificationBuilder


class DeletePublishedRecordRequestSubmitNotificationBuilder(
OARepoRequestActionNotificationBuilder
):
type = "delete-published-record-request-event.submit"

recipients = [EntityRecipient(key="request.receiver")] # email only


class DeletePublishedRecordRequestAcceptNotificationBuilder(
OARepoRequestActionNotificationBuilder
):
type = "delete-published-record-request-event.accept"

recipients = [EntityRecipient(key="request.created_by")]
24 changes: 13 additions & 11 deletions oarepo_requests/notifications/builders/oarepo.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from invenio_notifications.backends import EmailNotificationBackend
from invenio_notifications.services.builders import NotificationBuilder
from invenio_notifications.models import Notification
from invenio_notifications.registry import EntityResolverRegistry
from invenio_notifications.services.builders import NotificationBuilder
from invenio_notifications.services.generators import EntityResolve, UserEmailBackend

from invenio_users_resources.notifications.generators import (
EmailRecipient,
)
if TYPE_CHECKING:
from invenio_requests.records.api import Request


class OARepoUserEmailBackend(UserEmailBackend):
backend_id = EmailNotificationBackend.id


class OARepoRequestActionNotificationBuilder(NotificationBuilder):

@classmethod
def build(cls, request):
def build(cls, request: Request):
"""Build notification with context."""
return Notification(
type=cls.type,
context={
"request": EntityResolverRegistry.reference_entity(request),
"backend_ids": [backend.backend_id for backend in cls.recipient_backends]
"backend_ids": [
backend.backend_id for backend in cls.recipient_backends
],
},
)

Expand All @@ -29,8 +36,3 @@ def build(cls, request):
]

recipient_backends = [OARepoUserEmailBackend()]





20 changes: 10 additions & 10 deletions oarepo_requests/notifications/builders/publish.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
from .oarepo import OARepoRequestActionNotificationBuilder

from ..generators import EntityRecipient
from .oarepo import OARepoRequestActionNotificationBuilder


class PublishDraftRequestSubmitNotificationBuilder(OARepoRequestActionNotificationBuilder):
class PublishDraftRequestSubmitNotificationBuilder(
OARepoRequestActionNotificationBuilder
):
type = "publish-draft-request-event.submit"

recipients = [
EntityRecipient(key="request.receiver") # email only
]
recipients = [EntityRecipient(key="request.receiver")] # email only


class PublishDraftRequestAcceptNotificationBuilder(OARepoRequestActionNotificationBuilder):
class PublishDraftRequestAcceptNotificationBuilder(
OARepoRequestActionNotificationBuilder
):
type = "publish-draft-request-event.accept"

recipients = [
EntityRecipient(key="request.created_by")
]
recipients = [EntityRecipient(key="request.created_by")]
34 changes: 24 additions & 10 deletions oarepo_requests/notifications/generators.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from invenio_notifications.models import Recipient
from invenio_notifications.services.generators import RecipientGenerator
from invenio_records.dictutils import dict_lookup
from oarepo_requests.proxies import current_notification_recipients_resolvers_registry
from invenio_requests.proxies import current_requests

from oarepo_requests.proxies import current_notification_recipients_resolvers_registry

if TYPE_CHECKING:
from invenio_notifications.models import Notification


class EntityRecipient(RecipientGenerator):
"""Recipient generator working as handler for generic entity."""

def __init__(self, key: str):

def __init__(self, key):
"""Ctor."""
self.key = key

def __call__(self, notification, recipients: dict):
"""Fetch community and add members as recipients, based on roles."""
def __call__(self, notification: Notification, recipients: dict):
""""""
backend_ids = notification.context["backend_ids"]
entity_ref = dict_lookup(notification.context, self.key)
entity_type = list(entity_ref.keys())[0]
for backend_id in backend_ids:
generator = current_notification_recipients_resolvers_registry[entity_type][backend_id](entity_ref)
generator = current_notification_recipients_resolvers_registry[entity_type][
backend_id
](entity_ref)
generator(notification, recipients)


class SpecificEntityRecipient(RecipientGenerator):

def __init__(self, key):
Expand All @@ -34,11 +47,12 @@ def _resolve_entity(self):
entity = proxy.resolve()
return entity


class UserEmailRecipient(SpecificEntityRecipient):
"""User recipient generator for a notification."""
"""User email recipient generator for a notification."""

def __call__(self, notification, recipients):
"""Update required recipient information and add backend id."""
def __call__(self, notification: Notification, recipients: dict):
"""Update required recipient information."""
user = self._resolve_entity()
email = user.email
recipients[email] = Recipient(data={"email": email})
recipients[email] = Recipient(data={"email": email})
4 changes: 3 additions & 1 deletion oarepo_requests/proxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@
)

current_notification_recipients_resolvers_registry = LocalProxy( # type: ignore
lambda: current_app.extensions["oarepo-requests"].notification_recipients_resolvers_registry
lambda: current_app.extensions[
"oarepo-requests"
].notification_recipients_resolvers_registry
)
Loading

0 comments on commit 279623c

Please sign in to comment.