From 827939deb74182359312f01e7ba0faad3afb049f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Tue, 13 Mar 2018 14:08:45 +0200 Subject: [PATCH] Clean up Pushover subscription flow, add Setup Instructions with screenshots. --- ..._add_pushbover.py => test_add_pushover.py} | 52 ++++++---- hc/front/views.py | 40 ++++---- static/img/integrations/setup_pushover_1.png | Bin 0 -> 12636 bytes static/img/integrations/setup_pushover_2.png | Bin 0 -> 19945 bytes templates/integrations/add_pushover.html | 97 +++++++++++++++++- templates/integrations/add_slack.html | 6 +- 6 files changed, 147 insertions(+), 48 deletions(-) rename hc/front/tests/{test_add_pushbover.py => test_add_pushover.py} (55%) create mode 100644 static/img/integrations/setup_pushover_1.png create mode 100644 static/img/integrations/setup_pushover_2.png diff --git a/hc/front/tests/test_add_pushbover.py b/hc/front/tests/test_add_pushover.py similarity index 55% rename from hc/front/tests/test_add_pushbover.py rename to hc/front/tests/test_add_pushover.py index fc5b16f1..6f6d6be7 100644 --- a/hc/front/tests/test_add_pushbover.py +++ b/hc/front/tests/test_add_pushover.py @@ -3,52 +3,68 @@ from hc.api.models import Channel from hc.test import BaseTestCase -@override_settings(PUSHOVER_API_TOKEN="token", PUSHOVER_SUBSCRIPTION_URL="url") +@override_settings(PUSHOVER_API_TOKEN="token", PUSHOVER_SUBSCRIPTION_URL="http://example.org") class AddPushoverTestCase(BaseTestCase): - def test_instructions_work(self): + @override_settings(PUSHOVER_API_TOKEN=None) + def test_it_requires_api_token(self): + self.client.login(username="alice@example.org", password="password") + r = self.client.get("/integrations/add_pushover/") + self.assertEqual(r.status_code, 404) + + def test_instructions_work_without_login(self): + r = self.client.get("/integrations/add_pushover/") + self.assertContains(r, "Setup Guide") + + def test_it_shows_form(self): self.client.login(username="alice@example.org", password="password") r = self.client.get("/integrations/add_pushover/") self.assertContains(r, "Subscribe with Pushover") + def test_post_redirects(self): + self.client.login(username="alice@example.org", password="password") + payload = {"po_priority": 2} + r = self.client.post("/integrations/add_pushover/", form=payload) + self.assertEqual(r.status_code, 302) + + def test_post_requires_authenticated_user(self): + payload = {"po_priority": 2} + r = self.client.post("/integrations/add_pushover/", form=payload) + self.assertEqual(r.status_code, 200) + self.assertContains(r, "Setup Guide") + def test_it_adds_channel(self): self.client.login(username="alice@example.org", password="password") session = self.client.session - session["po_nonce"] = "n" + session["pushover"] = "foo" session.save() - params = "pushover_user_key=a&nonce=n&prio=0" + params = "pushover_user_key=a&state=foo&prio=0" r = self.client.get("/integrations/add_pushover/?%s" % params) - assert r.status_code == 302 + self.assertEqual(r.status_code, 302) channels = list(Channel.objects.all()) assert len(channels) == 1 assert channels[0].value == "a|0" - @override_settings(PUSHOVER_API_TOKEN=None) - def test_it_requires_api_token(self): - self.client.login(username="alice@example.org", password="password") - r = self.client.get("/integrations/add_pushover/") - self.assertEqual(r.status_code, 404) - def test_it_validates_priority(self): self.client.login(username="alice@example.org", password="password") session = self.client.session - session["po_nonce"] = "n" + session["pushover"] = "foo" session.save() - params = "pushover_user_key=a&nonce=n&prio=abc" + params = "pushover_user_key=a&state=foo&prio=abc" r = self.client.get("/integrations/add_pushover/?%s" % params) - assert r.status_code == 400 + self.assertEqual(r.status_code, 400) - def test_it_validates_nonce(self): + def test_it_validates_state(self): self.client.login(username="alice@example.org", password="password") session = self.client.session - session["po_nonce"] = "n" + session["pushover"] = "foo" session.save() - params = "pushover_user_key=a&nonce=INVALID&prio=0" + params = "pushover_user_key=a&state=INVALID&prio=0" r = self.client.get("/integrations/add_pushover/?%s" % params) - assert r.status_code == 403 + self.assertEqual(r.status_code, 400) diff --git a/hc/front/views.py b/hc/front/views.py index 18b6b86e..71a43b60 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -738,19 +738,21 @@ def add_discord(request): return render(request, "integrations/add_discord.html", ctx) -@login_required def add_pushover(request): if settings.PUSHOVER_API_TOKEN is None or settings.PUSHOVER_SUBSCRIPTION_URL is None: raise Http404("pushover integration is not available") + if not request.user.is_authenticated: + ctx = {"page": "channels"} + return render(request, "integrations/add_pushover.html", ctx) + if request.method == "POST": # Initiate the subscription - nonce = get_random_string() - request.session["po_nonce"] = nonce + state = _prepare_state(request, "pushover") failure_url = settings.SITE_ROOT + reverse("hc-channels") success_url = settings.SITE_ROOT + reverse("hc-add-pushover") + "?" + urlencode({ - "nonce": nonce, + "state": state, "prio": request.POST.get("po_priority", "0"), }) subscription_url = settings.PUSHOVER_SUBSCRIPTION_URL + "?" + urlencode({ @@ -762,34 +764,28 @@ def add_pushover(request): # Handle successful subscriptions if "pushover_user_key" in request.GET: - if "nonce" not in request.GET or "prio" not in request.GET: + key = _get_validated_code(request, "pushover", "pushover_user_key") + if key is None: return HttpResponseBadRequest() - # Validate nonce - if request.GET["nonce"] != request.session.get("po_nonce"): - return HttpResponseForbidden() - # Validate priority - if request.GET["prio"] not in ("-2", "-1", "0", "1", "2"): + prio = request.GET.get("prio") + if prio not in ("-2", "-1", "0", "1", "2"): return HttpResponseBadRequest() - # All looks well-- - del request.session["po_nonce"] - if request.GET.get("pushover_unsubscribed") == "1": # Unsubscription: delete all Pushover channels for this user Channel.objects.filter(user=request.user, kind="po").delete() return redirect("hc-channels") - else: - # Subscription - user_key = request.GET["pushover_user_key"] - priority = int(request.GET["prio"]) - channel = Channel(user=request.team.user, kind="po") - channel.value = "%s|%d" % (user_key, priority) - channel.save() - channel.assign_all_checks() - return redirect("hc-channels") + # Subscription + channel = Channel(user=request.team.user, kind="po") + channel.value = "%s|%s" % (key, prio) + channel.save() + channel.assign_all_checks() + + messages.success(request, "The Pushover integration has been added!") + return redirect("hc-channels") # Show Integration Settings form ctx = { diff --git a/static/img/integrations/setup_pushover_1.png b/static/img/integrations/setup_pushover_1.png new file mode 100644 index 0000000000000000000000000000000000000000..0daaf9123b9fa608108c00ad0e98eb3e4fa7cc5d GIT binary patch literal 12636 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%0A0p|6 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,kEkZ%y+^wvpE#>PigCw zp3K_V@4y6le8Y1OLPmL>)^>93%~U#l{8LMff>%aARz-8!IioFj6|&ejDR%k%rqh5Z zg4jW-xWkUb1K3ic2Y1dZRGVUexw=7MSYYr3l$#=x^Xh55UA{s>w=_{vnDZ(<-c2-j z`Hkh5DejBQd8=2~?n6Rca_9#lUxB0Uzh;|TM}UaV8RE@rfI{(fP4ToJaa@9A3F)RM z>i?i<&r!IrTN^7k>C|3bvnXwJ&N5dCBbY;F`6i|MzBaU+69w%>zSS?yvT%QV!hxdc zqU+-Rgm4cR4>(*dy!dt|I~v|IWrevFXG`XueIrDH(VBc=l1$PNfbWE*#kl4Ewh<6v z9~v0Gv)LfHNjZxb;8o+t0-Wo`4BM2|CU6d`z^2mmYhMn%jwaba4R^Qk{U{j zu?4I_Ro}gKp=sIY!#io3rbKOyPoZ(o_LQo`uRw@Sqw(r&#K zKlF68j#4o&Vt>5N{>*YZkpldAKkq3U(Rs{hJ@Y-OZrpy*g?$ES1& zeShf7?td~$a0LCq_w^O8NtEQyGUHlkHMXWbjE}cc#K-k^w=dP)#lZJ`n6Rf<9oU5$ zC~G^Rl!t@S51?L$?343YGd^$xk#yJBKfAyYgnRlYv!cgI>W@No>KaXaS)%)|tjMjZ zy%&Ot=-`0vqFLcvErB$G9x!8@Kj-{vV0_0v0g}W{(vYW0V~}D7>GF!ZCW{s%R+|*LWI{3h(J%cH@agPD;&J1^NZh&TMRpyRdx1Or#w#3tLQ<%<8 z6~1moH~)Z4A5k+X2)%9>W)t3{GKF?3EN-bqt$5`t#jlPeaPsM8tsQtZ3 zisGqyoC-cVMPK3gy-O)Gi<~d$SB%8D)T2a2@Rii_Ab(
-

Pushover

+
+ {% if request.user.is_authenticated %} +

+ Pushover delivers + real-time notifications on your Android, iPhone, iPad, and Desktop, + Android Wear and Apple Watch. You can set up {% site_name %} to + receive Pushover notifications in a few simple steps. +

+ {% else %} +

+ {% site_name %} is a free and + open source + service for monitoring your cron jobs, background processes and + scheduled tasks. Before adding Pushover integration, please log into + {% site_name %}:

-

Pushover is a service to receive - instant push notifications on your phone or tablet from a variety of - sources. If you bought the app on your mobile device, you can integrate it - with your {% site_name %} account in a few simple steps.

+
+
+ {% csrf_token %} +
+
+
@
+ +
+
+
+ +
+
+
+ {% endif %} +
+ + {% if not request.user.is_authenticated %} +

Setup Guide

+ +
+
+ 1 +

+ After logging in, go to "Integrations → Add Pushover". + Pushover supports different notification priorities from + silent to "Emergency". Select your preferred priority + and click "Subscribe with Pushover". +

+
+
+ Screenshot +
+
+ +
+
+ 2 +

+ You will be redirected to + pushover.net and + asked to confirm a subscription. Review the subscription + details and click "Subscribe Me". +

+
+
+ Screenshot +
+
+ +
+
+ 3 +

+ That is all! You will now be redirected back to + "Integrations" page on {% site_name %} and see + the new integration! +

+
+
+
+
+ {% else %}

Integration Settings

@@ -82,6 +168,7 @@
+ {% endif %} {% endblock %} diff --git a/templates/integrations/add_slack.html b/templates/integrations/add_slack.html index 05843a34..2e25a8d8 100644 --- a/templates/integrations/add_slack.html +++ b/templates/integrations/add_slack.html @@ -58,7 +58,7 @@
- 2 + 1

After {% if request.user.is_authenticated %}{% else %}logging in and{% endif %} clicking on "Add to Slack", you should @@ -77,7 +77,7 @@

- 3 + 2

You should now be on a page that says "{% site_name %} would like access to TEAM NAME". Select the channel you want to @@ -94,7 +94,7 @@

- 4 + 3

That is all! You will now be redirected back to "Integrations" page on {% site_name %} and see