webhooks.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import hashlib
  2. import hmac
  3. from django.contrib.contenttypes.models import ContentType
  4. from django.utils import timezone
  5. from django_rq import get_queue
  6. from utilities.api import get_serializer_for_model
  7. from .choices import *
  8. from .models import Webhook
  9. from .registry import registry
  10. def generate_signature(request_body, secret):
  11. """
  12. Return a cryptographic signature that can be used to verify the authenticity of webhook data.
  13. """
  14. hmac_prep = hmac.new(
  15. key=secret.encode('utf8'),
  16. msg=request_body,
  17. digestmod=hashlib.sha512
  18. )
  19. return hmac_prep.hexdigest()
  20. def enqueue_webhooks(instance, user, request_id, action):
  21. """
  22. Find Webhook(s) assigned to this instance + action and enqueue them
  23. to be processed
  24. """
  25. # Determine whether this type of object supports webhooks
  26. app_label = instance._meta.app_label
  27. model_name = instance._meta.model_name
  28. if model_name not in registry['model_features']['webhooks'].get(app_label, []):
  29. return
  30. # Retrieve any applicable Webhooks
  31. obj_type = ContentType.objects.get_for_model(instance)
  32. action_flag = {
  33. ObjectChangeActionChoices.ACTION_CREATE: 'type_create',
  34. ObjectChangeActionChoices.ACTION_UPDATE: 'type_update',
  35. ObjectChangeActionChoices.ACTION_DELETE: 'type_delete',
  36. }[action]
  37. webhooks = Webhook.objects.filter(obj_type=obj_type, enabled=True, **{action_flag: True})
  38. if webhooks.exists():
  39. # Get the Model's API serializer class and serialize the object
  40. serializer_class = get_serializer_for_model(instance.__class__)
  41. serializer_context = {
  42. 'request': None,
  43. }
  44. serializer = serializer_class(instance, context=serializer_context)
  45. # Enqueue the webhooks
  46. webhook_queue = get_queue('default')
  47. for webhook in webhooks:
  48. webhook_queue.enqueue(
  49. "extras.webhooks_worker.process_webhook",
  50. webhook,
  51. serializer.data,
  52. instance._meta.model_name,
  53. action,
  54. str(timezone.now()),
  55. user.username,
  56. request_id
  57. )