webhooks.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  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 extras.models import Webhook
  7. from utilities.api import get_serializer_for_model
  8. from .choices import *
  9. from .utils import FeatureQuery
  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. obj_type = ContentType.objects.get_for_model(instance.__class__)
  26. webhook_models = ContentType.objects.filter(FeatureQuery('webhooks').get_query())
  27. if obj_type not in webhook_models:
  28. return
  29. # Retrieve any applicable Webhooks
  30. action_flag = {
  31. ObjectChangeActionChoices.ACTION_CREATE: 'type_create',
  32. ObjectChangeActionChoices.ACTION_UPDATE: 'type_update',
  33. ObjectChangeActionChoices.ACTION_DELETE: 'type_delete',
  34. }[action]
  35. webhooks = Webhook.objects.filter(obj_type=obj_type, enabled=True, **{action_flag: True})
  36. if webhooks.exists():
  37. # Get the Model's API serializer class and serialize the object
  38. serializer_class = get_serializer_for_model(instance.__class__)
  39. serializer_context = {
  40. 'request': None,
  41. }
  42. serializer = serializer_class(instance, context=serializer_context)
  43. # Enqueue the webhooks
  44. webhook_queue = get_queue('default')
  45. for webhook in webhooks:
  46. webhook_queue.enqueue(
  47. "extras.webhooks_worker.process_webhook",
  48. webhook,
  49. serializer.data,
  50. instance._meta.model_name,
  51. action,
  52. str(timezone.now()),
  53. user.username,
  54. request_id
  55. )