diff --git a/hc/accounts/views.py b/hc/accounts/views.py index 7b667434..342cea39 100644 --- a/hc/accounts/views.py +++ b/hc/accounts/views.py @@ -100,6 +100,6 @@ def check_token(request, username, token): user.save() auth_login(request, user) - return redirect("hc-index") + return redirect("hc-checks") return render(request, "bad_link.html") diff --git a/hc/front/tests/test_channel_checks.py b/hc/front/tests/test_channel_checks.py index d714ce36..a4b48f0f 100644 --- a/hc/front/tests/test_channel_checks.py +++ b/hc/front/tests/test_channel_checks.py @@ -33,3 +33,11 @@ class ChannelChecksTestCase(TestCase): self.client.login(username="mallory", password="password") r = self.client.get(url) assert r.status_code == 403 + + def test_missing_channel(self): + # Valid UUID but there is no channel for it: + url = "/channels/6837d6ec-fc08-4da5-a67f-08a9ed1ccf62/checks/" + + self.client.login(username="alice", password="password") + r = self.client.get(url) + assert r.status_code == 404 diff --git a/hc/front/tests/test_log.py b/hc/front/tests/test_log.py index 5d24a9bb..ab0e3f35 100644 --- a/hc/front/tests/test_log.py +++ b/hc/front/tests/test_log.py @@ -27,3 +27,11 @@ class LogTestCase(TestCase): self.client.login(username="alice", password="password") r = self.client.get(url) assert r.status_code == 400 + + def test_it_handles_missing_uuid(self): + # Valid UUID but there is no check for it: + url = "/checks/6837d6ec-fc08-4da5-a67f-08a9ed1ccf62/log/" + + self.client.login(username="alice", password="password") + r = self.client.get(url) + assert r.status_code == 404 diff --git a/hc/front/tests/test_remove_channel.py b/hc/front/tests/test_remove_channel.py index 4f6571ad..a27bae2e 100644 --- a/hc/front/tests/test_remove_channel.py +++ b/hc/front/tests/test_remove_channel.py @@ -41,3 +41,11 @@ class RemoveChannelTestCase(TestCase): self.client.login(username="mallory", password="password") r = self.client.post(url) assert r.status_code == 403 + + def test_it_handles_missing_uuid(self): + # Valid UUID but there is no channel for it: + url = "/channels/6837d6ec-fc08-4da5-a67f-08a9ed1ccf62/remove/" + + self.client.login(username="alice", password="password") + r = self.client.post(url) + assert r.status_code == 404 diff --git a/hc/front/tests/test_remove_check.py b/hc/front/tests/test_remove_check.py index 843b244f..6335d35d 100644 --- a/hc/front/tests/test_remove_check.py +++ b/hc/front/tests/test_remove_check.py @@ -40,3 +40,11 @@ class RemoveCheckTestCase(TestCase): self.client.login(username="mallory", password="password") r = self.client.post(url) assert r.status_code == 403 + + def test_it_handles_missing_uuid(self): + # Valid UUID but there is no check for it: + url = "/checks/6837d6ec-fc08-4da5-a67f-08a9ed1ccf62/remove/" + + self.client.login(username="alice", password="password") + r = self.client.post(url) + assert r.status_code == 404 diff --git a/hc/front/tests/test_update_channel.py b/hc/front/tests/test_update_channel.py index af0596c5..de0acce0 100644 --- a/hc/front/tests/test_update_channel.py +++ b/hc/front/tests/test_update_channel.py @@ -63,4 +63,23 @@ class UpdateChannelTestCase(TestCase): r = self.client.post("/channels/", data=payload) # mc belongs to mallorym but self.check does not-- - assert r.status_code == 403 \ No newline at end of file + assert r.status_code == 403 + + def test_it_handles_missing_channel(self): + # Correct UUID but there is no channel for it: + payload = {"channel": "6837d6ec-fc08-4da5-a67f-08a9ed1ccf62"} + + self.client.login(username="alice", password="password") + r = self.client.post("/channels/", data=payload) + assert r.status_code == 400 + + def test_it_handles_missing_check(self): + # check- key has a correct UUID but there's no check object for it + payload = { + "channel": self.channel.code, + "check-6837d6ec-fc08-4da5-a67f-08a9ed1ccf62": True + } + + self.client.login(username="alice", password="password") + r = self.client.post("/channels/", data=payload) + assert r.status_code == 400 diff --git a/hc/front/tests/test_update_name.py b/hc/front/tests/test_update_name.py index 02f10fd6..5f0713ae 100644 --- a/hc/front/tests/test_update_name.py +++ b/hc/front/tests/test_update_name.py @@ -45,3 +45,12 @@ class UpdateNameTestCase(TestCase): self.client.login(username="alice", password="password") r = self.client.post(url, data=payload) assert r.status_code == 400 + + def test_it_handles_missing_uuid(self): + # Valid UUID but there is no check for it: + url = "/checks/6837d6ec-fc08-4da5-a67f-08a9ed1ccf62/name/" + payload = {"name": "Alice Was Here"} + + self.client.login(username="alice", password="password") + r = self.client.post(url, data=payload) + assert r.status_code == 404 diff --git a/hc/front/tests/test_update_timeout.py b/hc/front/tests/test_update_timeout.py index 91f025df..9a6cb362 100644 --- a/hc/front/tests/test_update_timeout.py +++ b/hc/front/tests/test_update_timeout.py @@ -33,3 +33,12 @@ class UpdateTimeoutTestCase(TestCase): self.client.login(username="alice", password="password") r = self.client.post(url, data=payload) assert r.status_code == 400 + + def test_it_handles_missing_uuid(self): + # Valid UUID but there is no check for it: + url = "/checks/6837d6ec-fc08-4da5-a67f-08a9ed1ccf62/timeout/" + payload = {"timeout": 3600, "grace": 60} + + self.client.login(username="alice", password="password") + r = self.client.post(url, data=payload) + assert r.status_code == 404 diff --git a/hc/front/tests/test_verify_email.py b/hc/front/tests/test_verify_email.py index da4acfd9..0229c24d 100644 --- a/hc/front/tests/test_verify_email.py +++ b/hc/front/tests/test_verify_email.py @@ -33,3 +33,12 @@ class VerifyEmailTestCase(TestCase): channel = Channel.objects.get(code=self.channel.code) assert not channel.email_verified + + def test_missing_channel(self): + # Valid UUID, and even valid token but there is no channel for it: + code = "6837d6ec-fc08-4da5-a67f-08a9ed1ccf62" + token = self.channel.make_token() + url = "/channels/%s/verify/%s/" % (code, token) + + r = self.client.post(url) + assert r.status_code == 404 diff --git a/hc/front/urls.py b/hc/front/urls.py index b3b58a97..9df00692 100644 --- a/hc/front/urls.py +++ b/hc/front/urls.py @@ -4,6 +4,7 @@ from hc.front import views urlpatterns = [ url(r'^$', views.index, name="hc-index"), + url(r'^checks/$', views.my_checks, name="hc-checks"), url(r'^checks/add/$', views.add_check, name="hc-add-check"), url(r'^checks/([\w-]+)/name/$', views.update_name, name="hc-update-name"), url(r'^checks/([\w-]+)/timeout/$', views.update_timeout, name="hc-update-timeout"), diff --git a/hc/front/views.py b/hc/front/views.py index af2e96c4..405dfe82 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -2,8 +2,8 @@ from datetime import timedelta as td from django.conf import settings from django.contrib.auth.decorators import login_required -from django.http import HttpResponseForbidden -from django.shortcuts import redirect, render +from django.http import HttpResponseBadRequest, HttpResponseForbidden +from django.shortcuts import get_object_or_404, redirect, render from django.utils import timezone from hc.api.decorators import uuid_or_400 @@ -11,7 +11,23 @@ from hc.api.models import Channel, Check, Ping from hc.front.forms import AddChannelForm, TimeoutForm -def _welcome(request): +@login_required +def my_checks(request): + checks = Check.objects.filter(user=request.user).order_by("created") + + ctx = { + "page": "checks", + "checks": checks, + "now": timezone.now() + } + + return render(request, "front/my_checks.html", ctx) + + +def index(request): + if request.user.is_authenticated(): + return redirect("hc-checks") + if "welcome_code" not in request.session: check = Check() check.save() @@ -30,25 +46,6 @@ def _welcome(request): return render(request, "front/welcome.html", ctx) -def _my_checks(request): - checks = Check.objects.filter(user=request.user).order_by("created") - - ctx = { - "page": "checks", - "checks": checks, - "now": timezone.now() - } - - return render(request, "front/my_checks.html", ctx) - - -def index(request): - if request.user.is_authenticated(): - return _my_checks(request) - else: - return _welcome(request) - - def pricing(request): return render(request, "front/pricing.html", {"page": "pricing"}) @@ -83,7 +80,7 @@ def add_check(request): check.assign_all_channels() - return redirect("hc-index") + return redirect("hc-checks") @login_required @@ -91,14 +88,14 @@ def add_check(request): def update_name(request, code): assert request.method == "POST" - check = Check.objects.get(code=code) + check = get_object_or_404(Check, code=code) if check.user != request.user: return HttpResponseForbidden() check.name = request.POST["name"] check.save() - return redirect("hc-index") + return redirect("hc-checks") @login_required @@ -106,7 +103,7 @@ def update_name(request, code): def update_timeout(request, code): assert request.method == "POST" - check = Check.objects.get(code=code) + check = get_object_or_404(Check, code=code) if check.user != request.user: return HttpResponseForbidden() @@ -116,7 +113,7 @@ def update_timeout(request, code): check.grace = td(seconds=form.cleaned_data["grace"]) check.save() - return redirect("hc-index") + return redirect("hc-checks") @login_required @@ -147,19 +144,19 @@ def email_preview(request, code): def remove_check(request, code): assert request.method == "POST" - check = Check.objects.get(code=code) + check = get_object_or_404(Check, code=code) if check.user != request.user: return HttpResponseForbidden() check.delete() - return redirect("hc-index") + return redirect("hc-checks") @login_required @uuid_or_400 def log(request, code): - check = Check.objects.get(code=code) + check = get_object_or_404(Check, code=code) if check.user != request.user: return HttpResponseForbidden() @@ -178,7 +175,10 @@ def log(request, code): def channels(request): if request.method == "POST": code = request.POST["channel"] - channel = Channel.objects.get(code=code) + try: + channel = Channel.objects.get(code=code) + except Channel.DoesNotExist: + return HttpResponseBadRequest() if channel.user != request.user: return HttpResponseForbidden() @@ -186,7 +186,10 @@ def channels(request): for key in request.POST: if key.startswith("check-"): code = key[6:] - check = Check.objects.get(code=code) + try: + check = Check.objects.get(code=code) + except Check.DoesNotExist: + return HttpResponseBadRequest() if check.user != request.user: return HttpResponseForbidden() new_checks.append(check) @@ -227,7 +230,7 @@ def add_channel(request): @login_required @uuid_or_400 def channel_checks(request, code): - channel = Channel.objects.get(code=code) + channel = get_object_or_404(Channel, code=code) if channel.user != request.user: return HttpResponseForbidden() @@ -245,7 +248,7 @@ def channel_checks(request, code): @uuid_or_400 def verify_email(request, code, token): - channel = Channel.objects.get(code=code) + channel = get_object_or_404(Channel, code=code) if channel.make_token() == token: channel.email_verified = True channel.save() @@ -259,7 +262,7 @@ def verify_email(request, code, token): def remove_channel(request, code): assert request.method == "POST" - channel = Channel.objects.get(code=code) + channel = get_object_or_404(Channel, code=code) if channel.user != request.user: return HttpResponseForbidden() diff --git a/templates/base.html b/templates/base.html index a73719f9..02d526b4 100644 --- a/templates/base.html +++ b/templates/base.html @@ -47,7 +47,7 @@