forked from GithubBackups/healthchecks
"Unsubscribe" link in alert emails. Fixes #111
This commit is contained in:
parent
c16eeda004
commit
6a1c5dd3b7
@ -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":
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
||||
|
38
hc/front/tests/test_unsubscribe_email.py
Normal file
38
hc/front/tests/test_unsubscribe_email.py
Normal file
@ -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)
|
@ -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
|
||||
|
@ -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 = [
|
||||
|
@ -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):
|
||||
|
@ -4,10 +4,10 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-sm-offset-3">
|
||||
<div class="hc-dialog">
|
||||
<h1>Incorrect Verification Link</h1>
|
||||
<h1>Incorrect Confirmation Link</h1>
|
||||
<div class="dialog-body">
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
@ -15,13 +15,13 @@ Here is a summary of all your checks:
|
||||
|
||||
{% include "emails/summary-html.html" %}
|
||||
|
||||
{% if show_upgrade_note %}
|
||||
<strong>P.S.</strong>
|
||||
Find this service useful? Support it by upgrading to
|
||||
a <a href="https://healthchecks.io/pricing/">premium account</a>!
|
||||
<br /><br />
|
||||
{% endif %}
|
||||
|
||||
Thanks,<br>
|
||||
The {% escaped_site_name %} Team
|
||||
{% endblock %}
|
||||
|
||||
{% block unsub %}
|
||||
<br>
|
||||
<a href="{{ unsub_link }}" target="_blank" style="color: #666666; text-decoration: underline;">
|
||||
Unsubscribe
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
19
templates/front/unsubscribe_success.html
Normal file
19
templates/front/unsubscribe_success.html
Normal file
@ -0,0 +1,19 @@
|
||||
{% extends "base.html" %}
|
||||
{% load hc_extras %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-sm-offset-3">
|
||||
<div class="hc-dialog">
|
||||
<h1>Unsubscribed</h1>
|
||||
<div class="dialog-body">
|
||||
<p>
|
||||
Your email address has been unsubscribed from
|
||||
{% site_name %} notifications.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user