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)
|
:param user: The user performing the action (optional)
|
||||||
"""
|
"""
|
||||||
from pretix.api.models import OAuthAccessToken, OAuthApplication
|
from pretix.api.models import OAuthAccessToken, OAuthApplication
|
||||||
from pretix.api.webhooks import get_all_webhook_events, notify_webhooks
|
from pretix.api.webhooks import notify_webhooks
|
||||||
|
|
||||||
from ..notifications import get_all_notification_types
|
|
||||||
from ..services.notifications import notify
|
from ..services.notifications import notify
|
||||||
from .devices import Device
|
from .devices import Device
|
||||||
from .event import Event
|
from .event import Event
|
||||||
@@ -93,21 +91,11 @@ class LoggingMixin:
|
|||||||
if save:
|
if save:
|
||||||
logentry.save()
|
logentry.save()
|
||||||
|
|
||||||
no_types = get_all_notification_types()
|
if logentry.notification_type:
|
||||||
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:
|
|
||||||
notify.apply_async(args=(logentry.pk,))
|
notify.apply_async(args=(logentry.pk,))
|
||||||
if wh_type:
|
if logentry.webhook_type:
|
||||||
notify_webhooks.apply_async(args=(logentry.pk,))
|
notify_webhooks.apply_async(args=(logentry.pk,))
|
||||||
|
|
||||||
return logentry
|
return logentry
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -63,14 +63,42 @@ class LogEntry(models.Model):
|
|||||||
return response
|
return response
|
||||||
return self.action_type
|
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
|
@cached_property
|
||||||
def organizer(self):
|
def organizer(self):
|
||||||
|
from .organizer import Organizer
|
||||||
|
|
||||||
if self.event:
|
if self.event:
|
||||||
return self.event.organizer
|
return self.event.organizer
|
||||||
elif hasattr(self.content_object, 'event'):
|
elif hasattr(self.content_object, 'event'):
|
||||||
return self.content_object.event.organizer
|
return self.content_object.event.organizer
|
||||||
elif hasattr(self.content_object, 'organizer'):
|
elif hasattr(self.content_object, 'organizer'):
|
||||||
return self.content_object.organizer
|
return self.content_object.organizer
|
||||||
|
elif isinstance(self.content_object, Organizer):
|
||||||
|
return self.content_object
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@@ -188,3 +216,15 @@ class LogEntry(models.Model):
|
|||||||
|
|
||||||
def delete(self, using=None, keep_parents=False):
|
def delete(self, using=None, keep_parents=False):
|
||||||
raise TypeError("Logs cannot be deleted.")
|
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)
|
@app.task(base=TransactionAwareTask, acks_late=True)
|
||||||
@scopes_disabled()
|
@scopes_disabled()
|
||||||
def notify(logentry_id: int):
|
def notify(logentry_ids: list):
|
||||||
logentry = LogEntry.all.select_related('event', 'event__organizer').get(id=logentry_id)
|
if not isinstance(logentry_ids, list):
|
||||||
if not logentry.event:
|
logentry_ids = [logentry_ids]
|
||||||
return # Ignore, we only have event-related notifications right now
|
|
||||||
types = get_all_notification_types(logentry.event)
|
|
||||||
|
|
||||||
notification_type = None
|
qs = LogEntry.all.select_related('event', 'event__organizer').filter(id__in=logentry_ids)
|
||||||
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]
|
|
||||||
|
|
||||||
if not notification_type:
|
_event, _at, notify_specific, notify_global = None, None, None, None
|
||||||
return # No suitable plugin
|
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
|
notification_type = logentry.notification_type
|
||||||
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)
|
|
||||||
|
|
||||||
# Get all notification settings, both specific to this event as well as global
|
if not notification_type:
|
||||||
notify_specific = {
|
break # No suitable plugin
|
||||||
(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():
|
if _event != logentry.event or _at != logentry.action_type or notify_global is None:
|
||||||
user, method = um
|
_event = logentry.event
|
||||||
if enabled:
|
_at = logentry.action_type
|
||||||
send_notification.apply_async(args=(logentry_id, notification_type.action_type, user.pk, method))
|
# 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():
|
# Get all notification settings, both specific to this event as well as global
|
||||||
user, method = um
|
notify_specific = {
|
||||||
if enabled and um not in notify_specific:
|
(ns.user, ns.method): ns.enabled
|
||||||
send_notification.apply_async(args=(logentry_id, notification_type.action_type, user.pk, method))
|
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)
|
@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 dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY, rrule, rruleset
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.files import File
|
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 import F, IntegerField, OuterRef, Prefetch, Subquery, Sum
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
from django.forms import inlineformset_factory
|
from django.forms import inlineformset_factory
|
||||||
@@ -863,7 +863,13 @@ class SubEventBulkCreate(SubEventEditorMixin, EventPermissionRequiredMixin, Crea
|
|||||||
f.subevent = se
|
f.subevent = se
|
||||||
f.save()
|
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()
|
self.request.event.cache.clear()
|
||||||
messages.success(self.request, pgettext_lazy('subevent', '{} new dates have been created.').format(len(subevents)))
|
messages.success(self.request, pgettext_lazy('subevent', '{} new dates have been created.').format(len(subevents)))
|
||||||
|
|||||||
Reference in New Issue
Block a user