Browse Source

Validate HTTP header names in the "Add Webhook" form.

pull/163/head
Pēteris Caune 7 years ago
parent
commit
55d6471156
5 changed files with 69 additions and 30 deletions
  1. +20
    -5
      hc/front/forms.py
  2. +17
    -2
      hc/front/tests/test_add_webhook.py
  3. +4
    -0
      static/css/add_webhook.css
  4. +1
    -0
      templates/base.html
  5. +27
    -23
      templates/integrations/add_webhook.html

+ 20
- 5
hc/front/forms.py View File

@ -1,5 +1,6 @@
import json
from datetime import timedelta as td
import json
import re
from django import forms
from django.core.validators import RegexValidator
@ -55,28 +56,42 @@ class AddUrlForm(forms.Form):
value = forms.URLField(max_length=1000, validators=[WebhookValidator()])
_valid_header_name = re.compile(r'\A[^:\s][^:\r\n]*\Z').match
class AddWebhookForm(forms.Form):
error_css_class = "has-error"
url_down = forms.URLField(max_length=1000, required=False,
validators=[WebhookValidator()])
validators=[WebhookValidator()])
url_up = forms.URLField(max_length=1000, required=False,
validators=[WebhookValidator()])
validators=[WebhookValidator()])
post_data = forms.CharField(max_length=1000, required=False)
def __init__(self, *args, **kwargs):
super(AddWebhookForm, self).__init__(*args, **kwargs)
self.invalid_header_names = set()
self.headers = {}
if "header_key[]" in self.data and "header_value[]" in self.data:
keys = self.data.getlist("header_key[]")
values = self.data.getlist("header_value[]")
for key, value in zip(keys, values):
if key:
self.headers[key] = value
if not key:
continue
if not _valid_header_name(key):
self.invalid_header_names.add(key)
self.headers[key] = value
def clean(self):
if self.invalid_header_names:
raise forms.ValidationError("Invalid header names")
return self.cleaned_data
def get_value(self):
val = dict(self.cleaned_data)


+ 17
- 2
hc/front/tests/test_add_webhook.py View File

@ -72,12 +72,27 @@ class AddWebhookTestCase(BaseTestCase):
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", "header_key[]": ["test", "test2"], "header_value[]": ["123", "abc"]}
form = {
"url_down": "http://foo.com",
"header_key[]": ["test", "test2"],
"header_value[]": ["123", "abc"]
}
self.client.login(username="[email protected]", password="password")
r = self.client.post(self.url, form)
self.assertRedirects(r, "/integrations/")
c = Channel.objects.get()
self.assertEqual(c.value, '{"headers": {"test": "123", "test2": "abc"}, "post_data": "", "url_down": "http://foo.com", "url_up": ""}')
self.assertEqual(c.headers, {"test": "123", "test2": "abc"})
def test_it_rejects_bad_header_names(self):
self.client.login(username="[email protected]", password="password")
form = {
"url_down": "http://example.org",
"header_key[]": ["ill:egal"],
"header_value[]": ["123"]
}
r = self.client.post(self.url, form)
self.assertContains(r, "Please use valid HTTP header names.")
self.assertEqual(Channel.objects.count(), 0)

+ 4
- 0
static/css/add_webhook.css View File

@ -0,0 +1,4 @@
.webhook-header .error {
border-color: #a94442;
}

+ 1
- 0
templates/base.html View File

@ -34,6 +34,7 @@
<link rel="stylesheet" href="{% static 'css/channel_checks.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/log.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/add_pushover.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/add_webhook.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/settings.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/last_ping.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/profile.css' %}" type="text/css">


+ 27
- 23
templates/integrations/add_webhook.html View File

@ -105,32 +105,36 @@
{% endif %}
</div>
</div>
<div class="form-group {{ form.headers.css_classes }}">
<div class="form-group">
<label class="col-sm-2 control-label">Request Headers</label>
<div id="webhook-headers" class="col-xs-12 col-sm-10">
{% for k, v in form.headers.items %}
<div class="form-inline webhook-header">
<input
type="text"
class="form-control key"
name="header_key[]"
placeholder="Content-Type"
value="{{ k }}" />
<input
type="text"
class="form-control value"
name="header_value[]"
placeholder="application/json"
value="{{ v }}" />
<button class="btn btn-default" type="button">
<span class="icon-delete"></span>
</button>
<div class="col-xs-12 col-sm-10">
<div id="webhook-headers">
{% for k, v in form.headers.items %}
<div class="form-inline webhook-header">
<input
type="text"
class="form-control key {% if k in form.invalid_header_names %}error{% endif %}"
name="header_key[]"
placeholder="Content-Type"
value="{{ k }}" />
<input
type="text"
class="form-control value"
name="header_value[]"
placeholder="application/json"
value="{{ v }}" />
<button class="btn btn-default" type="button">
<span class="icon-delete"></span>
</button>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
<div class="text-center">
{% if form.invalid_header_names %}
<div class="text-danger">
Please use valid HTTP header names.
</div>
{% endif %}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">


Loading…
Cancel
Save