Files
django-anymail/djrill/views.py
medmunds 99ac099081 Remove DjrillAdminSite
Closes #78
2015-05-14 11:00:52 -07:00

84 lines
3.1 KiB
Python

from base64 import b64encode
import hashlib
import hmac
import json
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.views.generic import View
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from djrill import signals
from djrill.compat import b
class DjrillWebhookSecretMixin(object):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
secret = getattr(settings, 'DJRILL_WEBHOOK_SECRET', None)
secret_name = getattr(settings, 'DJRILL_WEBHOOK_SECRET_NAME', 'secret')
if secret is None:
raise ImproperlyConfigured(
"You have not set DJRILL_WEBHOOK_SECRET in the settings file.")
if request.GET.get(secret_name) != secret:
return HttpResponse(status=403)
return super(DjrillWebhookSecretMixin, self).dispatch(
request, *args, **kwargs)
class DjrillWebhookSignatureMixin(object):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
signature_key = getattr(settings, 'DJRILL_WEBHOOK_SIGNATURE_KEY', None)
if signature_key and request.method == "POST":
# Make webhook url an explicit setting to make sure that this is the exact same string
# that the user entered in Mandrill
post_string = getattr(settings, "DJRILL_WEBHOOK_URL", None)
if post_string is None:
raise ImproperlyConfigured(
"You have set DJRILL_WEBHOOK_SIGNATURE_KEY, but haven't set DJRILL_WEBHOOK_URL in the settings file.")
signature = request.META.get("HTTP_X_MANDRILL_SIGNATURE", None)
if not signature:
return HttpResponse(status=403, content="X-Mandrill-Signature not set")
# The querydict is a bit special, see https://docs.djangoproject.com/en/dev/ref/request-response/#querydict-objects
# Mandrill needs it to be sorted and added to the hash
post_lists = sorted(request.POST.lists())
for value_list in post_lists:
for item in value_list[1]:
post_string += "%s%s" % (value_list[0], item)
hash_string = b64encode(hmac.new(key=b(signature_key), msg=b(post_string), digestmod=hashlib.sha1).digest())
if signature != hash_string:
return HttpResponse(status=403, content="Signature doesn't match")
return super(DjrillWebhookSignatureMixin, self).dispatch(
request, *args, **kwargs)
class DjrillWebhookView(DjrillWebhookSecretMixin, DjrillWebhookSignatureMixin, View):
def head(self, request, *args, **kwargs):
return HttpResponse()
def post(self, request, *args, **kwargs):
try:
data = json.loads(request.POST.get('mandrill_events'))
except TypeError:
return HttpResponse(status=400)
for event in data:
signals.webhook_event.send(
sender=None, event_type=event['event'], data=event)
return HttpResponse()