0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-11-30 01:46:24 +01:00

Add GroupApprovalTaskStateNotifier

This commit is contained in:
jacobtm 2020-01-13 10:59:19 +00:00 committed by Matt Westcott
parent 8f5535d5bb
commit cfeef13cfd

View File

@ -9,7 +9,7 @@ from django.utils.text import get_valid_filename
from django.utils.translation import override from django.utils.translation import override
from wagtail.admin.auth import users_with_page_permission from wagtail.admin.auth import users_with_page_permission
from wagtail.core.models import Page, PageRevision from wagtail.core.models import Page, PageRevision, GroupApprovalTaskState, WorkflowState
from wagtail.users.models import UserProfile from wagtail.users.models import UserProfile
@ -17,6 +17,7 @@ logger = logging.getLogger('wagtail.admin')
class OpenedConnection: class OpenedConnection:
"""Context manager for mail connections to ensure they are closed when manually opened"""
def __init__(self, connection): def __init__(self, connection):
self.connection = connection self.connection = connection
@ -133,96 +134,161 @@ def send_notification(page_revision_id, notification, excluded_user_id):
return sent_count == len(email_recipients) return sent_count == len(email_recipients)
def send_group_approval_task_state_notification(task_state, notification, triggering_user): class Notifier:
recipients = [] """Class for sending email notifications upon events: callable, taking a notifying_instance and a notification (str)
page = task_state.workflow_state.page and sending email notifications using rendered templates"""
if notification in ('approved', 'rejected'):
requested_by = task_state.workflow_state.requested_by
if requested_by != triggering_user:
recipients = [requested_by]
elif notification == 'submitted':
recipients = task_state.task.specific.group.user_set
include_superusers = getattr(settings, 'WAGTAILADMIN_NOTIFICATION_INCLUDE_SUPERUSERS', True)
if include_superusers:
recipients = recipients | get_user_model().objects.filter(is_superuser=True)
recipients = recipients.exclude(pk=triggering_user.pk).distinct()
context = {
"page": page,
"settings": settings,
"task": task_state.task,
}
send_notification_emails(recipients, notification, context, template_base_prefix='group_approval_task_')
def __init__(self, valid_classes, valid_notifications):
self.valid_classes = valid_classes
self.valid_notifications = valid_notifications
def send_workflow_state_notification(workflow_state, notification, triggering_user): def can_handle_class(self, instance):
recipients = [] return type(instance) in self.valid_classes
page = workflow_state.page
if notification in ('approved', 'rejected'):
requested_by = workflow_state.requested_by
if requested_by != triggering_user:
recipients = [requested_by]
elif notification == 'submitted':
include_superusers = getattr(settings, 'WAGTAILADMIN_NOTIFICATION_INCLUDE_SUPERUSERS', True)
if include_superusers:
recipients = get_user_model().objects.filter(is_superuser=True).exclude(pk=triggering_user.pk)
context = {
"page": page,
"settings": settings,
"workflow": workflow_state.workflow,
}
send_notification_emails(recipients, notification, context, template_base_prefix='workflow_')
def can_handle_notification(self, notification):
return notification in self.valid_notifications
def send_notification_emails(recipients, notification, context, template_base_prefix=''): def can_handle(self, notifying_instance, notification):
return self.can_handle_class(notifying_instance) and self.can_handle_notification(notification)
# Get list of email addresses def get_recipient_users(self, notifying_instance, notification, **kwargs):
email_recipients = [ return set()
recipient for recipient in recipients
if recipient.email and getattr( def get_valid_recipients(self, notifying_instance, notification, **kwargs):
"""Filters notification recipients to those allowing the notification type on their UserProfile, and those
with an email address"""
return {recipient for recipient in self.get_recipient_users(notifying_instance, notification, **kwargs) if recipient.email and getattr(
UserProfile.get_for_user(recipient), UserProfile.get_for_user(recipient),
notification + '_notifications' notification + '_notifications'
) )}
]
# Return if there are no email addresses def get_template_base_prefix(self, notifying_instance):
if not email_recipients: return get_valid_filename(type(notifying_instance).__name__)+'_'
return True
# Get template def get_template_set(self, notifying_instance, notification):
template_base = template_base_prefix + notification """Return a dictionary of template paths for the templates for the email subject and the text and html
alternatives"""
template_base = self.get_template_base_prefix(notifying_instance) + notification
template_subject = 'wagtailadmin/notifications/' + template_base + '_subject.txt' template_subject = 'wagtailadmin/notifications/' + template_base + '_subject.txt'
template_text = 'wagtailadmin/notifications/' + template_base + '.txt' template_text = 'wagtailadmin/notifications/' + template_base + '.txt'
template_html = 'wagtailadmin/notifications/' + template_base + '.html' template_html = 'wagtailadmin/notifications/' + template_base + '.html'
connection = get_connection() return {
'subject': template_subject,
'text': template_text,
'html': template_html,
}
with OpenedConnection(connection) as open_connection: def get_context(self, notifying_instance, notification, **kwargs):
return {'settings': settings}
# Send emails def send_emails(self, template_set, context, recipients):
sent_count = 0 connection = get_connection()
for recipient in email_recipients:
try:
# update context with this recipient
context["user"] = recipient
# Translate text to the recipient language settings with OpenedConnection(connection) as open_connection:
with override(recipient.wagtail_userprofile.get_preferred_language()):
# Get email subject and content
email_subject = render_to_string(template_subject, context).strip()
email_content = render_to_string(template_text, context).strip()
kwargs = {} # Send emails
if getattr(settings, 'WAGTAILADMIN_NOTIFICATION_USE_HTML', False): sent_count = 0
kwargs['html_message'] = render_to_string(template_html, context) for recipient in recipients:
try:
# update context with this recipient
context["user"] = recipient
# Send email # Translate text to the recipient language settings
send_mail(email_subject, email_content, [recipient.email], connection=open_connection, **kwargs) with override(recipient.wagtail_userprofile.get_preferred_language()):
sent_count += 1 # Get email subject and content
except Exception: email_subject = render_to_string(template_set['subject'], context).strip()
logger.exception( email_content = render_to_string(template_set['text'], context).strip()
"Failed to send notification email '%s' to %s",
email_subject, recipient.email
)
return sent_count == len(email_recipients) kwargs = {}
if getattr(settings, 'WAGTAILADMIN_NOTIFICATION_USE_HTML', False):
kwargs['html_message'] = render_to_string(template_set['html'], context)
# Send email
send_mail(email_subject, email_content, [recipient.email], connection=open_connection, **kwargs)
sent_count += 1
except Exception:
logger.exception(
"Failed to send notification email '%s' to %s",
email_subject, recipient.email
)
return sent_count == len(recipients)
def __call__(self, notifying_instance, notification, **kwargs):
"""Send emails corresponding to the notification (eg 'approved') from an instance, notifying_instance"""
if not self.can_handle(notifying_instance, notification):
return False
recipients = self.get_valid_recipients(notifying_instance, notification, **kwargs)
if not recipients:
return True
template_set = self.get_template_set(notifying_instance, notification)
context = self.get_context(notifying_instance, notification, **kwargs)
return self.send_emails(template_set, context, recipients)
class WorkflowStateNotifier(Notifier):
"""A Notifier to send updates for WorkflowState events"""
def __init__(self, valid_notifications):
super().__init__({WorkflowState}, valid_notifications)
def get_recipient_users(self, workflow_state, notification, **kwargs):
triggering_user = kwargs.get('user', None)
recipients = {}
if notification in ('approved', 'rejected'):
requested_by = workflow_state.requested_by
if requested_by != triggering_user:
recipients = {requested_by}
elif notification == 'submitted':
include_superusers = getattr(settings, 'WAGTAILADMIN_NOTIFICATION_INCLUDE_SUPERUSERS', True)
if include_superusers:
recipients = get_user_model().objects.filter(is_superuser=True)
if triggering_user:
recipients.exclude(pk=triggering_user.pk)
return recipients
def get_context(self, workflow_state, notification, **kwargs):
context = super().get_context(workflow_state, notification, **kwargs)
context['page'] = workflow_state.page
context['workflow'] = workflow_state.workflow
return context
class GroupApprovalTaskStateNotifier(Notifier):
"""A Notifier to send updates for GroupApprovalTask events"""
def __init__(self, valid_notifications):
super().__init__({GroupApprovalTaskState}, valid_notifications)
def get_context(self, task_state, notification, **kwargs):
context = super().get_context(task_state, notification, **kwargs)
context['page'] = task_state.revision.page
context['task'] = task_state.task.specific
return context
def get_recipient_users(self, task_state, notification, **kwargs):
triggering_user = kwargs.get('user', None)
requested_by = task_state.workflow_state.requested_by
group_members = task_state.task.specific.group.user_set
recipients = requested_by | group_members
include_superusers = getattr(settings, 'WAGTAILADMIN_NOTIFICATION_INCLUDE_SUPERUSERS', True)
if include_superusers:
superusers = get_user_model().objects.filter(is_superuser=True)
recipients = recipients | superusers
if triggering_user:
"""Exclude"""
recipients = recipients.exclude(pk=triggering_user.pk)
return recipients