Skip to content

Commit

Permalink
access-requests: send notification on submit action
Browse files Browse the repository at this point in the history
  • Loading branch information
rekt-hard committed Oct 3, 2023
1 parent 3db3156 commit 8fc48d3
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 5 deletions.
126 changes: 126 additions & 0 deletions invenio_rdm_records/notifications/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from invenio_users_resources.notifications.filters import UserPreferencesRecipientFilter
from invenio_users_resources.notifications.generators import (
EmailRecipient,
IfUserRecipient,
UserRecipient,
)

Expand Down Expand Up @@ -98,6 +99,51 @@ def build(cls, record, email, verify_url):
]


class GuestAccessRequestSubmitNotificationBuilder(NotificationBuilder):
"""Notification builder for guest access requests."""

type = "guest-access-request.submit"

@classmethod
def build(cls, request):
"""Build notification with request context."""
return Notification(
type=cls.type,
context={
"request": EntityResolverRegistry.reference_entity(request),
"receiver_entity": request.receiver.reference_dict, # will not be resolved for easier lookup for recipients
},
)

context = [
EntityResolve(key="request"),
EntityResolve(key="request.created_by"),
EntityResolve(key="request.topic"),
EntityResolve(key="request.receiver"),
]

recipients = [
# Currently only these two are allowed. Adapt as needed.
IfUserRecipient(
key="receiver_entity",
then_=[UserRecipient(key="request.receiver")],
else_=[
CommunityMembersRecipient(
key="request.receiver", roles=["curator", "owner"]
)
],
)
]

recipient_filters = [
UserPreferencesRecipientFilter(),
]

recipient_backends = [
UserEmailBackend(),
]


class GuestAccessRequestAcceptNotificationBuilder(NotificationBuilder):
"""Notification builder for user access requests."""

Expand Down Expand Up @@ -131,6 +177,86 @@ def build(cls, request, access_url):
]


class UserAccessRequestSubmitNotificationBuilder(NotificationBuilder):
"""Notification builder for user access requests."""

type = "user-access-request.submit"

@classmethod
def build(cls, request):
"""Build notification with request context."""
return Notification(
type=cls.type,
context={
"request": EntityResolverRegistry.reference_entity(request),
"receiver_entity": request.receiver.reference_dict, # will not be resolved for easier lookup for recipients
},
)

context = [
EntityResolve(key="request"),
EntityResolve(key="request.created_by"),
EntityResolve(key="request.topic"),
EntityResolve(key="request.receiver"),
]

recipients = [
# Currently only these two are allowed. Adapt as needed.
IfUserRecipient(
key="receiver_entity",
then_=[UserRecipient(key="request.receiver")],
else_=[
CommunityMembersRecipient(
key="request.receiver", roles=["curator", "owner"]
)
],
)
]

recipient_filters = [
UserPreferencesRecipientFilter(),
]

recipient_backends = [
UserEmailBackend(),
]


class UserAccessRequestAcceptNotificationBuilder(NotificationBuilder):
"""Notification builder for user access requests."""

type = "user-access-request.accept"

@classmethod
def build(cls, request):
"""Build notification with request context."""
return Notification(
type=cls.type,
context={
"request": EntityResolverRegistry.reference_entity(request),
},
)

context = [
EntityResolve(key="request"),
EntityResolve(key="request.created_by"),
EntityResolve(key="request.topic"),
EntityResolve(key="request.receiver"),
]

recipients = [
UserRecipient(key="request.created_by"),
]

recipient_filters = [
UserPreferencesRecipientFilter(),
]

recipient_backends = [
UserEmailBackend(),
]


class CommunityInclusionActionNotificationBuilder(NotificationBuilder):
"""Notification builder for inclusion actions."""

Expand Down
13 changes: 12 additions & 1 deletion invenio_rdm_records/requests/access/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

from invenio_rdm_records.notifications.builders import (
GuestAccessRequestAcceptNotificationBuilder,
GuestAccessRequestSubmitNotificationBuilder,
UserAccessRequestAcceptNotificationBuilder,
UserAccessRequestSubmitNotificationBuilder,
)

from ...proxies import current_rdm_records_service as service
Expand All @@ -37,6 +39,11 @@ class UserSubmitAction(actions.SubmitAction):
def execute(self, identity, uow):
"""Execute the submit action."""
self.request["title"] = self.request.topic.resolve().metadata["title"]
uow.register(
NotificationOp(
UserAccessRequestSubmitNotificationBuilder.build(request=self.request)
)
)
super().execute(identity, uow)


Expand All @@ -47,7 +54,11 @@ def execute(self, identity, uow):
"""Execute the submit action."""
record = self.request.topic.resolve()
self.request["title"] = record.metadata["title"]

uow.register(
NotificationOp(
GuestAccessRequestSubmitNotificationBuilder.build(request=self.request)
)
)
super().execute(identity, uow)


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{% set access_request = notification.context.request %}
{% set creator_email = access_request.created_by %}
{% set record = access_request.topic %}

{% set record_title = record.metadata.title %}
{% set request_id = access_request.id %}
{# TODO: use request.links.self_html when issue issue is resolved: https://github.com/inveniosoftware/invenio-rdm-records/issues/1327 #}
{% set request_link = "{ui}/me/requests/{id}".format(
ui=config.SITE_UI_URL, id=request_id
)
%}

{%- block subject -%}
{{ _("New access request for '{record_title}'.").format(record_title=record_title) }}
{%- endblock subject -%}

{%- block html_body -%}
<p>
{{ _("New access request for '{record_title}' was submitted.").format(record_title=record_title) }}
</p>

<a href="{{ request_link }}" class="button"> {{ _("Check out the access request") }}</a>
{%- endblock html_body -%}

{%- block plain_body -%}
{{ _("New access request for '{record_title}' was submitted.").format(record_title=record_title) }}

{{ _("Checkout the access request: {url}").format(url=request_link) }}
{%- endblock plain_body -%}

{# Markdown for Slack/Mattermost/chat #}
{%- block md_body -%}
{{ _("New access request for *{record_title}* was submitted.").format(record_title=record_title) }}

[{{ _("Checkout the access request") }}]({{ request_link }})
{%- endblock md_body -%}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{% set access_request = notification.context.request %}
{% set creator = access_request.created_by %}
{% set record = access_request.topic %}

{% set record_title = record.metadata.title %}
{% set request_id = access_request.id %}
{# TODO: use request.links.self_html when issue issue is resolved: https://github.com/inveniosoftware/invenio-rdm-records/issues/1327 #}
{% set request_link = "{ui}/me/requests/{id}".format(
ui=config.SITE_UI_URL, id=request_id
)
%}

{%- block subject -%}
{{ _("New access request for '{record_title}'.").format(record_title=record_title) }}
{%- endblock subject -%}

{%- block html_body -%}
<p>
{{ _("New access request for '{record_title}' was submitted.").format(record_title=record_title) }}
</p>

<a href="{{ request_link }}" class="button"> {{ _("Check out the access request") }}</a>
{%- endblock html_body -%}

{%- block plain_body -%}
{{ _("New access request for '{record_title}' was submitted.").format(record_title=record_title) }}

{{ _("Checkout the access request: {url}").format(url=request_link) }}
{%- endblock plain_body -%}

{# Markdown for Slack/Mattermost/chat #}
{%- block md_body -%}
{{ _("New access request for *{record_title}* was submitted.").format(record_title=record_title) }}

[{{ _("Checkout the access request") }}]({{ request_link }})
{%- endblock md_body -%}
4 changes: 4 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@
CommunityInclusionExpireNotificationBuilder,
CommunityInclusionSubmittedNotificationBuilder,
GuestAccessRequestAcceptNotificationBuilder,
GuestAccessRequestSubmitNotificationBuilder,
GuestAccessRequestTokenCreateNotificationBuilder,
UserAccessRequestAcceptNotificationBuilder,
UserAccessRequestSubmitNotificationBuilder,
)
from invenio_rdm_records.proxies import current_rdm_records_service
from invenio_rdm_records.records.api import RDMDraft, RDMParent, RDMRecord
Expand Down Expand Up @@ -298,7 +300,9 @@ def app_config(app_config, mock_datacite_client):
CommunityInvitationSubmittedNotificationBuilder.type: DummyNotificationBuilder,
GuestAccessRequestTokenCreateNotificationBuilder.type: GuestAccessRequestTokenCreateNotificationBuilder,
GuestAccessRequestAcceptNotificationBuilder.type: GuestAccessRequestAcceptNotificationBuilder,
GuestAccessRequestSubmitNotificationBuilder.type: GuestAccessRequestSubmitNotificationBuilder,
UserAccessRequestAcceptNotificationBuilder.type: UserAccessRequestAcceptNotificationBuilder,
UserAccessRequestSubmitNotificationBuilder.type: UserAccessRequestSubmitNotificationBuilder,
}

# Specifying default resolvers. Will only be used in specific test cases.
Expand Down
17 changes: 13 additions & 4 deletions tests/resources/test_access_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,16 @@ def test_simple_guest_access_request_flow(running_app, client, users, minimal_re
identity=guest_identity, token=args["access_request_token"]
)

assert len(outbox) == 2
submit_message = outbox[1]
# TODO: update to `req["links"]["self_html"]` when addressing https://github.com/inveniosoftware/invenio-rdm-records/issues/1327
assert "/me/requests/{}".format(request.id) in submit_message.html

# Accept the request
# This is expected to send out another email, containing the new secret link
current_requests_service.execute_action(identity, request.id, "accept", data={})
assert len(outbox) == 2
success_message = outbox[1]
assert len(outbox) == 3
success_message = outbox[2]
match = link_regex.search(str(success_message.body))
assert match
access_url = match.group(1)
Expand Down Expand Up @@ -184,11 +189,15 @@ def test_simple_user_access_request_flow(running_app, client, users, minimal_rec
)
request_id = response.json["id"]
assert response.status_code == 200
assert len(outbox) == 1
submit_message = outbox[0]
# TODO: update to `req["links"]["self_html"]` when addressing https://github.com/inveniosoftware/invenio-rdm-records/issues/1327
assert "/me/requests/{}".format(request_id) in submit_message.html

# The record owner approves the access request
current_requests_service.execute_action(identity, request_id, "accept", data={})
assert len(outbox) == 1
success_message = outbox[0]
assert len(outbox) == 2
success_message = outbox[1]
assert record.to_dict()["links"]["self_html"] in success_message.body

# Now, the user has permission to view the record's files!
Expand Down

0 comments on commit 8fc48d3

Please sign in to comment.