diff --git a/hc/api/models.py b/hc/api/models.py index a1cdd7d4..e645119a 100644 --- a/hc/api/models.py +++ b/hc/api/models.py @@ -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 = { diff --git a/hc/front/forms.py b/hc/front/forms.py index c7bf28a3..4923dc1a 100644 --- a/hc/front/forms.py +++ b/hc/front/forms.py @@ -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) diff --git a/hc/front/tests/test_add_channel.py b/hc/front/tests/test_add_channel.py deleted file mode 100644 index c1ba14f4..00000000 --- a/hc/front/tests/test_add_channel.py +++ /dev/null @@ -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) diff --git a/hc/front/tests/test_add_email.py b/hc/front/tests/test_add_email.py new file mode 100644 index 00000000..44a98b4b --- /dev/null +++ b/hc/front/tests/test_add_email.py @@ -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") diff --git a/hc/front/tests/test_add_hipchat.py b/hc/front/tests/test_add_hipchat.py new file mode 100644 index 00000000..86adafb7 --- /dev/null +++ b/hc/front/tests/test_add_hipchat.py @@ -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") diff --git a/hc/front/tests/test_add_pd.py b/hc/front/tests/test_add_pd.py new file mode 100644 index 00000000..157ef137 --- /dev/null +++ b/hc/front/tests/test_add_pd.py @@ -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") diff --git a/hc/front/tests/test_add_pushbover.py b/hc/front/tests/test_add_pushbover.py index 103299de..fc5b16f1 100644 --- a/hc/front/tests/test_add_pushbover.py +++ b/hc/front/tests/test_add_pushbover.py @@ -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") diff --git a/hc/front/tests/test_add_pushbullet.py b/hc/front/tests/test_add_pushbullet.py index aec9649f..cc31925b 100644 --- a/hc/front/tests/test_add_pushbullet.py +++ b/hc/front/tests/test_add_pushbullet.py @@ -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) diff --git a/hc/front/tests/test_add_slack.py b/hc/front/tests/test_add_slack.py index b7456055..ff6f4822 100644 --- a/hc/front/tests/test_add_slack.py +++ b/hc/front/tests/test_add_slack.py @@ -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") - @patch("hc.front.views.requests.post") - def test_it_handles_oauth_error(self, mock_post): - oauth_response = { - "ok": False, - "error": "something went wrong" - } + c = Channel.objects.get() + self.assertEqual(c.kind, "slack") + self.assertEqual(c.value, "http://example.org") - 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") diff --git a/hc/front/tests/test_add_slack_btn.py b/hc/front/tests/test_add_slack_btn.py new file mode 100644 index 00000000..e82a0e7f --- /dev/null +++ b/hc/front/tests/test_add_slack_btn.py @@ -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") diff --git a/hc/front/tests/test_add_victorops.py b/hc/front/tests/test_add_victorops.py new file mode 100644 index 00000000..8dae20f8 --- /dev/null +++ b/hc/front/tests/test_add_victorops.py @@ -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") diff --git a/hc/front/tests/test_add_webhook.py b/hc/front/tests/test_add_webhook.py index 0570706b..276799c5 100644 --- a/hc/front/tests/test_add_webhook.py +++ b/hc/front/tests/test_add_webhook.py @@ -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": ""} + + r = self.client.post(self.url, form) + self.assertContains(r, "Enter a valid URL.", msg_prefix=url) - self.assertEqual(Channel.objects.count(), 0) + 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") diff --git a/hc/front/urls.py b/hc/front/urls.py index 53befc60..07c77ac5 100644 --- a/hc/front/urls.py +++ b/hc/front/urls.py @@ -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"), diff --git a/hc/front/validators.py b/hc/front/validators.py new file mode 100644 index 00000000..bb9481fa --- /dev/null +++ b/hc/front/validators.py @@ -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) diff --git a/hc/front/views.py b/hc/front/views.py index 46015059..4f8da7e5 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -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) diff --git a/templates/integrations/add_email.html b/templates/integrations/add_email.html index 5da69e3b..d181e9e9 100644 --- a/templates/integrations/add_email.html +++ b/templates/integrations/add_email.html @@ -24,10 +24,9 @@