diff --git a/hc/front/tests/test_add_pushover.py b/hc/front/tests/test_add_pushover.py index fe55ff49..a9ff4761 100644 --- a/hc/front/tests/test_add_pushover.py +++ b/hc/front/tests/test_add_pushover.py @@ -7,10 +7,14 @@ from hc.test import BaseTestCase PUSHOVER_API_TOKEN="token", PUSHOVER_SUBSCRIPTION_URL="http://example.org" ) class AddPushoverTestCase(BaseTestCase): + def setUp(self): + super(AddPushoverTestCase, self).setUp() + self.url = "/projects/%s/add_pushover/" % self.project.code + @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/") + r = self.client.get(self.url) self.assertEqual(r.status_code, 404) def test_instructions_work_without_login(self): @@ -19,20 +23,18 @@ class AddPushoverTestCase(BaseTestCase): def test_it_shows_form(self): self.client.login(username="alice@example.org", password="password") - r = self.client.get("/integrations/add_pushover/") + r = self.client.get(self.url) 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) + r = self.client.post(self.url, 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_requires_authenticated_user(self): + r = self.client.get(self.url) + self.assertRedirects(r, "/accounts/login/?next=" + self.url) def test_it_adds_channel(self): self.client.login(username="alice@example.org", password="password") @@ -41,9 +43,9 @@ class AddPushoverTestCase(BaseTestCase): session["pushover"] = "foo" session.save() - params = "pushover_user_key=a&state=foo&prio=0&prio_up=-1" - r = self.client.get("/integrations/add_pushover/?%s" % params) - self.assertEqual(r.status_code, 302) + params = "?pushover_user_key=a&state=foo&prio=0&prio_up=-1" + r = self.client.get(self.url + params, follow=True) + self.assertRedirects(r, self.channels_url) channel = Channel.objects.get() self.assertEqual(channel.value, "a|0|-1") @@ -56,8 +58,8 @@ class AddPushoverTestCase(BaseTestCase): session["pushover"] = "foo" session.save() - params = "pushover_user_key=a&state=foo&prio=abc" - r = self.client.get("/integrations/add_pushover/?%s" % params) + params = "?pushover_user_key=a&state=foo&prio=abc" + r = self.client.get(self.url + params) self.assertEqual(r.status_code, 400) def test_it_validates_priority_up(self): @@ -67,8 +69,8 @@ class AddPushoverTestCase(BaseTestCase): session["pushover"] = "foo" session.save() - params = "pushover_user_key=a&state=foo&prio_up=abc" - r = self.client.get("/integrations/add_pushover/?%s" % params) + params = "?pushover_user_key=a&state=foo&prio_up=abc" + r = self.client.get(self.url + params) self.assertEqual(r.status_code, 400) def test_it_validates_state(self): @@ -78,6 +80,6 @@ class AddPushoverTestCase(BaseTestCase): session["pushover"] = "foo" session.save() - params = "pushover_user_key=a&state=INVALID&prio=0" - r = self.client.get("/integrations/add_pushover/?%s" % params) - self.assertEqual(r.status_code, 400) + params = "?pushover_user_key=a&state=INVALID&prio=0" + r = self.client.get(self.url + params) + self.assertEqual(r.status_code, 403) diff --git a/hc/front/urls.py b/hc/front/urls.py index 37150578..aa12f1cc 100644 --- a/hc/front/urls.py +++ b/hc/front/urls.py @@ -32,7 +32,7 @@ channel_urls = [ name="hc-add-pushbullet-complete", ), path("add_discord/", views.add_discord_complete, name="hc-add-discord-complete"), - path("add_pushover/", views.add_pushover, name="hc-add-pushover"), + path("add_pushover/", views.add_pushover_help), path("telegram/bot/", views.telegram_bot, name="hc-telegram-webhook"), path("add_telegram/", views.add_telegram, name="hc-add-telegram"), path("add_trello/", views.add_trello, name="hc-add-trello"), @@ -66,6 +66,7 @@ project_urls = [ path("add_pdc//", views.add_pdc, name="hc-add-pdc-state"), path("add_prometheus/", views.add_prometheus, name="hc-add-prometheus"), path("add_pushbullet/", views.add_pushbullet, name="hc-add-pushbullet"), + path("add_pushover/", views.add_pushover, name="hc-add-pushover"), path("add_shell/", views.add_shell, name="hc-add-shell"), path("add_sms/", views.add_sms, name="hc-add-sms"), path("add_victorops/", views.add_victorops, name="hc-add-victorops"), diff --git a/hc/front/views.py b/hc/front/views.py index f5463460..1e136d3e 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -1241,25 +1241,26 @@ def add_discord_complete(request): return redirect("hc-p-channels", project.code) -def add_pushover(request): - if ( - settings.PUSHOVER_API_TOKEN is None - or settings.PUSHOVER_SUBSCRIPTION_URL is None - ): +def add_pushover_help(request): + ctx = {"page": "channels"} + return render(request, "integrations/add_pushover_help.html", ctx) + + +@login_required +def add_pushover(request, code): + if settings.PUSHOVER_API_TOKEN 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) + project = _get_project_for_user(request, code) if request.method == "POST": # Initiate the subscription - state = _prepare_state(request, "pushover") + state = token_urlsafe() - failure_url = settings.SITE_ROOT + reverse("hc-channels") + failure_url = settings.SITE_ROOT + reverse("hc-p-channels", args=[project.code]) success_url = ( settings.SITE_ROOT - + reverse("hc-add-pushover") + + reverse("hc-add-pushover", args=[project.code]) + "?" + urlencode( { @@ -1275,11 +1276,19 @@ def add_pushover(request): + urlencode({"success": success_url, "failure": failure_url}) ) + request.session["pushover"] = state return redirect(subscription_url) # Handle successful subscriptions if "pushover_user_key" in request.GET: - key = _get_validated_code(request, "pushover", "pushover_user_key") + if "pushover" not in request.session: + return HttpResponseForbidden() + + state = request.session.pop("pushover") + if request.GET.get("state") != state: + return HttpResponseForbidden() + + key = request.GET.get("pushover_user_key") if key is None: return HttpResponseBadRequest() @@ -1294,22 +1303,22 @@ def add_pushover(request): if request.GET.get("pushover_unsubscribed") == "1": # Unsubscription: delete all Pushover channels for this project - Channel.objects.filter(project=request.project, kind="po").delete() + Channel.objects.filter(project=project, kind="po").delete() return redirect("hc-channels") # Subscription - channel = Channel(project=request.project, kind="po") + channel = Channel(project=project, kind="po") channel.value = "%s|%s|%s" % (key, prio, prio_up) channel.save() channel.assign_all_checks() messages.success(request, "The Pushover integration has been added!") - return redirect("hc-channels") + return redirect("hc-p-channels", project.code) # Show Integration Settings form ctx = { "page": "channels", - "project": request.project, + "project": project, "po_retry_delay": td(seconds=settings.PUSHOVER_EMERGENCY_RETRY_DELAY), "po_expiration": td(seconds=settings.PUSHOVER_EMERGENCY_EXPIRATION), } diff --git a/templates/front/channels.html b/templates/front/channels.html index 2a55a7bd..a3943e64 100644 --- a/templates/front/channels.html +++ b/templates/front/channels.html @@ -308,7 +308,7 @@

Pushover

Receive instant push notifications on your phone or tablet.

- Add Integration + Add Integration {% endif %} diff --git a/templates/integrations/add_pushover.html b/templates/integrations/add_pushover.html index 9c165eab..b7db892b 100644 --- a/templates/integrations/add_pushover.html +++ b/templates/integrations/add_pushover.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% load compress humanize static hc_extras %} -{% block title %}Add Pushover - {% site_name %}{% endblock %} +{% block title %}Pushover Integration for {% site_name %}{% endblock %} {% block content %} @@ -9,88 +9,17 @@

Pushover

- {% if request.user.is_authenticated %}

Pushover delivers real-time notifications on your Android, iPhone, iPad, 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 %}:

- -
- Sign In -
- {% 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 priorities - 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! -

-
-
- Screenshot -
- {% else %}

Integration Settings

-
+ {% csrf_token %}
@@ -163,7 +92,6 @@
- {% endif %} {% endblock %} diff --git a/templates/integrations/add_pushover_help.html b/templates/integrations/add_pushover_help.html new file mode 100644 index 00000000..f10f320b --- /dev/null +++ b/templates/integrations/add_pushover_help.html @@ -0,0 +1,82 @@ +{% extends "base.html" %} +{% load compress humanize static hc_extras %} + +{% block title %}Pushover Integration for {% site_name %}{% endblock %} + +{% block content %} +
+
+

Pushover

+
+

+ {% 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 %}:

+ +
+ Sign In +
+
+ +

Setup Guide

+ +
+
+ 1 +

+ After logging in, go to "Integrations → Add Pushover". + Pushover supports different notification priorities from + silent to "Emergency". Select your preferred priorities + 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! +

+
+
+ Screenshot +
+
+ +
+
+{% endblock %} +