diff --git a/hc/api/models.py b/hc/api/models.py index 25e16721..505c3636 100644 --- a/hc/api/models.py +++ b/hc/api/models.py @@ -33,9 +33,6 @@ class Check(models.Model): alert_after = models.DateTimeField(null=True, blank=True, editable=False) status = models.CharField(max_length=6, choices=STATUSES, default="new") - def __str__(self): - return "Check(%s)" % self.code - def name_then_code(self): if self.name: return self.name diff --git a/hc/api/tests/test_notify.py b/hc/api/tests/test_notify.py index 74c229a9..e57078bd 100644 --- a/hc/api/tests/test_notify.py +++ b/hc/api/tests/test_notify.py @@ -1,4 +1,5 @@ from django.contrib.auth.models import User +from django.core import mail from django.test import TestCase from mock import patch from requests.exceptions import ReadTimeout @@ -8,35 +9,54 @@ from hc.api.models import Channel, Check, Notification class NotifyTestCase(TestCase): - @patch("hc.api.models.requests.get") - def test_webhook(self, mock_get): - alice = User(username="alice") - alice.save() + def _setup_data(self, channel_kind, channel_value, email_verified=True): + self.alice = User(username="alice") + self.alice.save() + + self.check = Check() + self.check.status = "down" + self.check.save() - check = Check() - check.status = "down" - check.save() + self.channel = Channel(user=self.alice) + self.channel.kind = channel_kind + self.channel.value = channel_value + self.channel.email_verified = email_verified + self.channel.save() + self.channel.checks.add(self.check) - channel = Channel(user=alice, kind="webhook", value="http://example") - channel.save() - channel.checks.add(check) + @patch("hc.api.models.requests.get") + def test_webhook(self, mock_get): + self._setup_data("webhook", "http://example") - channel.notify(check) + self.channel.notify(self.check) mock_get.assert_called_with(u"http://example", timeout=5) @patch("hc.api.models.requests.get", side_effect=ReadTimeout) - def test_it_handles_requests_exceptions(self, mock_get): - alice = User(username="alice") - alice.save() + def test_webhooks_handle_timeouts(self, mock_get): + self._setup_data("webhook", "http://example") + self.channel.notify(self.check) + assert Notification.objects.count() == 1 + + def test_email(self): + self._setup_data("email", "alice@example.org") + self.channel.notify(self.check) + assert Notification.objects.count() == 1 - check = Check() - check.status = "down" - check.save() + # And email should have been sent + self.assertEqual(len(mail.outbox), 1) - channel = Channel(user=alice, kind="webhook", value="http://example") - channel.save() - channel.checks.add(check) + def test_it_skips_unverified_email(self): + self._setup_data("email", "alice@example.org", email_verified=False) + self.channel.notify(self.check) - channel.notify(check) + assert Notification.objects.count() == 0 + self.assertEqual(len(mail.outbox), 0) + @patch("hc.api.models.requests.post") + def test_pd(self, mock_post): + self._setup_data("pd", "123") + self.channel.notify(self.check) assert Notification.objects.count() == 1 + + args, kwargs = mock_post.call_args + assert "trigger" in kwargs["data"] diff --git a/hc/front/tests/test_add_channel.py b/hc/front/tests/test_add_channel.py new file mode 100644 index 00000000..ec50c187 --- /dev/null +++ b/hc/front/tests/test_add_channel.py @@ -0,0 +1,31 @@ +from django.contrib.auth.models import User +from django.test import TestCase + +from hc.api.models import Channel + + +class AddChannelTestCase(TestCase): + + def setUp(self): + self.alice = User(username="alice") + self.alice.set_password("password") + self.alice.save() + + def test_it_works(self): + url = "/channels/add/" + form = {"kind": "email", "value": "alice@example.org"} + + self.client.login(username="alice", password="password") + r = self.client.post(url, form) + + assert r.status_code == 302 + assert Channel.objects.count() == 1 + + def test_it_rejects_bad_kind(self): + url = "/channels/add/" + form = {"kind": "dog", "value": "Lassie"} + + self.client.login(username="alice", password="password") + r = self.client.post(url, form) + + assert r.status_code == 400, r.status_code diff --git a/hc/front/tests/test_log.py b/hc/front/tests/test_log.py index ab0e3f35..d0656ec1 100644 --- a/hc/front/tests/test_log.py +++ b/hc/front/tests/test_log.py @@ -35,3 +35,13 @@ class LogTestCase(TestCase): self.client.login(username="alice", password="password") r = self.client.get(url) assert r.status_code == 404 + + def test_it_checks_ownership(self): + charlie = User(username="charlie") + charlie.set_password("password") + charlie.save() + + url = "/checks/%s/log/" % self.check.code + self.client.login(username="charlie", password="password") + r = self.client.get(url) + assert r.status_code == 403 diff --git a/hc/front/tests/test_my_checks.py b/hc/front/tests/test_my_checks.py new file mode 100644 index 00000000..d42ee941 --- /dev/null +++ b/hc/front/tests/test_my_checks.py @@ -0,0 +1,20 @@ +from django.contrib.auth.models import User +from django.test import TestCase + +from hc.api.models import Check + + +class MyChecksTestCase(TestCase): + + def setUp(self): + self.alice = User(username="alice") + self.alice.set_password("password") + self.alice.save() + + self.check = Check(user=self.alice, name="Alice Was Here") + self.check.save() + + def test_it_works(self): + self.client.login(username="alice", password="password") + r = self.client.get("/checks/") + self.assertContains(r, "Alice Was Here", status_code=200) diff --git a/hc/front/tests/test_update_timeout.py b/hc/front/tests/test_update_timeout.py index 9a6cb362..7eb24407 100644 --- a/hc/front/tests/test_update_timeout.py +++ b/hc/front/tests/test_update_timeout.py @@ -42,3 +42,15 @@ class UpdateTimeoutTestCase(TestCase): self.client.login(username="alice", password="password") r = self.client.post(url, data=payload) assert r.status_code == 404 + + def test_it_checks_ownership(self): + charlie = User(username="charlie") + charlie.set_password("password") + charlie.save() + + url = "/checks/%s/timeout/" % self.check.code + payload = {"timeout": 3600, "grace": 60} + + self.client.login(username="charlie", password="password") + r = self.client.post(url, data=payload) + assert r.status_code == 403 diff --git a/hc/front/views.py b/hc/front/views.py index 405dfe82..8a0b5e9d 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -224,7 +224,9 @@ def add_channel(request): if channel.kind == "email": channel.send_verify_link() - return redirect("hc-channels") + return redirect("hc-channels") + else: + return HttpResponseBadRequest() @login_required diff --git a/templates/emails/alert-body-html.html b/templates/emails/alert-body-html.html index 68817735..81f3997b 100644 --- a/templates/emails/alert-body-html.html +++ b/templates/emails/alert-body-html.html @@ -33,7 +33,7 @@

Hello,

This is a notification sent by healthchecks.io.

-

The check "{{ check.name|default:check.code }}" has gone {{ check.status }}.

+

The check "{{ check.name_then_code }}" has gone {{ check.status }}.

Here is a summary of all your checks:

diff --git a/templates/emails/alert-subject.html b/templates/emails/alert-subject.html index 8ac3c573..ee060ce9 100644 --- a/templates/emails/alert-subject.html +++ b/templates/emails/alert-subject.html @@ -1,2 +1,2 @@ -{{ check.name|default:check.code }} is {{ check.status }} +{{ check.name_then_code }} is {{ check.status }} diff --git a/templates/front/log.html b/templates/front/log.html index b620b679..082aab76 100644 --- a/templates/front/log.html +++ b/templates/front/log.html @@ -7,7 +7,7 @@ {% block content %}
-

Log for “{{ check.name|default:check.code }}”

+

Log for “{{ check.name_then_code }}”

{% if pings %}
diff --git a/templates/front/my_checks_mobile.html b/templates/front/my_checks_mobile.html index 7a10d5d7..e9cad751 100644 --- a/templates/front/my_checks_mobile.html +++ b/templates/front/my_checks_mobile.html @@ -14,7 +14,7 @@