From c3d458f6f02884a24bed190b09ea7cdaa62f1a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Mon, 2 Aug 2021 12:51:05 +0300 Subject: [PATCH] Fix the unsubscribe_reports view to handle already deleted users --- hc/accounts/tests/test_unsubscribe_reports.py | 9 +++++++++ hc/accounts/views.py | 20 +++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/hc/accounts/tests/test_unsubscribe_reports.py b/hc/accounts/tests/test_unsubscribe_reports.py index c2bdd566..f4cdb2fe 100644 --- a/hc/accounts/tests/test_unsubscribe_reports.py +++ b/hc/accounts/tests/test_unsubscribe_reports.py @@ -51,3 +51,12 @@ class UnsubscribeReportsTestCase(BaseTestCase): r = self.client.get(url) self.assertContains(r, "Please press the button below") self.assertContains(r, "submit()") + + def test_it_handles_missing_user(self): + self.alice.delete() + + sig = signing.TimestampSigner(salt="reports").sign("alice") + url = "/accounts/unsubscribe_reports/%s/" % sig + + r = self.client.post(url) + self.assertContains(r, "Unsubscribed") diff --git a/hc/accounts/views.py b/hc/accounts/views.py index db22627d..eb165f82 100644 --- a/hc/accounts/views.py +++ b/hc/accounts/views.py @@ -555,7 +555,6 @@ def unsubscribe_reports(request, signed_username): # If the signature is more than 5 minutes old, we also include JS code to # auto-submit the form. - ctx = {} signer = signing.TimestampSigner(salt="reports") # First, check the signature without looking at the timestamp: try: @@ -563,16 +562,25 @@ def unsubscribe_reports(request, signed_username): except signing.BadSignature: return render(request, "bad_link.html") - # Check if timestamp is older than 5 minutes: try: - username = signer.unsign(signed_username, max_age=300) - except signing.SignatureExpired: - ctx["autosubmit"] = True + user = User.objects.get(username=username) + except User.DoesNotExist: + # This is likely an old unsubscribe link, and the user account has already + # been deleted. Show the "Unsubscribed!" page nevertheless. + return render(request, "accounts/unsubscribed.html") if request.method != "POST": + # Unsign again, now with max_age set, + # to see if the timestamp is older than 5 minutes + try: + autosubmit = False + username = signer.unsign(signed_username, max_age=300) + except signing.SignatureExpired: + autosubmit = True + + ctx = {"autosubmit": autosubmit} return render(request, "accounts/unsubscribe_submit.html", ctx) - user = User.objects.get(username=username) profile = Profile.objects.for_user(user) profile.reports = "off" profile.next_report_date = None