Closed zzacharo closed 1 year ago
[
{target: <Jim>, template: }
# Anna (curator)
Bob (curator)
]
#
# Notification builder interface
#
# Invenio-Records-Resources/Invenio-Notifications
class PayloadGeneratorABC:
def run(context: dict) -> dict:
pass
class NotificationBuilderBase:
def build(context: dict) -> Notification:
pass
payload_generator: List[PayloadGeneratorABC]
recipients_generator: List[RecipientGeneratorABC]
recipients_filters: List[PayloadGeneratorABC]
recipient_backend_transform: List[PayloadGeneratorABC]
#
# Notification builder implementation for community record inclusion request
#
# invenio_rdm_records/communities/notifications.py
class CommunityRecordInclusionNotificationBuilder(NotificationBuilderBase):
payload_generator = [
RequestPayloadGenerator,
CommunityPayloadGenerator,
RecordPayloadGenerator,
]
recipients_generator = [
RequestRecipientsGenerator,
CommunityRecipientsGenerator,
]
recipients_filters = [
UserRecipientFilter,
CommunityMemberRecipientFilter,
]
recipient_backend_transform = [
UserPreferencesBackend,
]
# invenio_requests/notifications.py
class RequestPayloadGenerator:
def run(**kwargs):
return { "request": request_item.to_dict(), }
# invenio_rdm_records/notifications.py
class RecordPayloadGenerator:
def run():
return {"record": record.dumps()},
# invenio_communities/notifications.py
class CommunityPayloadGenerator:
def run():
return {"community": current_communities.service.read(identity=system_identity, id_=community.id).to_dict()}
# invenio_requests/notifications.py
class RequestRecipientsGenerator:
def run():
return [
request.created_by,
# {"community": "biosyslit"}
request.receiver,
]
# invenio_communities/notifications.py
class CommunityRecipientsGenerator:
def run(request_item):
if type in [CommunitySubmissionCreatedEvent, CommunitySubmissionSubmittedEvent]:
members = Member.get_members(community.id)
# get owner, managers and curators. There should be an easier way
return [
m.relations.user.dereference() for m in members
if m.user_id
and m.role in ["owner", "manager", "curator"] #
]
# invenio_users_resources/notifications.py
class UserRecipientFilter:
def run(user):
return user.preferences["notifications"]["enabled"]
# invenio_communities/notifications.py
class CommunityMemberRecipientFilter:
def run(user, community, request):
community_member = community.members[user.id]
comm_pref = community_member.preferences.notifications
PREF_MAP = {
"all": ["inclusion requests", "accepted/rejected", "comments"],
"all_but_no_comments": ["inclusion requests", "accepted/rejected"],
"none": [],
}
return request.type in PREF_MAP[comm_pref]
#
# Example fully-resolved user payload
#
user = {
"id": 1234,
"email": "jim@example.com",
"username": "jim",
"profile": {
"full_name": "Jim Doe",
"affiliation": "ACME Inc.",
},
"preferences": {
"visibility": "public",
"email_visibility": "public",
"notifications": {
"enabled": True,
# E.g. in the future we could have:
# "prefferd_backend": "email",
}
}
}
#
# Example backend payloads
#
email_backend_payload = {
"backend": "email",
"template": "member_invitation_receiver.html",
# "template": "member_invitation_curators.html",
"to": "Jim Doe <jim@example.com",
# or could be:
# "cc": "Jim Doe <jim@example.com",
}
chat_backend_payload = {
"backend": "chat",
"target": "@jim",
}
recipients = [
{"user": user, "backends": [email_backend_payload, chat_backend_payload]},
]
#
# Example UoW notification sending
#
# in the service
uow.register(NotificationOp(CommunityRecordInclusionNotificationBuilder.build(
{
"request": request,
"community": community,
"record": record,
}
)))
def on_post_commit():
curent_notifications.broadcast(self._payload)
#
# User preferences marshmallow schema
#
# invenio_users_resources/schemas.py
class NotificationPreferencesSchema(BaseUserPreferencesSchema):
notifications = fields.Nested({
"enabled": fields.Bool(),
})
class NotificationPreferencesMixin:
notifications = fields.Nested({
"enabled": fields.Bool(),
})
# invenio_app_rdm/config.py
from invenio_users_resources.schema import NotificationPreferencesSchema
ACCOUNTS_USER_PREFERENCES_SCHEMA = NotificationPreferencesSchema
from invenio_users_resources.schema import NotificationPreferencesMixin
class UserPreferencesSchema(BaseUserPreferencesSchema, NotificationPreferencesMixin):
pass
ACCOUNTS_USER_PREFERENCES_SCHEMA = UserPreferencesSchema
This issue was automatically marked as stale.
New repository at https://github.com/inveniosoftware/invenio-notifications
Previous RFC
https://codimd.web.cern.ch/RH_steApSGOk4Yaoex782A#notifications
Issues/comments
Open PRs
master
Next steps
invenio_requests/notifications
to a newinvenio-notifications
moduleUser.preferences.notifications
configuration so that users can easily enable/disable all notifications.User.preferences.locale
(to be used in templates); see also the relevant I18N codeDecisions
What is the mechanism for creating notifications? Some likely candidates:
NotificationOp
(we already haveChangeNotificationOp
for a different use-case)Where is the notification mechanism triggered?. See examples for clarity:
ReviewService.submit()
SubmitAction.execute()
RequestEventService.create()
AcceptAction.execute()