From 5781ddfe4dccc3cb05cf35413e7d7c3ce8efb1f5 Mon Sep 17 00:00:00 2001 From: someposer Date: Sun, 5 Nov 2017 19:10:19 -0600 Subject: [PATCH] Created an improved interface for arbitrary headers and simplified header storage. --- hc/api/tests/test_notify.py | 4 +-- hc/api/transports.py | 2 +- hc/front/forms.py | 16 +++++++++-- hc/front/tests/test_add_webhook.py | 12 ++++----- hc/front/views.py | 5 +++- static/js/webhook.js | 26 ++++++++++++++++++ templates/integrations/add_webhook.html | 36 ++++++++++++++++++------- 7 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 static/js/webhook.js diff --git a/hc/api/tests/test_notify.py b/hc/api/tests/test_notify.py index 48627710..ce1c0565 100644 --- a/hc/api/tests/test_notify.py +++ b/hc/api/tests/test_notify.py @@ -174,8 +174,8 @@ class NotifyTestCase(BaseTestCase): @patch("hc.api.transports.requests.request") def test_webhooks_handle_headers(self, mock_request): self._setup_data("webhook", '{"url_down": "http://foo.com", ' - '"url_up": "", "post_data": "data", "headers": ' - '"{\\\"Content-Type\\\": \\\"application/json\\\"}"}') + '"url_up": "", "post_data": "data", ' + '"headers": {"Content-Type": "application/json"}}') self.channel.notify(self.check) headers = { diff --git a/hc/api/transports.py b/hc/api/transports.py index aeaac2e7..68ae002e 100644 --- a/hc/api/transports.py +++ b/hc/api/transports.py @@ -167,7 +167,7 @@ class Webhook(HttpTransport): payload = self.prepare(self.channel.post_data, check) headers = {} if self.channel.headers: - headers = json.loads(self.channel.headers) + headers = self.channel.headers return self.post(url, data=payload.encode("utf-8"), headers=headers) else: return self.get(url) diff --git a/hc/front/forms.py b/hc/front/forms.py index babae8b0..3308787b 100644 --- a/hc/front/forms.py +++ b/hc/front/forms.py @@ -66,10 +66,22 @@ class AddWebhookForm(forms.Form): post_data = forms.CharField(max_length=1000, required=False) - headers = forms.CharField(max_length=1000, required=False) + def __init__(self, *args, **kwargs): + self.headers = {} + if all(k in kwargs for k in ("header_keys", "header_values")): + header_keys = kwargs.pop("header_keys") + header_values = kwargs.pop("header_values") + + for i, (key, val) in enumerate(zip(header_keys, header_values)): + if key: + self.headers[key] = val + + super(AddWebhookForm, self).__init__(*args, **kwargs) def get_value(self): - return json.dumps(self.cleaned_data, sort_keys=True) + val = dict(self.cleaned_data) + val["headers"] = self.headers + return json.dumps(val, sort_keys=True) phone_validator = RegexValidator(regex='^\+\d{5,15}$', diff --git a/hc/front/tests/test_add_webhook.py b/hc/front/tests/test_add_webhook.py index 5db65e86..744f5686 100644 --- a/hc/front/tests/test_add_webhook.py +++ b/hc/front/tests/test_add_webhook.py @@ -18,7 +18,7 @@ class AddWebhookTestCase(BaseTestCase): self.assertRedirects(r, "/integrations/") c = Channel.objects.get() - self.assertEqual(c.value, '{"headers": "", "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}') + self.assertEqual(c.value, '{"headers": {}, "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}') def test_it_adds_webhook_using_team_access(self): form = {"url_down": "http://foo.com", "url_up": "https://bar.com"} @@ -30,7 +30,7 @@ class AddWebhookTestCase(BaseTestCase): c = Channel.objects.get() self.assertEqual(c.user, self.alice) - self.assertEqual(c.value, '{"headers": "", "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}') + self.assertEqual(c.value, '{"headers": {}, "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}') def test_it_rejects_bad_urls(self): urls = [ @@ -59,7 +59,7 @@ class AddWebhookTestCase(BaseTestCase): self.client.post(self.url, form) c = Channel.objects.get() - self.assertEqual(c.value, '{"headers": "", "post_data": "", "url_down": "", "url_up": "http://foo.com"}') + self.assertEqual(c.value, '{"headers": {}, "post_data": "", "url_down": "", "url_up": "http://foo.com"}') def test_it_adds_post_data(self): form = {"url_down": "http://foo.com", "post_data": "hello"} @@ -69,15 +69,15 @@ class AddWebhookTestCase(BaseTestCase): self.assertRedirects(r, "/integrations/") c = Channel.objects.get() - self.assertEqual(c.value, '{"headers": "", "post_data": "hello", "url_down": "http://foo.com", "url_up": ""}') + self.assertEqual(c.value, '{"headers": {}, "post_data": "hello", "url_down": "http://foo.com", "url_up": ""}') def test_it_adds_headers(self): - form = {"url_down": "http://foo.com", "headers": '{"test": "123"}'} + form = {"url_down": "http://foo.com", "header_key[]": ["test", "test2"], "header_value[]": ["123", "abc"]} self.client.login(username="alice@example.org", password="password") r = self.client.post(self.url, form) self.assertRedirects(r, "/integrations/") c = Channel.objects.get() - self.assertEqual(c.value, '{"headers": "{\\\"test\\\": \\\"123\\\"}", "post_data": "", "url_down": "http://foo.com", "url_up": ""}') + self.assertEqual(c.value, '{"headers": {"test": "123", "test2": "abc"}, "post_data": "", "url_down": "http://foo.com", "url_up": ""}') diff --git a/hc/front/views.py b/hc/front/views.py index 22853577..972ef126 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -437,7 +437,10 @@ def add_email(request): @login_required def add_webhook(request): if request.method == "POST": - form = AddWebhookForm(request.POST) + header_keys = request.POST.getlist('header_key[]') + header_values = request.POST.getlist('header_value[]') + form = AddWebhookForm(request.POST or None, + header_keys=header_keys, header_values=header_values) if form.is_valid(): channel = Channel(user=request.team.user, kind="webhook") channel.value = form.get_value() diff --git a/static/js/webhook.js b/static/js/webhook.js new file mode 100644 index 00000000..7a07435e --- /dev/null +++ b/static/js/webhook.js @@ -0,0 +1,26 @@ +$(function() { + $("#webhook_headers").on("click", ".webhook_header_btn.btn-danger", function(e) { + e.preventDefault(); + $(this).closest("div.row").remove(); + }); + + $("#webhook_headers").on("click", ".webhook_header_btn.btn-info", function(e) { + e.preventDefault(); + + // Add new header form + $("#webhook_headers").append( +'
\ +
\ + \ +
\ +
\ +
\ + \ + \ + \ + \ +
\ +
\ +
'); + }); +}); \ No newline at end of file diff --git a/templates/integrations/add_webhook.html b/templates/integrations/add_webhook.html index 1aacfee0..c9d3c338 100644 --- a/templates/integrations/add_webhook.html +++ b/templates/integrations/add_webhook.html @@ -106,20 +106,28 @@
- -
- Headers +
+
+
+ +
+
+
+ + + + +
+
+
+
+ - {% if form.headers.errors %} -
- {{ form.headers.errors|join:"" }} -
- {% endif %} -
+
@@ -130,3 +138,11 @@
{% endblock %} + +{% block scripts %} +{% compress js %} + + + +{% endcompress %} +{% endblock %}