| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- import time
- from importlib import import_module
- from django.db.models.signals import post_save, post_delete
- from django.conf import settings
- from django.core.cache import caches
- from django.db.models import Q
- from django.dispatch import Signal
- from django.contrib.contenttypes.models import ContentType
- from utilities.utils import dynamic_import
- from extras.models import Webhook
- def enqueue_webhooks(webhooks, model_class, data, event, signal_received_timestamp):
- """
- Serialize data and enqueue webhooks
- """
- serializer_context = {
- 'request': None,
- }
- if isinstance(data, list):
- serializer_property = data[0].serializer
- serializer_cls = dynamic_import(serializer_property)
- serialized_data = serializer_cls(data, context=serializer_context, many=True)
- else:
- serializer_property = data.serializer
- serializer_cls = dynamic_import(serializer_property)
- serialized_data = serializer_cls(data, context=serializer_context)
- from django_rq import get_queue
- webhook_queue = get_queue('default')
- for webhook in webhooks:
- webhook_queue.enqueue("extras.webhooks_worker.process_webhook",
- webhook,
- serialized_data.data,
- model_class,
- event,
- signal_received_timestamp)
- def post_save_receiver(sender, instance, created, **kwargs):
- """
- Receives post_save signals from registered models. If the webhook
- backend is enabled, queue any webhooks that apply to the event.
- """
- if settings.WEBHOOKS_ENABLED:
- signal_received_timestamp = time.time()
- # look for any webhooks that match this event
- updated = not created
- obj_type = ContentType.objects.get_for_model(sender)
- webhooks = Webhook.objects.filter(
- Q(enabled=True) &
- (
- Q(type_create=created) |
- Q(type_update=updated)
- ) &
- Q(obj_type=obj_type)
- )
- event = 'created' if created else 'updated'
- if webhooks:
- enqueue_webhooks(webhooks, sender, instance, event, signal_received_timestamp)
- def post_delete_receiver(sender, instance, **kwargs):
- """
- Receives post_delete signals from registered models. If the webhook
- backend is enabled, queue any webhooks that apply to the event.
- """
- if settings.WEBHOOKS_ENABLED:
- signal_received_timestamp = time.time()
- obj_type = ContentType.objects.get_for_model(sender)
- # look for any webhooks that match this event
- webhooks = Webhook.objects.filter(enabled=True, type_delete=True, obj_type=obj_type)
- if webhooks:
- enqueue_webhooks(webhooks, sender, instance, 'deleted', signal_received_timestamp)
- def bulk_operation_receiver(sender, **kwargs):
- """
- Receives bulk_operation_signal signals from registered models. If the webhook
- backend is enabled, queue any webhooks that apply to the event.
- """
- if settings.WEBHOOKS_ENABLED:
- signal_received_timestamp = time.time()
- event = kwargs['event']
- obj_type = ContentType.objects.get_for_model(sender)
- # look for any webhooks that match this event
- if event == 'created':
- webhooks = Webhook.objects.filter(enabled=True, type_create=True, obj_type=obj_type)
- elif event == 'updated':
- webhooks = Webhook.objects.filter(enabled=True, type_update=True, obj_type=obj_type)
- elif event == 'deleted':
- webhooks = Webhook.objects.filter(enabled=True, type_delete=True, obj_type=obj_type)
- else:
- webhooks = None
- if webhooks:
- enqueue_webhooks(webhooks, sender, list(kwargs['instances']), event, signal_received_timestamp)
- # the bulk operation signal is used to overcome signals not being sent for bulk model changes
- bulk_operation_signal = Signal(providing_args=["instances", "event"])
- bulk_operation_signal.connect(bulk_operation_receiver)
- def register_signals(senders):
- """
- Take a list of senders (Models) and register them to the post_save
- and post_delete signal receivers.
- """
- if settings.WEBHOOKS_ENABLED:
- # only register signals if the backend is enabled
- # this reduces load by not firing signals if the
- # webhook backend feature is disabled
- for sender in senders:
- post_save.connect(post_save_receiver, sender=sender)
- post_delete.connect(post_delete_receiver, sender=sender)
|