Add webhook handler

This commit is contained in:
José Padilla
2013-04-11 14:57:53 -04:00
parent 717e048365
commit c60a7c666f
3 changed files with 66 additions and 17 deletions

5
djrill/signals.py Normal file
View File

@@ -0,0 +1,5 @@
from django.dispatch import Signal
webhook_verify = Signal()
webhook_event = Signal(providing_args=['event_type', 'data'])

View File

@@ -0,0 +1,13 @@
try:
from django.conf.urls import patterns, url
except ImportError:
from django.conf.urls.defaults import patterns, url
from .views import DjrillWebhookView
urlpatterns = patterns(
'',
url(r'^webhook/$', DjrillWebhookView.as_view(), name='djrill_webhook'),
)

View File

@@ -4,19 +4,21 @@ from django import forms
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.views.generic import TemplateView from django.views.generic import TemplateView, View
from django.http import HttpResponse
from djrill import MANDRILL_API_URL from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
import requests import requests
from djrill import MANDRILL_API_URL, signals
class DjrillAdminMedia(object): class DjrillAdminMedia(object):
def _media(self): def _media(self):
js = ["js/core.js", "js/jquery.min.js", "js/jquery.init.js"] js = ["js/core.js", "js/jquery.min.js", "js/jquery.init.js"]
return forms.Media(js=["%s%s" % (settings.STATIC_URL, url) return forms.Media(js=["%s%s" % (settings.STATIC_URL, url) for url in js])
for url in js])
media = property(_media) media = property(_media)
@@ -29,15 +31,15 @@ class DjrillApiMixin(object):
self.api_url = MANDRILL_API_URL self.api_url = MANDRILL_API_URL
if not self.api_key: if not self.api_key:
raise ImproperlyConfigured("You have not set your mandrill api key " raise ImproperlyConfigured("You have not set your mandrill \
"in the settings file.") api key in the settings file.")
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(DjrillApiMixin, self).get_context_data(**kwargs) kwargs = super(DjrillApiMixin, self).get_context_data(**kwargs)
status = False status = False
req = requests.post("%s/%s" % (self.api_url, "users/ping.json"), req = requests.post("%s/%s" % (self.api_url, "users/ping.json"),
data={"key": self.api_key}) data={"key": self.api_key})
if req.status_code == 200: if req.status_code == 200:
status = True status = True
@@ -53,10 +55,11 @@ class DjrillApiJsonObjectsMixin(object):
def get_api_uri(self): def get_api_uri(self):
if self.api_uri is None: if self.api_uri is None:
raise NotImplementedError("%(cls)s is missing an api_uri. Define " raise NotImplementedError("%(cls)s is missing an api_uri. Define \
"%(cls)s.api_uri or override %(cls)s.get_api_uri()." % { %(cls)s.api_uri or override \
"cls": self.__class__.__name__ %(cls)s.get_api_uri()." % {
}) "cls": self.__class__.__name__
})
def get_json_objects(self, extra_dict=None, extra_api_uri=None): def get_json_objects(self, extra_dict=None, extra_api_uri=None):
request_dict = {"key": self.api_key} request_dict = {"key": self.api_key}
@@ -65,7 +68,7 @@ class DjrillApiJsonObjectsMixin(object):
payload = json.dumps(request_dict) payload = json.dumps(request_dict)
api_uri = extra_api_uri or self.api_uri api_uri = extra_api_uri or self.api_uri
req = requests.post("%s/%s" % (self.api_url, api_uri), req = requests.post("%s/%s" % (self.api_url, api_uri),
data=payload) data=payload)
if req.status_code == 200: if req.status_code == 200:
return req.content return req.content
messages.error(self.request, self._api_error_handler(req)) messages.error(self.request, self._api_error_handler(req))
@@ -77,7 +80,20 @@ class DjrillApiJsonObjectsMixin(object):
""" """
content = json.loads(req.content) content = json.loads(req.content)
return "Mandrill returned a %d response: %s" % (req.status_code, return "Mandrill returned a %d response: %s" % (req.status_code,
content["message"]) content["message"])
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 request.GET.get(secret_name) != secret:
return HttpResponse(status=403)
return super(DjrillWebhookSecretMixin, self).dispatch(request, *args, **kwargs)
class DjrillIndexView(DjrillApiMixin, TemplateView): class DjrillIndexView(DjrillApiMixin, TemplateView):
@@ -92,7 +108,7 @@ class DjrillIndexView(DjrillApiMixin, TemplateView):
class DjrillSendersListView(DjrillAdminMedia, DjrillApiMixin, class DjrillSendersListView(DjrillAdminMedia, DjrillApiMixin,
DjrillApiJsonObjectsMixin, TemplateView): DjrillApiJsonObjectsMixin, TemplateView):
api_uri = "users/senders.json" api_uri = "users/senders.json"
template_name = "djrill/senders_list.html" template_name = "djrill/senders_list.html"
@@ -109,7 +125,7 @@ class DjrillSendersListView(DjrillAdminMedia, DjrillApiMixin,
class DjrillTagListView(DjrillAdminMedia, DjrillApiMixin, class DjrillTagListView(DjrillAdminMedia, DjrillApiMixin,
DjrillApiJsonObjectsMixin, TemplateView): DjrillApiJsonObjectsMixin, TemplateView):
api_uri = "tags/list.json" api_uri = "tags/list.json"
template_name = "djrill/tags_list.html" template_name = "djrill/tags_list.html"
@@ -125,7 +141,7 @@ class DjrillTagListView(DjrillAdminMedia, DjrillApiMixin,
class DjrillUrlListView(DjrillAdminMedia, DjrillApiMixin, class DjrillUrlListView(DjrillAdminMedia, DjrillApiMixin,
DjrillApiJsonObjectsMixin, TemplateView): DjrillApiJsonObjectsMixin, TemplateView):
api_uri = "urls/list.json" api_uri = "urls/list.json"
template_name = "djrill/urls_list.html" template_name = "djrill/urls_list.html"
@@ -138,3 +154,18 @@ class DjrillUrlListView(DjrillAdminMedia, DjrillApiMixin,
"media": self.media "media": self.media
}) })
return self.render_to_response(context) return self.render_to_response(context)
class DjrillWebhookView(DjrillWebhookSecretMixin, View):
def head(self, request, *args, **kwargs):
signals.webhook_verify.send()
return HttpResponse()
def post(self, request, *args, **kwargs):
data = json.loads(request.body)
for event in data:
signals.webhook_event.send(
sender=None, event_type=event['event'], data=event)
return HttpResponse()