*** Wartungsfenster jeden ersten Mittwoch vormittag im Monat ***

Skip to content
Snippets Groups Projects
Commit cd37d401 authored by Moser, Maximilian's avatar Moser, Maximilian
Browse files

Implement custom notification infrastructure

* to support our notification use-cases
parent 2392122d
No related branches found
No related tags found
1 merge request!57Implement new curation workflow
...@@ -9,7 +9,11 @@ ...@@ -9,7 +9,11 @@
from datetime import datetime from datetime import datetime
from invenio_app_rdm.config import NOTIFICATIONS_BACKENDS, NOTIFICATIONS_BUILDERS from invenio_app_rdm.config import (
NOTIFICATIONS_BACKENDS,
NOTIFICATIONS_BUILDERS,
NOTIFICATIONS_ENTITY_RESOLVERS,
)
from invenio_curations.config import CURATIONS_NOTIFICATIONS_BUILDERS from invenio_curations.config import CURATIONS_NOTIFICATIONS_BUILDERS
from invenio_curations.services.facets import status as facets_status from invenio_curations.services.facets import status as facets_status
from invenio_curations.services.facets import type as facets_type from invenio_curations.services.facets import type as facets_type
...@@ -18,10 +22,11 @@ from invenio_oauthclient.views.client import auto_redirect_login ...@@ -18,10 +22,11 @@ from invenio_oauthclient.views.client import auto_redirect_login
from invenio_rdm_records.config import RDM_RECORDS_REVIEWS from invenio_rdm_records.config import RDM_RECORDS_REVIEWS
from .auth import TUWSSOSettingsHelper from .auth import TUWSSOSettingsHelper
from .notifications import GroupNotificationBuilder, SystemEntityResolver
from .notifications import ( from .notifications import (
TUWCurationRequestUploaderResubmitNotificationBuilder as TUWUploaderResubmitNotifBuilder, TUWCurationRequestUploaderResubmitNotificationBuilder as TUWUploaderResubmitNotifBuilder,
) )
from .notifications import TUWEmailNotificationBackend from .notifications import TUWEmailNotificationBackend, UserNotificationBuilder
from .permissions import ( from .permissions import (
TUWCommunityPermissionPolicy, TUWCommunityPermissionPolicy,
TUWRecordPermissionPolicy, TUWRecordPermissionPolicy,
...@@ -298,6 +303,8 @@ NOTIFICATIONS_BUILDERS = { ...@@ -298,6 +303,8 @@ NOTIFICATIONS_BUILDERS = {
**NOTIFICATIONS_BUILDERS, **NOTIFICATIONS_BUILDERS,
**CURATIONS_NOTIFICATIONS_BUILDERS, **CURATIONS_NOTIFICATIONS_BUILDERS,
TUWUploaderResubmitNotifBuilder.type: TUWUploaderResubmitNotifBuilder, TUWUploaderResubmitNotifBuilder.type: TUWUploaderResubmitNotifBuilder,
UserNotificationBuilder.type: UserNotificationBuilder,
GroupNotificationBuilder.type: GroupNotificationBuilder,
} }
CURATIONS_MODERATION_ROLE = "reviewer" CURATIONS_MODERATION_ROLE = "reviewer"
...@@ -306,6 +313,11 @@ CURATIONS_ALLOW_PUBLISHING_EDITS = True ...@@ -306,6 +313,11 @@ CURATIONS_ALLOW_PUBLISHING_EDITS = True
CURATIONS_PERMISSIONS_VIA_GRANTS = False CURATIONS_PERMISSIONS_VIA_GRANTS = False
NOTIFICATIONS_ENTITY_RESOLVERS = [
SystemEntityResolver("users"),
*NOTIFICATIONS_ENTITY_RESOLVERS,
]
# Misc. Configuration # Misc. Configuration
# =================== # ===================
......
...@@ -8,18 +8,137 @@ ...@@ -8,18 +8,137 @@
"""Overrides for notification builders from Invenio-Notifications.""" """Overrides for notification builders from Invenio-Notifications."""
from flask import current_app from flask import current_app
from invenio_access.permissions import system_identity
from invenio_curations.notifications.builders import ( from invenio_curations.notifications.builders import (
CurationRequestActionNotificationBuilder, CurationRequestActionNotificationBuilder,
) )
from invenio_curations.requests.curation import CurationRequest, CurationResubmitAction from invenio_curations.notifications.generators import GroupMembersRecipient
from invenio_curations.requests.curation import (
CurationCreateAndSubmitAction,
CurationRequest,
CurationResubmitAction,
CurationSubmitAction,
)
from invenio_mail.tasks import send_email from invenio_mail.tasks import send_email
from invenio_notifications.backends.email import EmailNotificationBackend from invenio_notifications.backends.email import EmailNotificationBackend
from invenio_notifications.models import Notification
from invenio_notifications.services.builders import NotificationBuilder
from invenio_notifications.services.generators import EntityResolve, UserEmailBackend
from invenio_notifications.services.uow import NotificationOp from invenio_notifications.services.uow import NotificationOp
from invenio_records_resources.references.entity_resolvers import (
EntityProxy,
EntityResolver,
)
from invenio_records_resources.services.uow import TaskOp
from invenio_users_resources.notifications.filters import UserPreferencesRecipientFilter from invenio_users_resources.notifications.filters import UserPreferencesRecipientFilter
from invenio_users_resources.notifications.generators import UserRecipient from invenio_users_resources.notifications.generators import UserRecipient
from marshmallow_utils.html import strip_html from marshmallow_utils.html import strip_html
from .proxies import current_config_tuw from .proxies import current_config_tuw
from .tasks import auto_review_curation_request
class UserNotificationBuilder(NotificationBuilder):
"""Basic notification builder for users."""
type = "user-notification"
context = [EntityResolve(key="receiver")]
recipients = [UserRecipient(key="receiver")]
recipient_backends = [UserEmailBackend()]
@classmethod
def build(
cls,
receiver,
subject,
message,
html_message=None,
plain_message=None,
md_message=None,
):
"""Build notification with context."""
return Notification(
type=cls.type,
context={
"receiver": receiver,
"subject": subject,
"message": message,
"html_message": html_message,
"plain_message": plain_message,
"md_message": md_message,
},
)
class GroupNotificationBuilder(UserNotificationBuilder):
"""Basic notification builder for groups."""
type = "group-notification"
recipients = [GroupMembersRecipient(key="receiver")]
class SystemEntityProxy(EntityProxy):
"""Entity proxy for the fake "system" entity."""
def get_needs(self):
"""Get the needs of the ``system_identity``."""
return system_identity.needs
def _resolve(self):
"""Create a user-like representation of the system.
Since this will mostly be used in Jinja templates, it being a dictionary
and not an actual object is fine.
"""
return {"username": "system", "user_profile": {"full_name": "System"}}
def pick_resolved_fields(self, identity, resolved_dict):
"""Select which fields to return when resolving the reference."""
return resolved_dict
class SystemEntityResolver(EntityResolver):
"""Entity resolver for the system identity."""
type_key = "users"
def _reference_entity(self, entity):
"""Create a reference dictionary for the system."""
return {"user": "system"}
def _get_entity_proxy(self, ref_dict):
"""Get an entity proxy for the fake "system" entity."""
return SystemEntityProxy(None, ref_dict)
def matches_entity(self, entity):
"""Since the system is not an actual entity, it can never match anything."""
return False
def matches_reference_dict(self, ref_dict):
"""Only matches the dictionary ``{"user": "system"}``."""
return ref_dict == {"user": "system"}
class TUWTaskOp(TaskOp):
"""A celery task operation.
Providing options for celery has been implemented via
``TaskOp.for_async_apply()`` in Invenio-Records-Resources v6.
Once we get that version, we can remove this class here.
"""
def __init__(self, celery_task, *args, countdown=None, **kwargs):
"""Initialize the task operation."""
self._celery_task = celery_task
self._args = args
self._kwargs = kwargs
self._cd = countdown
def on_post_commit(self, uow):
"""Run the post task operation."""
self._celery_task.apply_async(
args=self._args, kwargs=self._kwargs, countdown=self._cd
)
class TUWEmailNotificationBackend(EmailNotificationBackend): class TUWEmailNotificationBackend(EmailNotificationBackend):
......
{%- set context = notification.context -%}
{%- set receiver = recipient.data -%}
{#- Subject line for emails #}
{%- block subject -%}
{{ context.subject }}
{%- endblock subject %}
{#- HTML body for emails #}
{%- block html_body -%}
<p>
Hey, {{ receiver.profile.given_name or receiver.profile.full_name or receiver.username }}!
</p>
<p>
{{ context.html_message or context.message }}
</p>
<p>
From: {{ config.THEME_SITENAME }}
</p>
{%- endblock html_body -%}
{#- Plaintext body for emails #}
{%- block plain_body -%}
Hey, {{ receiver.profile.given_name or receiver.profile.full_name or receiver.username }}!
{{ context.plain_message or context.message }}
From: {{ config.THEME_SITENAME }}
{%- endblock plain_body -%}
{#- Markdown body for chat #}
{%- block md_body -%}
Hey, {{ receiver.profile.given_name or receiver.profile.full_name or receiver.username }}!
{{ context.md_message or context.message }}
From: {{ config.THEME_SITENAME }}
{%- endblock md_body -%}
{%- set context = notification.context -%}
{%- set receiver = recipient.data -%}
{#- Subject line for emails #}
{%- block subject -%}
{{ context.subject }}
{%- endblock subject %}
{#- HTML body for emails #}
{%- block html_body -%}
<p>
Hey, {{ receiver.profile.given_name or receiver.profile.full_name or receiver.username }}!
</p>
<p>
{{ context.html_message or context.message }}
</p>
<p>
From: {{ config.THEME_SITENAME }}
</p>
{%- endblock html_body -%}
{#- Plaintext body for emails #}
{%- block plain_body -%}
Hey, {{ receiver.profile.given_name or receiver.profile.full_name or receiver.username }}!
{{ context.plain_message or context.message }}
From: {{ config.THEME_SITENAME }}
{%- endblock plain_body -%}
{#- Markdown body for chat #}
{%- block md_body -%}
Hey, {{ receiver.profile.given_name or receiver.profile.full_name or receiver.username }}!
{{ context.md_message or context.message }}
From: {{ config.THEME_SITENAME }}
{%- endblock md_body -%}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment