forked from GithubBackups/healthchecks
Unsubscribe links serve a form, and require HTTP POST to actually unsubscribe
This commit is contained in:
parent
4ee92a44ff
commit
8d81d27af3
@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
- Don't set CSRF cookie on first visit. Signup is exempt from CSRF protection
|
- Don't set CSRF cookie on first visit. Signup is exempt from CSRF protection
|
||||||
- Fix List-Unsubscribe email header value: add angle brackets
|
- Fix List-Unsubscribe email header value: add angle brackets
|
||||||
|
- Unsubscribe links serve a form, and require HTTP POST to actually unsubscribe
|
||||||
|
|
||||||
|
|
||||||
## v1.11.0 - 2019-11-22
|
## v1.11.0 - 2019-11-22
|
||||||
|
@ -15,7 +15,7 @@ class UnsubscribeReportsTestCase(BaseTestCase):
|
|||||||
sig = signing.TimestampSigner(salt="reports").sign("alice")
|
sig = signing.TimestampSigner(salt="reports").sign("alice")
|
||||||
url = "/accounts/unsubscribe_reports/%s/" % sig
|
url = "/accounts/unsubscribe_reports/%s/" % sig
|
||||||
|
|
||||||
r = self.client.get(url)
|
r = self.client.post(url)
|
||||||
self.assertContains(r, "Unsubscribed")
|
self.assertContains(r, "Unsubscribed")
|
||||||
|
|
||||||
self.profile.refresh_from_db()
|
self.profile.refresh_from_db()
|
||||||
@ -30,16 +30,9 @@ class UnsubscribeReportsTestCase(BaseTestCase):
|
|||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertContains(r, "Incorrect Link")
|
self.assertContains(r, "Incorrect Link")
|
||||||
|
|
||||||
def test_post_works(self):
|
def test_it_serves_confirmation_form(self):
|
||||||
sig = signing.TimestampSigner(salt="reports").sign("alice")
|
sig = signing.TimestampSigner(salt="reports").sign("alice")
|
||||||
url = "/accounts/unsubscribe_reports/%s/" % sig
|
url = "/accounts/unsubscribe_reports/%s/" % sig
|
||||||
|
|
||||||
r = self.client.post(url)
|
|
||||||
self.assertContains(r, "Unsubscribed")
|
|
||||||
|
|
||||||
def test_it_serves_confirmation_form(self):
|
|
||||||
sig = signing.TimestampSigner(salt="reports").sign("alice")
|
|
||||||
url = "/accounts/unsubscribe_reports/%s/?ask=1" % sig
|
|
||||||
|
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertContains(r, "Please press the button below")
|
self.assertContains(r, "Please press the button below")
|
||||||
|
@ -442,7 +442,7 @@ def unsubscribe_reports(request, username):
|
|||||||
|
|
||||||
# Some email servers open links in emails to check for malicious content.
|
# Some email servers open links in emails to check for malicious content.
|
||||||
# To work around this, we serve a form that auto-submits with JS.
|
# To work around this, we serve a form that auto-submits with JS.
|
||||||
if "ask" in request.GET and request.method != "POST":
|
if request.method != "POST":
|
||||||
return render(request, "accounts/unsubscribe_submit.html")
|
return render(request, "accounts/unsubscribe_submit.html")
|
||||||
|
|
||||||
user = User.objects.get(username=username)
|
user = User.objects.get(username=username)
|
||||||
|
@ -49,3 +49,8 @@ class BounceTestCase(BaseTestCase):
|
|||||||
url = "/api/v1/notifications/%s/bounce" % fake_code
|
url = "/api/v1/notifications/%s/bounce" % fake_code
|
||||||
r = self.client.post(url, "", content_type="text/plain")
|
r = self.client.post(url, "", content_type="text/plain")
|
||||||
self.assertEqual(r.status_code, 404)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
|
def test_it_requires_post(self):
|
||||||
|
url = "/api/v1/notifications/%s/bounce" % self.n.code
|
||||||
|
r = self.client.get(url)
|
||||||
|
self.assertEqual(r.status_code, 405)
|
||||||
|
@ -14,6 +14,7 @@ from django.shortcuts import get_object_or_404
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.views.decorators.cache import never_cache
|
from django.views.decorators.cache import never_cache
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
from django.views.decorators.http import require_POST
|
||||||
|
|
||||||
from hc.api import schemas
|
from hc.api import schemas
|
||||||
from hc.api.decorators import authorize, authorize_read, cors, validate_json
|
from hc.api.decorators import authorize, authorize_read, cors, validate_json
|
||||||
@ -256,6 +257,7 @@ def badge(request, badge_key, signature, tag, fmt="svg"):
|
|||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
|
@require_POST
|
||||||
def bounce(request, code):
|
def bounce(request, code):
|
||||||
notification = get_object_or_404(Notification, code=code)
|
notification = get_object_or_404(Notification, code=code)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class UnsubscribeEmailTestCase(BaseTestCase):
|
|||||||
token = self.channel.make_token()
|
token = self.channel.make_token()
|
||||||
url = "/integrations/%s/unsub/%s/" % (self.channel.code, token)
|
url = "/integrations/%s/unsub/%s/" % (self.channel.code, token)
|
||||||
|
|
||||||
r = self.client.get(url)
|
r = self.client.post(url)
|
||||||
self.assertContains(r, "has been unsubscribed", status_code=200)
|
self.assertContains(r, "has been unsubscribed", status_code=200)
|
||||||
|
|
||||||
q = Channel.objects.filter(code=self.channel.code)
|
q = Channel.objects.filter(code=self.channel.code)
|
||||||
@ -35,16 +35,9 @@ class UnsubscribeEmailTestCase(BaseTestCase):
|
|||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertEqual(r.status_code, 400)
|
self.assertEqual(r.status_code, 400)
|
||||||
|
|
||||||
def test_post_works(self):
|
def test_it_serves_confirmation_form(self):
|
||||||
token = self.channel.make_token()
|
token = self.channel.make_token()
|
||||||
url = "/integrations/%s/unsub/%s/" % (self.channel.code, token)
|
url = "/integrations/%s/unsub/%s/" % (self.channel.code, token)
|
||||||
|
|
||||||
r = self.client.post(url)
|
|
||||||
self.assertContains(r, "has been unsubscribed", status_code=200)
|
|
||||||
|
|
||||||
def test_it_serves_confirmation_form(self):
|
|
||||||
token = self.channel.make_token()
|
|
||||||
url = "/integrations/%s/unsub/%s/?ask=1" % (self.channel.code, token)
|
|
||||||
|
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertContains(r, "Please press the button below")
|
self.assertContains(r, "Please press the button below")
|
||||||
|
@ -712,7 +712,7 @@ def unsubscribe_email(request, code, token):
|
|||||||
|
|
||||||
# Some email servers open links in emails to check for malicious content.
|
# Some email servers open links in emails to check for malicious content.
|
||||||
# To work around this, we serve a form that auto-submits with JS.
|
# To work around this, we serve a form that auto-submits with JS.
|
||||||
if "ask" in request.GET and request.method != "POST":
|
if request.method != "POST":
|
||||||
return render(request, "accounts/unsubscribe_submit.html")
|
return render(request, "accounts/unsubscribe_submit.html")
|
||||||
|
|
||||||
channel.delete()
|
channel.delete()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user