From 5e051bfc30a9333c9978517dc1112102b0422f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= <cuu508@gmail.com> Date: Tue, 20 Aug 2024 10:57:36 +0300 Subject: [PATCH] Fix AJAX views to better handle user logging out Rather than redirecting to login page, return HTTP 403 Forbidden --- CHANGELOG.md | 1 + hc/front/tests/test_log_events.py | 4 ++++ hc/front/tests/test_status.py | 4 ++++ hc/front/tests/test_status_single.py | 4 ++++ hc/front/views.py | 18 ++++++++++++------ static/js/log.js | 3 +++ 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49444f69..48486736 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. ### Bug Fixes - Fix Check.ping() to lock the check before updating (#1023) +- Fix AJAX views to better handle user logging out ## v3.4 - 2024-06-20 diff --git a/hc/front/tests/test_log_events.py b/hc/front/tests/test_log_events.py index eab3d3aa..69fdee7e 100644 --- a/hc/front/tests/test_log_events.py +++ b/hc/front/tests/test_log_events.py @@ -57,6 +57,10 @@ class LogTestCase(BaseTestCase): self.assertContains(r, "Sent email to alice@example.org") self.assertContains(r, "new ➔ down") + def test_it_returns_403_for_anon_requests(self) -> None: + r = self.client.get(self.url()) + self.assertEqual(r.status_code, 403) + def test_team_access_works(self) -> None: # Logging in as bob, not alice. Bob has team access so this # should work. diff --git a/hc/front/tests/test_status.py b/hc/front/tests/test_status.py index a48e3e89..68545a11 100644 --- a/hc/front/tests/test_status.py +++ b/hc/front/tests/test_status.py @@ -26,6 +26,10 @@ class StatusTestCase(BaseTestCase): self.assertEqual(detail["status"], "new") self.assertIn("Never", detail["last_ping"]) + def test_it_returns_403_for_anon_requests(self) -> None: + r = self.client.get(self.url) + self.assertEqual(r.status_code, 403) + def test_it_allows_cross_team_access(self) -> None: self.client.login(username="bob@example.org", password="password") r = self.client.get(self.url) diff --git a/hc/front/tests/test_status_single.py b/hc/front/tests/test_status_single.py index 0a16381c..d39b4992 100644 --- a/hc/front/tests/test_status_single.py +++ b/hc/front/tests/test_status_single.py @@ -21,6 +21,10 @@ class StatusSingleTestCase(BaseTestCase): self.assertTrue("never received a ping" in doc["status_text"]) self.assertTrue("not received any pings yet" in doc["events"]) + def test_it_returns_403_for_anon_requests(self) -> None: + r = self.client.get(self.url) + self.assertEqual(r.status_code, 403) + def test_it_returns_events(self) -> None: p = Ping.objects.create(owner=self.check, ua="test-user-agent", n=1) self.check.status = "up" diff --git a/hc/front/views.py b/hc/front/views.py index e529ec11..512ce8d1 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -303,8 +303,10 @@ def checks(request: AuthenticatedHttpRequest, code: UUID) -> HttpResponse: return render(request, "front/checks.html", ctx) -@login_required -def status(request: AuthenticatedHttpRequest, code: UUID) -> HttpResponse: +def status(request: HttpRequest, code: UUID) -> HttpResponse: + if not request.user.is_authenticated: + return HttpResponseForbidden() + project, rw = _get_project_for_user(request, code) checks = list(Check.objects.filter(project=project)) @@ -1085,8 +1087,10 @@ def copy(request: AuthenticatedHttpRequest, code: UUID) -> HttpResponse: return redirect(url + "?copied") -@login_required -def status_single(request: AuthenticatedHttpRequest, code: UUID) -> HttpResponse: +def status_single(request: HttpRequest, code: UUID) -> HttpResponse: + if not request.user.is_authenticated: + return HttpResponseForbidden() + check, rw = _get_check_for_user(request, code, preload_owner_profile=True) status = check.get_status() @@ -2779,8 +2783,10 @@ def verify_signal_number(request: AuthenticatedHttpRequest) -> HttpResponse: return render_result(None) -@login_required -def log_events(request: AuthenticatedHttpRequest, code: UUID) -> HttpResponse: +def log_events(request: HttpRequest, code: UUID) -> HttpResponse: + if not request.user.is_authenticated: + return HttpResponseForbidden() + check, rw = _get_check_for_user(request, code, preload_owner_profile=True) form = forms.LogFiltersForm(request.GET) if not form.is_valid(): diff --git a/static/js/log.js b/static/js/log.js index 4a36ed43..b579fa1b 100644 --- a/static/js/log.js +++ b/static/js/log.js @@ -124,6 +124,9 @@ $(function () { switchDateFormat(dateFormat, tbody.querySelectorAll("tr")); document.getElementById("log").prepend(tbody); updateNumHits(); + }, + error: function(data, textStatus, xhr) { + activeRequest = null; } }); }