forked from CGM_Public/pretix_original
Add support for bulk-webhooks
This commit is contained in:
@@ -49,9 +49,7 @@ class LoggingMixin:
|
||||
:param user: The user performing the action (optional)
|
||||
"""
|
||||
from pretix.api.models import OAuthAccessToken, OAuthApplication
|
||||
from pretix.api.webhooks import get_all_webhook_events, notify_webhooks
|
||||
|
||||
from ..notifications import get_all_notification_types
|
||||
from pretix.api.webhooks import notify_webhooks
|
||||
from ..services.notifications import notify
|
||||
from .devices import Device
|
||||
from .event import Event
|
||||
@@ -93,21 +91,11 @@ class LoggingMixin:
|
||||
if save:
|
||||
logentry.save()
|
||||
|
||||
no_types = get_all_notification_types()
|
||||
wh_types = get_all_webhook_events()
|
||||
|
||||
no_type = None
|
||||
wh_type = None
|
||||
typepath = logentry.action_type
|
||||
while (not no_type or not wh_types) and '.' in typepath:
|
||||
wh_type = wh_type or wh_types.get(typepath + ('.*' if typepath != logentry.action_type else ''))
|
||||
no_type = no_type or no_types.get(typepath + ('.*' if typepath != logentry.action_type else ''))
|
||||
typepath = typepath.rsplit('.', 1)[0]
|
||||
|
||||
if no_type:
|
||||
if logentry.notification_type:
|
||||
notify.apply_async(args=(logentry.pk,))
|
||||
if wh_type:
|
||||
if logentry.webhook_type:
|
||||
notify_webhooks.apply_async(args=(logentry.pk,))
|
||||
|
||||
return logentry
|
||||
|
||||
|
||||
|
||||
@@ -63,14 +63,42 @@ class LogEntry(models.Model):
|
||||
return response
|
||||
return self.action_type
|
||||
|
||||
@property
|
||||
def webhook_type(self):
|
||||
from pretix.api.webhooks import get_all_webhook_events
|
||||
|
||||
wh_types = get_all_webhook_events()
|
||||
wh_type = None
|
||||
typepath = self.action_type
|
||||
while not wh_type and '.' in typepath:
|
||||
wh_type = wh_type or wh_types.get(typepath + ('.*' if typepath != self.action_type else ''))
|
||||
typepath = typepath.rsplit('.', 1)[0]
|
||||
return wh_type
|
||||
|
||||
@property
|
||||
def notification_type(self):
|
||||
from pretix.base.notifications import get_all_notification_types
|
||||
|
||||
no_type = None
|
||||
no_types = get_all_notification_types()
|
||||
typepath = self.action_type
|
||||
while not no_type and '.' in typepath:
|
||||
no_type = no_type or no_types.get(typepath + ('.*' if typepath != self.action_type else ''))
|
||||
typepath = typepath.rsplit('.', 1)[0]
|
||||
return no_type
|
||||
|
||||
@cached_property
|
||||
def organizer(self):
|
||||
from .organizer import Organizer
|
||||
|
||||
if self.event:
|
||||
return self.event.organizer
|
||||
elif hasattr(self.content_object, 'event'):
|
||||
return self.content_object.event.organizer
|
||||
elif hasattr(self.content_object, 'organizer'):
|
||||
return self.content_object.organizer
|
||||
elif isinstance(self.content_object, Organizer):
|
||||
return self.content_object
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
@@ -188,3 +216,15 @@ class LogEntry(models.Model):
|
||||
|
||||
def delete(self, using=None, keep_parents=False):
|
||||
raise TypeError("Logs cannot be deleted.")
|
||||
|
||||
@classmethod
|
||||
def bulk_postprocess(cls, objects):
|
||||
from pretix.api.webhooks import notify_webhooks
|
||||
from ..services.notifications import notify
|
||||
|
||||
to_notify = [o.id for o in objects if o.notification_type]
|
||||
if to_notify:
|
||||
notify.apply_async(args=(to_notify,))
|
||||
to_wh = [o.id for o in objects if o.webhook_type]
|
||||
if to_wh:
|
||||
notify_webhooks.apply_async(args=(to_wh,))
|
||||
|
||||
@@ -15,55 +15,59 @@ from pretix.helpers.urls import build_absolute_uri
|
||||
|
||||
@app.task(base=TransactionAwareTask, acks_late=True)
|
||||
@scopes_disabled()
|
||||
def notify(logentry_id: int):
|
||||
logentry = LogEntry.all.select_related('event', 'event__organizer').get(id=logentry_id)
|
||||
if not logentry.event:
|
||||
return # Ignore, we only have event-related notifications right now
|
||||
types = get_all_notification_types(logentry.event)
|
||||
def notify(logentry_ids: list):
|
||||
if not isinstance(logentry_ids, list):
|
||||
logentry_ids = [logentry_ids]
|
||||
|
||||
notification_type = None
|
||||
typepath = logentry.action_type
|
||||
while not notification_type and '.' in typepath:
|
||||
notification_type = types.get(typepath + ('.*' if typepath != logentry.action_type else ''))
|
||||
typepath = typepath.rsplit('.', 1)[0]
|
||||
qs = LogEntry.all.select_related('event', 'event__organizer').filter(id__in=logentry_ids)
|
||||
|
||||
if not notification_type:
|
||||
return # No suitable plugin
|
||||
_event, _at, notify_specific, notify_global = None, None, None, None
|
||||
for logentry in qs:
|
||||
if not logentry.event:
|
||||
break # Ignore, we only have event-related notifications right now
|
||||
|
||||
# All users that have the permission to get the notification
|
||||
users = logentry.event.get_users_with_permission(
|
||||
notification_type.required_permission
|
||||
).filter(notifications_send=True, is_active=True)
|
||||
if logentry.user:
|
||||
users = users.exclude(pk=logentry.user.pk)
|
||||
notification_type = logentry.notification_type
|
||||
|
||||
# Get all notification settings, both specific to this event as well as global
|
||||
notify_specific = {
|
||||
(ns.user, ns.method): ns.enabled
|
||||
for ns in NotificationSetting.objects.filter(
|
||||
event=logentry.event,
|
||||
action_type=notification_type.action_type,
|
||||
user__pk__in=users.values_list('pk', flat=True)
|
||||
)
|
||||
}
|
||||
notify_global = {
|
||||
(ns.user, ns.method): ns.enabled
|
||||
for ns in NotificationSetting.objects.filter(
|
||||
event__isnull=True,
|
||||
action_type=notification_type.action_type,
|
||||
user__pk__in=users.values_list('pk', flat=True)
|
||||
)
|
||||
}
|
||||
if not notification_type:
|
||||
break # No suitable plugin
|
||||
|
||||
for um, enabled in notify_specific.items():
|
||||
user, method = um
|
||||
if enabled:
|
||||
send_notification.apply_async(args=(logentry_id, notification_type.action_type, user.pk, method))
|
||||
if _event != logentry.event or _at != logentry.action_type or notify_global is None:
|
||||
_event = logentry.event
|
||||
_at = logentry.action_type
|
||||
# All users that have the permission to get the notification
|
||||
users = logentry.event.get_users_with_permission(
|
||||
notification_type.required_permission
|
||||
).filter(notifications_send=True, is_active=True)
|
||||
if logentry.user:
|
||||
users = users.exclude(pk=logentry.user.pk)
|
||||
|
||||
for um, enabled in notify_global.items():
|
||||
user, method = um
|
||||
if enabled and um not in notify_specific:
|
||||
send_notification.apply_async(args=(logentry_id, notification_type.action_type, user.pk, method))
|
||||
# Get all notification settings, both specific to this event as well as global
|
||||
notify_specific = {
|
||||
(ns.user, ns.method): ns.enabled
|
||||
for ns in NotificationSetting.objects.filter(
|
||||
event=logentry.event,
|
||||
action_type=notification_type.action_type,
|
||||
user__pk__in=users.values_list('pk', flat=True)
|
||||
)
|
||||
}
|
||||
notify_global = {
|
||||
(ns.user, ns.method): ns.enabled
|
||||
for ns in NotificationSetting.objects.filter(
|
||||
event__isnull=True,
|
||||
action_type=notification_type.action_type,
|
||||
user__pk__in=users.values_list('pk', flat=True)
|
||||
)
|
||||
}
|
||||
|
||||
for um, enabled in notify_specific.items():
|
||||
user, method = um
|
||||
if enabled:
|
||||
send_notification.apply_async(args=(logentry.id, notification_type.action_type, user.pk, method))
|
||||
|
||||
for um, enabled in notify_global.items():
|
||||
user, method = um
|
||||
if enabled and um not in notify_specific:
|
||||
send_notification.apply_async(args=(logentry.id, notification_type.action_type, user.pk, method))
|
||||
|
||||
|
||||
@app.task(base=ProfiledTask, acks_late=True)
|
||||
|
||||
@@ -4,7 +4,7 @@ from datetime import datetime, timedelta
|
||||
from dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY, rrule, rruleset
|
||||
from django.contrib import messages
|
||||
from django.core.files import File
|
||||
from django.db import transaction
|
||||
from django.db import transaction, connections
|
||||
from django.db.models import F, IntegerField, OuterRef, Prefetch, Subquery, Sum
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.forms import inlineformset_factory
|
||||
@@ -863,7 +863,13 @@ class SubEventBulkCreate(SubEventEditorMixin, EventPermissionRequiredMixin, Crea
|
||||
f.subevent = se
|
||||
f.save()
|
||||
|
||||
LogEntry.objects.bulk_create(log_entries)
|
||||
if connections['default'].features.can_return_rows_from_bulk_insert:
|
||||
LogEntry.objects.bulk_create(log_entries)
|
||||
LogEntry.bulk_postprocess(log_entries)
|
||||
else:
|
||||
for le in log_entries:
|
||||
le.save()
|
||||
LogEntry.bulk_postprocess(log_entries)
|
||||
|
||||
self.request.event.cache.clear()
|
||||
messages.success(self.request, pgettext_lazy('subevent', '{} new dates have been created.').format(len(subevents)))
|
||||
|
||||
Reference in New Issue
Block a user