diff --git a/hc/api/models.py b/hc/api/models.py index 5f0c4223..14dd3279 100644 --- a/hc/api/models.py +++ b/hc/api/models.py @@ -229,6 +229,11 @@ class Channel(models.Model): verify_link = settings.SITE_ROOT + verify_link emails.verify_email(self.value, {"verify_link": verify_link}) + def get_unsub_link(self): + args = [self.code, self.make_token()] + verify_link = reverse("hc-unsubscribe-alerts", args=args) + return settings.SITE_ROOT + verify_link + @property def transport(self): if self.kind == "email": diff --git a/hc/api/tests/test_notify.py b/hc/api/tests/test_notify.py index aeb6c158..a5b6acac 100644 --- a/hc/api/tests/test_notify.py +++ b/hc/api/tests/test_notify.py @@ -146,23 +146,6 @@ class NotifyTestCase(BaseTestCase): self.assertEqual(n.error, "Email not verified") self.assertEqual(len(mail.outbox), 0) - @override_settings(USE_PAYMENTS=True) - def test_email_contains_upgrade_notice(self): - self._setup_data("email", "alice@example.org", status="up") - self.profile.team_access_allowed = False - self.profile.save() - - self.channel.notify(self.check) - - n = Notification.objects.get() - self.assertEqual(n.error, "") - - # Check is up, payments are enabled, and the user does not have team - # access: the email should contain upgrade note - message = mail.outbox[0] - html, _ = message.alternatives[0] - assert "/pricing/" in html - @patch("hc.api.transports.requests.request") def test_pd(self, mock_post): self._setup_data("pd", "123") diff --git a/hc/api/transports.py b/hc/api/transports.py index 893547b1..910ce65c 100644 --- a/hc/api/transports.py +++ b/hc/api/transports.py @@ -46,16 +46,11 @@ class Email(Transport): if not self.channel.email_verified: return "Email not verified" - show_upgrade_note = False - if settings.USE_PAYMENTS and check.status == "up": - if not check.user.profile.team_access_allowed: - show_upgrade_note = True - ctx = { "check": check, "checks": self.checks(), "now": timezone.now(), - "show_upgrade_note": show_upgrade_note + "unsub_link": self.channel.get_unsub_link() } emails.alert(self.channel.value, ctx) diff --git a/hc/front/tests/test_unsubscribe_email.py b/hc/front/tests/test_unsubscribe_email.py new file mode 100644 index 00000000..a6c8fcab --- /dev/null +++ b/hc/front/tests/test_unsubscribe_email.py @@ -0,0 +1,38 @@ +from hc.api.models import Channel +from hc.test import BaseTestCase + + +class UnsubscribeEmailTestCase(BaseTestCase): + + def setUp(self): + super(UnsubscribeEmailTestCase, self).setUp() + self.channel = Channel(user=self.alice, kind="email") + self.channel.value = "alice@example.org" + self.channel.save() + + def test_it_works(self): + token = self.channel.make_token() + url = "/integrations/%s/unsub/%s/" % (self.channel.code, token) + + r = self.client.get(url) + self.assertContains(r, "has been unsubscribed", status_code=200) + + q = Channel.objects.filter(code=self.channel.code) + self.assertEqual(q.count(), 0) + + def test_it_checks_token(self): + url = "/integrations/%s/unsub/faketoken/" % self.channel.code + + r = self.client.get(url) + self.assertContains(r, "link you just used is incorrect", + status_code=200) + + def test_it_checks_channel_kind(self): + self.channel.kind = "webhook" + self.channel.save() + + token = self.channel.make_token() + url = "/integrations/%s/unsub/%s/" % (self.channel.code, token) + + r = self.client.get(url) + self.assertEqual(r.status_code, 400) diff --git a/hc/front/tests/test_verify_email.py b/hc/front/tests/test_verify_email.py index 3d24d217..5ad56703 100644 --- a/hc/front/tests/test_verify_email.py +++ b/hc/front/tests/test_verify_email.py @@ -14,7 +14,7 @@ class VerifyEmailTestCase(BaseTestCase): token = self.channel.make_token() url = "/integrations/%s/verify/%s/" % (self.channel.code, token) - r = self.client.post(url) + r = self.client.get(url) assert r.status_code == 200, r.status_code channel = Channel.objects.get(code=self.channel.code) @@ -23,7 +23,7 @@ class VerifyEmailTestCase(BaseTestCase): def test_it_handles_bad_token(self): url = "/integrations/%s/verify/bad-token/" % self.channel.code - r = self.client.post(url) + r = self.client.get(url) assert r.status_code == 200, r.status_code channel = Channel.objects.get(code=self.channel.code) @@ -35,5 +35,5 @@ class VerifyEmailTestCase(BaseTestCase): token = self.channel.make_token() url = "/integrations/%s/verify/%s/" % (code, token) - r = self.client.post(url) + r = self.client.get(url) assert r.status_code == 404 diff --git a/hc/front/urls.py b/hc/front/urls.py index 0147e80f..244b1917 100644 --- a/hc/front/urls.py +++ b/hc/front/urls.py @@ -27,6 +27,8 @@ channel_urls = [ url(r'^([\w-]+)/remove/$', views.remove_channel, name="hc-remove-channel"), url(r'^([\w-]+)/verify/([\w-]+)/$', views.verify_email, name="hc-verify-email"), + url(r'^([\w-]+)/unsub/([\w-]+)/$', views.unsubscribe_email, + name="hc-unsubscribe-alerts"), ] urlpatterns = [ diff --git a/hc/front/views.py b/hc/front/views.py index 47c6a90e..14fc98c2 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -361,6 +361,19 @@ def verify_email(request, code, token): return render(request, "bad_link.html") +@uuid_or_400 +def unsubscribe_email(request, code, token): + channel = get_object_or_404(Channel, code=code) + if channel.make_token() != token: + return render(request, "bad_link.html") + + if channel.kind != "email": + return HttpResponseBadRequest() + + channel.delete() + return render(request, "front/unsubscribe_success.html") + + @login_required @uuid_or_400 def remove_channel(request, code): diff --git a/templates/bad_link.html b/templates/bad_link.html index d5a5877e..38c5a6b7 100644 --- a/templates/bad_link.html +++ b/templates/bad_link.html @@ -4,10 +4,10 @@
-

Incorrect Verification Link

+

Incorrect Confirmation Link

- The verification link you just used is incorrect. + The confirmation link you just used is incorrect. If you copy-pasted the link, please make sure you did not miss any characters.

diff --git a/templates/emails/alert-body-html.html b/templates/emails/alert-body-html.html index f97c5b87..c626420c 100644 --- a/templates/emails/alert-body-html.html +++ b/templates/emails/alert-body-html.html @@ -15,13 +15,13 @@ Here is a summary of all your checks: {% include "emails/summary-html.html" %} -{% if show_upgrade_note %} -P.S. -Find this service useful? Support it by upgrading to -a premium account! -

-{% endif %} - Thanks,
The {% escaped_site_name %} Team {% endblock %} + +{% block unsub %} +
+ + Unsubscribe + +{% endblock %} diff --git a/templates/front/unsubscribe_success.html b/templates/front/unsubscribe_success.html new file mode 100644 index 00000000..55188024 --- /dev/null +++ b/templates/front/unsubscribe_success.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} +{% load hc_extras %} + +{% block content %} +
+
+
+

Unsubscribed

+
+

+ Your email address has been unsubscribed from + {% site_name %} notifications. +

+
+
+
+
+ +{% endblock %}