forked from GithubBackups/healthchecks
Validate channel values. Don't allow ftp addresses, http://localhost addresses, invalid email addresses
This commit is contained in:
parent
fa63c9034e
commit
ac4ba079d3
@ -21,9 +21,13 @@ STATUSES = (
|
||||
)
|
||||
DEFAULT_TIMEOUT = td(days=1)
|
||||
DEFAULT_GRACE = td(hours=1)
|
||||
CHANNEL_KINDS = (("email", "Email"), ("webhook", "Webhook"),
|
||||
CHANNEL_KINDS = (("email", "Email"),
|
||||
("webhook", "Webhook"),
|
||||
("hipchat", "HipChat"),
|
||||
("slack", "Slack"), ("pd", "PagerDuty"), ("po", "Pushover"),
|
||||
("slack", "Slack"),
|
||||
("pd", "PagerDuty"),
|
||||
("po", "Pushover"),
|
||||
("pushbullet", "Pushbullet"),
|
||||
("victorops", "VictorOps"))
|
||||
|
||||
PO_PRIORITIES = {
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from hc.front.validators import WebhookValidator
|
||||
from hc.api.models import Channel
|
||||
|
||||
|
||||
@ -7,14 +8,14 @@ class NameTagsForm(forms.Form):
|
||||
tags = forms.CharField(max_length=500, required=False)
|
||||
|
||||
def clean_tags(self):
|
||||
l = []
|
||||
result = []
|
||||
|
||||
for part in self.cleaned_data["tags"].split(" "):
|
||||
part = part.strip()
|
||||
if part != "":
|
||||
l.append(part)
|
||||
result.append(part)
|
||||
|
||||
return " ".join(l)
|
||||
return " ".join(result)
|
||||
|
||||
|
||||
class TimeoutForm(forms.Form):
|
||||
@ -33,11 +34,29 @@ class AddChannelForm(forms.ModelForm):
|
||||
return value.strip()
|
||||
|
||||
|
||||
class AddPdForm(forms.Form):
|
||||
error_css_class = "has-error"
|
||||
value = forms.CharField(max_length=20)
|
||||
|
||||
|
||||
class AddEmailForm(forms.Form):
|
||||
error_css_class = "has-error"
|
||||
value = forms.EmailField(max_length=100)
|
||||
|
||||
|
||||
class AddUrlForm(forms.Form):
|
||||
error_css_class = "has-error"
|
||||
value = forms.URLField(max_length=1000, validators=[WebhookValidator()])
|
||||
|
||||
|
||||
class AddWebhookForm(forms.Form):
|
||||
error_css_class = "has-error"
|
||||
|
||||
value_down = forms.URLField(max_length=1000, required=False)
|
||||
value_up = forms.URLField(max_length=1000, required=False)
|
||||
value_down = forms.URLField(max_length=1000, required=False,
|
||||
validators=[WebhookValidator()])
|
||||
|
||||
value_up = forms.URLField(max_length=1000, required=False,
|
||||
validators=[WebhookValidator()])
|
||||
|
||||
def get_value(self):
|
||||
return "{value_down}\n{value_up}".format(**self.cleaned_data)
|
||||
|
@ -1,58 +0,0 @@
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from hc.api.models import Channel
|
||||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
@override_settings(PUSHOVER_API_TOKEN="token", PUSHOVER_SUBSCRIPTION_URL="url")
|
||||
class AddChannelTestCase(BaseTestCase):
|
||||
|
||||
def test_it_adds_email(self):
|
||||
url = "/integrations/add/"
|
||||
form = {"kind": "email", "value": "alice@example.org"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post(url, form)
|
||||
|
||||
self.assertRedirects(r, "/integrations/")
|
||||
assert Channel.objects.count() == 1
|
||||
|
||||
def test_team_access_works(self):
|
||||
url = "/integrations/add/"
|
||||
form = {"kind": "email", "value": "bob@example.org"}
|
||||
|
||||
self.client.login(username="bob@example.org", password="password")
|
||||
self.client.post(url, form)
|
||||
|
||||
ch = Channel.objects.get()
|
||||
# Added by bob, but should belong to alice (bob has team access)
|
||||
self.assertEqual(ch.user, self.alice)
|
||||
|
||||
def test_it_trims_whitespace(self):
|
||||
""" Leading and trailing whitespace should get trimmed. """
|
||||
|
||||
url = "/integrations/add/"
|
||||
form = {"kind": "email", "value": " alice@example.org "}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
self.client.post(url, form)
|
||||
|
||||
q = Channel.objects.filter(value="alice@example.org")
|
||||
self.assertEqual(q.count(), 1)
|
||||
|
||||
def test_it_rejects_bad_kind(self):
|
||||
url = "/integrations/add/"
|
||||
form = {"kind": "dog", "value": "Lassie"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post(url, form)
|
||||
|
||||
assert r.status_code == 400, r.status_code
|
||||
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
kinds = ("email", "webhook", "pd", "pushover", "hipchat", "victorops")
|
||||
for frag in kinds:
|
||||
url = "/integrations/add_%s/" % frag
|
||||
r = self.client.get(url)
|
||||
self.assertContains(r, "Integration Settings", status_code=200)
|
49
hc/front/tests/test_add_email.py
Normal file
49
hc/front/tests/test_add_email.py
Normal file
@ -0,0 +1,49 @@
|
||||
from hc.api.models import Channel
|
||||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
class AddPdTestCase(BaseTestCase):
|
||||
url = "/integrations/add_email/"
|
||||
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(self.url)
|
||||
self.assertContains(r, "Get an email message")
|
||||
|
||||
def test_it_creates_channel(self):
|
||||
form = {"value": "alice@example.org"}
|
||||
|
||||
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.kind, "email")
|
||||
self.assertEqual(c.value, "alice@example.org")
|
||||
self.assertFalse(c.email_verified)
|
||||
|
||||
def test_team_access_works(self):
|
||||
form = {"value": "bob@example.org"}
|
||||
|
||||
self.client.login(username="bob@example.org", password="password")
|
||||
self.client.post(self.url, form)
|
||||
|
||||
ch = Channel.objects.get()
|
||||
# Added by bob, but should belong to alice (bob has team access)
|
||||
self.assertEqual(ch.user, self.alice)
|
||||
|
||||
def test_it_rejects_bad_email(self):
|
||||
form = {"value": "not an email address"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post(self.url, form)
|
||||
self.assertContains(r, "Enter a valid email address.")
|
||||
|
||||
def test_it_trims_whitespace(self):
|
||||
form = {"value": " alice@example.org "}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
self.client.post(self.url, form)
|
||||
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.value, "alice@example.org")
|
38
hc/front/tests/test_add_hipchat.py
Normal file
38
hc/front/tests/test_add_hipchat.py
Normal file
@ -0,0 +1,38 @@
|
||||
from hc.api.models import Channel
|
||||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
class AddHipChatTestCase(BaseTestCase):
|
||||
url = "/integrations/add_hipchat/"
|
||||
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(self.url)
|
||||
self.assertContains(r, "appropriate HipChat room")
|
||||
|
||||
def test_it_works(self):
|
||||
form = {"value": "http://example.org"}
|
||||
|
||||
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.kind, "hipchat")
|
||||
self.assertEqual(c.value, "http://example.org")
|
||||
|
||||
def test_it_rejects_bad_url(self):
|
||||
form = {"value": "not an URL"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post(self.url, form)
|
||||
self.assertContains(r, "Enter a valid URL")
|
||||
|
||||
def test_it_trims_whitespace(self):
|
||||
form = {"value": " http://example.org "}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
self.client.post(self.url, form)
|
||||
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.value, "http://example.org")
|
31
hc/front/tests/test_add_pd.py
Normal file
31
hc/front/tests/test_add_pd.py
Normal file
@ -0,0 +1,31 @@
|
||||
from hc.api.models import Channel
|
||||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
class AddPdTestCase(BaseTestCase):
|
||||
url = "/integrations/add_pd/"
|
||||
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(self.url)
|
||||
self.assertContains(r, "incident management system")
|
||||
|
||||
def test_it_works(self):
|
||||
form = {"value": "123456"}
|
||||
|
||||
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.kind, "pd")
|
||||
self.assertEqual(c.value, "123456")
|
||||
|
||||
def test_it_trims_whitespace(self):
|
||||
form = {"value": " 123456 "}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
self.client.post(self.url, form)
|
||||
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.value, "123456")
|
@ -5,6 +5,11 @@ from hc.test import BaseTestCase
|
||||
|
||||
@override_settings(PUSHOVER_API_TOKEN="token", PUSHOVER_SUBSCRIPTION_URL="url")
|
||||
class AddPushoverTestCase(BaseTestCase):
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get("/integrations/add_pushover/")
|
||||
self.assertContains(r, "Subscribe with Pushover")
|
||||
|
||||
def test_it_adds_channel(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
|
||||
|
@ -8,16 +8,22 @@ from mock import patch
|
||||
|
||||
@override_settings(PUSHBULLET_CLIENT_ID="t1", PUSHBULLET_CLIENT_SECRET="s1")
|
||||
class AddPushbulletTestCase(BaseTestCase):
|
||||
url = "/integrations/add_pushbullet/"
|
||||
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(self.url)
|
||||
self.assertContains(r, "Connect Pushbullet")
|
||||
|
||||
def test_it_shows_instructions(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get("/integrations/add_pushbullet/")
|
||||
r = self.client.get(self.url)
|
||||
self.assertContains(r, "www.pushbullet.com/authorize", status_code=200)
|
||||
|
||||
@override_settings(PUSHBULLET_CLIENT_ID=None)
|
||||
def test_it_requires_client_id(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get("/integrations/add_pushbullet/")
|
||||
r = self.client.get(self.url)
|
||||
self.assertEqual(r.status_code, 404)
|
||||
|
||||
@patch("hc.front.views.requests.post")
|
||||
@ -27,7 +33,7 @@ class AddPushbulletTestCase(BaseTestCase):
|
||||
mock_post.return_value.text = json.dumps(oauth_response)
|
||||
mock_post.return_value.json.return_value = oauth_response
|
||||
|
||||
url = "/integrations/add_pushbullet/?code=12345678"
|
||||
url = self.url + "?code=12345678"
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(url, follow=True)
|
||||
|
@ -1,70 +1,32 @@
|
||||
import json
|
||||
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from hc.api.models import Channel
|
||||
from hc.test import BaseTestCase
|
||||
from mock import patch
|
||||
|
||||
|
||||
class AddSlackTestCase(BaseTestCase):
|
||||
|
||||
@override_settings(SLACK_CLIENT_ID=None)
|
||||
def test_webhook_instructions_work(self):
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get("/integrations/add_slack/")
|
||||
self.assertContains(r, "Integration Settings", status_code=200)
|
||||
|
||||
@override_settings(SLACK_CLIENT_ID="foo")
|
||||
def test_slack_button(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get("/integrations/add_slack/")
|
||||
self.assertContains(r, "slack.com/oauth/authorize", status_code=200)
|
||||
|
||||
@override_settings(SLACK_CLIENT_ID="foo")
|
||||
def test_landing_page(self):
|
||||
r = self.client.get("/integrations/add_slack/")
|
||||
self.assertContains(r, "Before adding Slack integration",
|
||||
status_code=200)
|
||||
|
||||
@patch("hc.front.views.requests.post")
|
||||
def test_it_handles_oauth_response(self, mock_post):
|
||||
oauth_response = {
|
||||
"ok": True,
|
||||
"team_name": "foo",
|
||||
"incoming_webhook": {
|
||||
"url": "http://example.org",
|
||||
"channel": "bar"
|
||||
}
|
||||
}
|
||||
|
||||
mock_post.return_value.text = json.dumps(oauth_response)
|
||||
mock_post.return_value.json.return_value = oauth_response
|
||||
|
||||
url = "/integrations/add_slack_btn/?code=12345678"
|
||||
@override_settings(SLACK_CLIENT_ID=None)
|
||||
def test_it_works(self):
|
||||
form = {"value": "http://example.org"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(url, follow=True)
|
||||
r = self.client.post("/integrations/add_slack/", form)
|
||||
self.assertRedirects(r, "/integrations/")
|
||||
self.assertContains(r, "The Slack integration has been added!")
|
||||
|
||||
ch = Channel.objects.get()
|
||||
self.assertEqual(ch.slack_team, "foo")
|
||||
self.assertEqual(ch.slack_channel, "bar")
|
||||
self.assertEqual(ch.slack_webhook_url, "http://example.org")
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.kind, "slack")
|
||||
self.assertEqual(c.value, "http://example.org")
|
||||
|
||||
@patch("hc.front.views.requests.post")
|
||||
def test_it_handles_oauth_error(self, mock_post):
|
||||
oauth_response = {
|
||||
"ok": False,
|
||||
"error": "something went wrong"
|
||||
}
|
||||
|
||||
mock_post.return_value.text = json.dumps(oauth_response)
|
||||
mock_post.return_value.json.return_value = oauth_response
|
||||
|
||||
url = "/integrations/add_slack_btn/?code=12345678"
|
||||
@override_settings(SLACK_CLIENT_ID=None)
|
||||
def test_it_rejects_bad_url(self):
|
||||
form = {"value": "not an URL"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(url, follow=True)
|
||||
self.assertRedirects(r, "/integrations/")
|
||||
self.assertContains(r, "something went wrong")
|
||||
r = self.client.post("/integrations/add_slack/", form)
|
||||
self.assertContains(r, "Enter a valid URL")
|
||||
|
64
hc/front/tests/test_add_slack_btn.py
Normal file
64
hc/front/tests/test_add_slack_btn.py
Normal file
@ -0,0 +1,64 @@
|
||||
import json
|
||||
|
||||
from django.test.utils import override_settings
|
||||
from hc.api.models import Channel
|
||||
from hc.test import BaseTestCase
|
||||
from mock import patch
|
||||
|
||||
|
||||
class AddSlackBtnTestCase(BaseTestCase):
|
||||
|
||||
@override_settings(SLACK_CLIENT_ID="foo")
|
||||
def test_instructions_work(self):
|
||||
r = self.client.get("/integrations/add_slack/")
|
||||
self.assertContains(r, "Before adding Slack integration",
|
||||
status_code=200)
|
||||
|
||||
@override_settings(SLACK_CLIENT_ID="foo")
|
||||
def test_slack_button(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get("/integrations/add_slack/")
|
||||
self.assertContains(r, "slack.com/oauth/authorize", status_code=200)
|
||||
|
||||
@patch("hc.front.views.requests.post")
|
||||
def test_it_handles_oauth_response(self, mock_post):
|
||||
oauth_response = {
|
||||
"ok": True,
|
||||
"team_name": "foo",
|
||||
"incoming_webhook": {
|
||||
"url": "http://example.org",
|
||||
"channel": "bar"
|
||||
}
|
||||
}
|
||||
|
||||
mock_post.return_value.text = json.dumps(oauth_response)
|
||||
mock_post.return_value.json.return_value = oauth_response
|
||||
|
||||
url = "/integrations/add_slack_btn/?code=12345678"
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(url, follow=True)
|
||||
self.assertRedirects(r, "/integrations/")
|
||||
self.assertContains(r, "The Slack integration has been added!")
|
||||
|
||||
ch = Channel.objects.get()
|
||||
self.assertEqual(ch.slack_team, "foo")
|
||||
self.assertEqual(ch.slack_channel, "bar")
|
||||
self.assertEqual(ch.slack_webhook_url, "http://example.org")
|
||||
|
||||
@patch("hc.front.views.requests.post")
|
||||
def test_it_handles_oauth_error(self, mock_post):
|
||||
oauth_response = {
|
||||
"ok": False,
|
||||
"error": "something went wrong"
|
||||
}
|
||||
|
||||
mock_post.return_value.text = json.dumps(oauth_response)
|
||||
mock_post.return_value.json.return_value = oauth_response
|
||||
|
||||
url = "/integrations/add_slack_btn/?code=12345678"
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(url, follow=True)
|
||||
self.assertRedirects(r, "/integrations/")
|
||||
self.assertContains(r, "something went wrong")
|
29
hc/front/tests/test_add_victorops.py
Normal file
29
hc/front/tests/test_add_victorops.py
Normal file
@ -0,0 +1,29 @@
|
||||
from hc.api.models import Channel
|
||||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
class AddVictorOpsTestCase(BaseTestCase):
|
||||
url = "/integrations/add_victorops/"
|
||||
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(self.url)
|
||||
self.assertContains(r, "incident management system")
|
||||
|
||||
def test_it_works(self):
|
||||
form = {"value": "http://example.org"}
|
||||
|
||||
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.kind, "victorops")
|
||||
self.assertEqual(c.value, "http://example.org")
|
||||
|
||||
def test_it_rejects_bad_url(self):
|
||||
form = {"value": "not an URL"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post(self.url, form)
|
||||
self.assertContains(r, "Enter a valid URL")
|
@ -3,12 +3,18 @@ from hc.test import BaseTestCase
|
||||
|
||||
|
||||
class AddWebhookTestCase(BaseTestCase):
|
||||
url = "/integrations/add_webhook/"
|
||||
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(self.url)
|
||||
self.assertContains(r, "Webhooks are a simple way")
|
||||
|
||||
def test_it_adds_two_webhook_urls_and_redirects(self):
|
||||
form = {"value_down": "http://foo.com", "value_up": "https://bar.com"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post("/integrations/add_webhook/", form)
|
||||
r = self.client.post(self.url, form)
|
||||
self.assertRedirects(r, "/integrations/")
|
||||
|
||||
c = Channel.objects.get()
|
||||
@ -20,26 +26,37 @@ class AddWebhookTestCase(BaseTestCase):
|
||||
# Logging in as bob, not alice. Bob has team access so this
|
||||
# should work.
|
||||
self.client.login(username="bob@example.org", password="password")
|
||||
self.client.post("/integrations/add_webhook/", form)
|
||||
self.client.post(self.url, form)
|
||||
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.user, self.alice)
|
||||
self.assertEqual(c.value, "http://foo.com\nhttps://bar.com")
|
||||
|
||||
def test_it_rejects_non_http_webhook_urls(self):
|
||||
form = {"value_down": "foo", "value_up": "bar"}
|
||||
def test_it_rejects_bad_urls(self):
|
||||
urls = [
|
||||
# clearly not an URL
|
||||
"foo",
|
||||
# FTP addresses not allowed
|
||||
"ftp://example.org",
|
||||
# no loopback
|
||||
"http://localhost:1234/endpoint",
|
||||
"http://127.0.0.1/endpoint"
|
||||
]
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post("/integrations/add_webhook/", form)
|
||||
self.assertContains(r, "Enter a valid URL.")
|
||||
for url in urls:
|
||||
form = {"value_down": url, "value_up": ""}
|
||||
|
||||
self.assertEqual(Channel.objects.count(), 0)
|
||||
r = self.client.post(self.url, form)
|
||||
self.assertContains(r, "Enter a valid URL.", msg_prefix=url)
|
||||
|
||||
self.assertEqual(Channel.objects.count(), 0)
|
||||
|
||||
def test_it_handles_empty_down_url(self):
|
||||
form = {"value_down": "", "value_up": "http://foo.com"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
self.client.post("/integrations/add_webhook/", form)
|
||||
self.client.post(self.url, form)
|
||||
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.value, "\nhttp://foo.com")
|
||||
|
@ -12,7 +12,6 @@ check_urls = [
|
||||
|
||||
channel_urls = [
|
||||
url(r'^$', views.channels, name="hc-channels"),
|
||||
url(r'^add/$', views.add_channel, name="hc-add-channel"),
|
||||
url(r'^add_email/$', views.add_email, name="hc-add-email"),
|
||||
url(r'^add_webhook/$', views.add_webhook, name="hc-add-webhook"),
|
||||
url(r'^add_pd/$', views.add_pd, name="hc-add-pd"),
|
||||
|
14
hc/front/validators.py
Normal file
14
hc/front/validators.py
Normal file
@ -0,0 +1,14 @@
|
||||
from django.core.exceptions import ValidationError
|
||||
from six.moves.urllib_parse import urlparse
|
||||
|
||||
|
||||
class WebhookValidator(object):
|
||||
message = "Enter a valid URL."
|
||||
|
||||
def __call__(self, value):
|
||||
parsed = urlparse(value)
|
||||
if parsed.scheme not in ("http", "https"):
|
||||
raise ValidationError(message=self.message)
|
||||
|
||||
if parsed.hostname in ("127.0.0.1", "localhost"):
|
||||
raise ValidationError(message=self.message)
|
@ -16,7 +16,7 @@ from django.utils.six.moves.urllib.parse import urlencode
|
||||
from hc.api.decorators import uuid_or_400
|
||||
from hc.api.models import DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check, Ping
|
||||
from hc.front.forms import (AddChannelForm, AddWebhookForm, NameTagsForm,
|
||||
TimeoutForm)
|
||||
TimeoutForm, AddUrlForm, AddPdForm, AddEmailForm)
|
||||
|
||||
|
||||
# from itertools recipes:
|
||||
@ -291,29 +291,6 @@ def channels(request):
|
||||
return render(request, "front/channels.html", ctx)
|
||||
|
||||
|
||||
def do_add_channel(request, data):
|
||||
form = AddChannelForm(data)
|
||||
if form.is_valid():
|
||||
channel = form.save(commit=False)
|
||||
channel.user = request.team.user
|
||||
channel.save()
|
||||
|
||||
channel.assign_all_checks()
|
||||
|
||||
if channel.kind == "email":
|
||||
channel.send_verify_link()
|
||||
|
||||
return redirect("hc-channels")
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
|
||||
@login_required
|
||||
def add_channel(request):
|
||||
assert request.method == "POST"
|
||||
return do_add_channel(request, request.POST)
|
||||
|
||||
|
||||
@login_required
|
||||
@uuid_or_400
|
||||
def channel_checks(request, code):
|
||||
@ -361,7 +338,20 @@ def remove_channel(request, code):
|
||||
|
||||
@login_required
|
||||
def add_email(request):
|
||||
ctx = {"page": "channels"}
|
||||
if request.method == "POST":
|
||||
form = AddEmailForm(request.POST)
|
||||
if form.is_valid():
|
||||
channel = Channel(user=request.team.user, kind="email")
|
||||
channel.value = form.cleaned_data["value"]
|
||||
channel.save()
|
||||
|
||||
channel.assign_all_checks()
|
||||
channel.send_verify_link()
|
||||
return redirect("hc-channels")
|
||||
else:
|
||||
form = AddEmailForm()
|
||||
|
||||
ctx = {"page": "channels", "form": form}
|
||||
return render(request, "integrations/add_email.html", ctx)
|
||||
|
||||
|
||||
@ -385,7 +375,19 @@ def add_webhook(request):
|
||||
|
||||
@login_required
|
||||
def add_pd(request):
|
||||
ctx = {"page": "channels"}
|
||||
if request.method == "POST":
|
||||
form = AddPdForm(request.POST)
|
||||
if form.is_valid():
|
||||
channel = Channel(user=request.team.user, kind="pd")
|
||||
channel.value = form.cleaned_data["value"]
|
||||
channel.save()
|
||||
|
||||
channel.assign_all_checks()
|
||||
return redirect("hc-channels")
|
||||
else:
|
||||
form = AddPdForm()
|
||||
|
||||
ctx = {"page": "channels", "form": form}
|
||||
return render(request, "integrations/add_pd.html", ctx)
|
||||
|
||||
|
||||
@ -393,10 +395,24 @@ def add_slack(request):
|
||||
if not settings.SLACK_CLIENT_ID and not request.user.is_authenticated:
|
||||
return redirect("hc-login")
|
||||
|
||||
if request.method == "POST":
|
||||
form = AddUrlForm(request.POST)
|
||||
if form.is_valid():
|
||||
channel = Channel(user=request.team.user, kind="slack")
|
||||
channel.value = form.cleaned_data["value"]
|
||||
channel.save()
|
||||
|
||||
channel.assign_all_checks()
|
||||
return redirect("hc-channels")
|
||||
else:
|
||||
form = AddUrlForm()
|
||||
|
||||
ctx = {
|
||||
"page": "channels",
|
||||
"form": form,
|
||||
"slack_client_id": settings.SLACK_CLIENT_ID
|
||||
}
|
||||
|
||||
return render(request, "integrations/add_slack.html", ctx)
|
||||
|
||||
|
||||
@ -430,7 +446,19 @@ def add_slack_btn(request):
|
||||
|
||||
@login_required
|
||||
def add_hipchat(request):
|
||||
ctx = {"page": "channels"}
|
||||
if request.method == "POST":
|
||||
form = AddUrlForm(request.POST)
|
||||
if form.is_valid():
|
||||
channel = Channel(user=request.team.user, kind="hipchat")
|
||||
channel.value = form.cleaned_data["value"]
|
||||
channel.save()
|
||||
|
||||
channel.assign_all_checks()
|
||||
return redirect("hc-channels")
|
||||
else:
|
||||
form = AddUrlForm()
|
||||
|
||||
ctx = {"page": "channels", "form": form}
|
||||
return render(request, "integrations/add_hipchat.html", ctx)
|
||||
|
||||
|
||||
@ -526,10 +554,11 @@ def add_pushover(request):
|
||||
user_key = request.GET["pushover_user_key"]
|
||||
priority = int(request.GET["prio"])
|
||||
|
||||
return do_add_channel(request, {
|
||||
"kind": "po",
|
||||
"value": "%s|%d" % (user_key, priority),
|
||||
})
|
||||
channel = Channel(user=request.team.user, kind="po")
|
||||
channel.value = "%s|%d" % (user_key, priority)
|
||||
channel.save()
|
||||
channel.assign_all_checks()
|
||||
return redirect("hc-channels")
|
||||
|
||||
# Show Integration Settings form
|
||||
ctx = {
|
||||
@ -542,7 +571,19 @@ def add_pushover(request):
|
||||
|
||||
@login_required
|
||||
def add_victorops(request):
|
||||
ctx = {"page": "channels"}
|
||||
if request.method == "POST":
|
||||
form = AddUrlForm(request.POST)
|
||||
if form.is_valid():
|
||||
channel = Channel(user=request.team.user, kind="victorops")
|
||||
channel.value = form.cleaned_data["value"]
|
||||
channel.save()
|
||||
|
||||
channel.assign_all_checks()
|
||||
return redirect("hc-channels")
|
||||
else:
|
||||
form = AddUrlForm()
|
||||
|
||||
ctx = {"page": "channels", "form": form}
|
||||
return render(request, "integrations/add_victorops.html", ctx)
|
||||
|
||||
|
||||
|
@ -24,10 +24,9 @@
|
||||
|
||||
<h2>Integration Settings</h2>
|
||||
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-channel' %}">
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-email' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="kind" value="email" />
|
||||
<div class="form-group">
|
||||
<div class="form-group {{ form.value.css_classes }}">
|
||||
<label for="id_email" class="col-sm-2 control-label">Email</label>
|
||||
<div class="col-sm-3">
|
||||
<input
|
||||
@ -35,7 +34,14 @@
|
||||
type="email"
|
||||
class="form-control"
|
||||
name="value"
|
||||
placeholder="you@example.org">
|
||||
placeholder="you@example.org"
|
||||
value="{{ form.value.value|default:"" }}">
|
||||
|
||||
{% if form.value.errors %}
|
||||
<div class="help-block">
|
||||
{{ form.value.errors|join:"" }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -64,10 +64,9 @@
|
||||
|
||||
<h2>Integration Settings</h2>
|
||||
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-channel' %}">
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-hipchat' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="kind" value="hipchat" />
|
||||
<div class="form-group">
|
||||
<div class="form-group {{ form.value.css_classes }}">
|
||||
<label for="callback-url" class="col-sm-2 control-label">Callback URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
@ -75,7 +74,14 @@
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="value"
|
||||
placeholder="">
|
||||
placeholder="https://"
|
||||
value="{{ form.value.value|default:"" }}">
|
||||
|
||||
{% if form.value.errors %}
|
||||
<div class="help-block">
|
||||
{{ form.value.errors|join:"" }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -63,10 +63,9 @@
|
||||
|
||||
<h2>Integration Settings</h2>
|
||||
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-channel' %}">
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-pd' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="kind" value="pd" />
|
||||
<div class="form-group">
|
||||
<div class="form-group {{ form.value.css_classes }}">
|
||||
<label for="api-key" class="col-sm-2 control-label">API Key</label>
|
||||
<div class="col-sm-3">
|
||||
<input
|
||||
@ -74,7 +73,14 @@
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="value"
|
||||
placeholder="">
|
||||
placeholder=""
|
||||
value="{{ form.value.value|default:"" }}">
|
||||
|
||||
{% if form.value.errors %}
|
||||
<div class="help-block">
|
||||
{{ form.value.errors|join:"" }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -156,13 +156,26 @@
|
||||
|
||||
<h2>Integration Settings</h2>
|
||||
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-channel' %}">
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-slack' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="kind" value="slack" />
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Callback URL</label>
|
||||
<div class="form-group {{ form.value.css_classes }}">
|
||||
<label for="callback-url" class="col-sm-2 control-label">
|
||||
Callback URL
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="value" placeholder="">
|
||||
<input
|
||||
id="callback-url"
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="value"
|
||||
placeholder="https://"
|
||||
value="{{ form.value.value|default:"" }}">
|
||||
|
||||
{% if form.value.errors %}
|
||||
<div class="help-block">
|
||||
{{ form.value.errors|join:"" }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -77,10 +77,9 @@
|
||||
|
||||
<h2>Integration Settings</h2>
|
||||
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-channel' %}">
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-victorops' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="kind" value="victorops" />
|
||||
<div class="form-group">
|
||||
<div class="form-group {{ form.value.css_classes }}">
|
||||
<label for="post-url" class="col-sm-2 control-label">Post URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
@ -88,7 +87,14 @@
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="value"
|
||||
placeholder="">
|
||||
placeholder="https://"
|
||||
value="{{ form.value.value|default:"" }}">
|
||||
|
||||
{% if form.value.errors %}
|
||||
<div class="help-block">
|
||||
{{ form.value.errors|join:"" }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
Loading…
x
Reference in New Issue
Block a user