Set Pushover alert priorities for "down" and "up" events separately. Fixes #204

This commit is contained in:
Pēteris Caune 2018-11-28 21:40:46 +02:00
parent 2e6d050656
commit fb45b67892
No known key found for this signature in database
GPG Key ID: E28D7679E9A9EDE2
10 changed files with 123 additions and 72 deletions

View File

@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file.
## Unreleased ## Unreleased
### Improvements
- Set Pushover alert priorities for "down" and "up" events separately
### Bug Fixes ### Bug Fixes
- Fix after-login redirects for users landing in the "Add Slack" page - Fix after-login redirects for users landing in the "Add Slack" page

View File

@ -339,11 +339,11 @@ class Channel(models.Model):
return 'img/integrations/%s.png' % self.kind return 'img/integrations/%s.png' % self.kind
@property @property
def po_value(self): def po_priority(self):
assert self.kind == "po" assert self.kind == "po"
user_key, prio = self.value.split("|") parts = self.value.split("|")
prio = int(prio) prio = int(parts[1])
return user_key, prio, PO_PRIORITIES[prio] return PO_PRIORITIES[prio]
@property @property
def url_down(self): def url_down(self):

View File

@ -405,6 +405,21 @@ class NotifyTestCase(BaseTestCase):
payload = kwargs["data"] payload = kwargs["data"]
self.assertIn("DOWN", payload["title"]) self.assertIn("DOWN", payload["title"])
@patch("hc.api.transports.requests.request")
def test_pushover_up_priority(self, mock_post):
self._setup_data("po", "123|0|2", status="up")
mock_post.return_value.status_code = 200
self.channel.notify(self.check)
assert Notification.objects.count() == 1
args, kwargs = mock_post.call_args
payload = kwargs["data"]
self.assertIn("UP", payload["title"])
self.assertEqual(payload["priority"], 2)
self.assertIn("retry", payload)
self.assertIn("expire", payload)
@patch("hc.api.transports.requests.request") @patch("hc.api.transports.requests.request")
def test_victorops(self, mock_post): def test_victorops(self, mock_post):
self._setup_data("victorops", "123") self._setup_data("victorops", "123")

View File

@ -304,7 +304,13 @@ class Pushover(HttpTransport):
} }
text = tmpl("pushover_message.html", **ctx) text = tmpl("pushover_message.html", **ctx)
title = tmpl("pushover_title.html", **ctx) title = tmpl("pushover_title.html", **ctx)
user_key, prio = self.channel.value.split("|")
pieces = self.channel.value.split("|")
user_key, prio = pieces[0], pieces[1]
# The third element, if present, is the priority for "up" events
if len(pieces) == 3 and check.status == "up":
prio = pieces[2]
payload = { payload = {
"token": settings.PUSHOVER_API_TOKEN, "token": settings.PUSHOVER_API_TOKEN,
"user": user_key, "user": user_key,

View File

@ -39,13 +39,13 @@ class AddPushoverTestCase(BaseTestCase):
session["pushover"] = "foo" session["pushover"] = "foo"
session.save() session.save()
params = "pushover_user_key=a&state=foo&prio=0" params = "pushover_user_key=a&state=foo&prio=0&prio_up=-1"
r = self.client.get("/integrations/add_pushover/?%s" % params) r = self.client.get("/integrations/add_pushover/?%s" % params)
self.assertEqual(r.status_code, 302) self.assertEqual(r.status_code, 302)
channels = list(Channel.objects.all()) channels = list(Channel.objects.all())
assert len(channels) == 1 assert len(channels) == 1
assert channels[0].value == "a|0" assert channels[0].value == "a|0|-1"
def test_it_validates_priority(self): def test_it_validates_priority(self):
self.client.login(username="alice@example.org", password="password") self.client.login(username="alice@example.org", password="password")
@ -58,6 +58,17 @@ class AddPushoverTestCase(BaseTestCase):
r = self.client.get("/integrations/add_pushover/?%s" % params) r = self.client.get("/integrations/add_pushover/?%s" % params)
self.assertEqual(r.status_code, 400) self.assertEqual(r.status_code, 400)
def test_it_validates_priority_up(self):
self.client.login(username="alice@example.org", password="password")
session = self.client.session
session["pushover"] = "foo"
session.save()
params = "pushover_user_key=a&state=foo&prio_up=abc"
r = self.client.get("/integrations/add_pushover/?%s" % params)
self.assertEqual(r.status_code, 400)
def test_it_validates_state(self): def test_it_validates_state(self):
self.client.login(username="alice@example.org", password="password") self.client.login(username="alice@example.org", password="password")

View File

@ -873,6 +873,7 @@ def add_pushover(request):
success_url = settings.SITE_ROOT + reverse("hc-add-pushover") + "?" + urlencode({ success_url = settings.SITE_ROOT + reverse("hc-add-pushover") + "?" + urlencode({
"state": state, "state": state,
"prio": request.POST.get("po_priority", "0"), "prio": request.POST.get("po_priority", "0"),
"prio_up": request.POST.get("po_priority_up", "0")
}) })
subscription_url = settings.PUSHOVER_SUBSCRIPTION_URL + "?" + urlencode({ subscription_url = settings.PUSHOVER_SUBSCRIPTION_URL + "?" + urlencode({
"success": success_url, "success": success_url,
@ -892,6 +893,10 @@ def add_pushover(request):
if prio not in ("-2", "-1", "0", "1", "2"): if prio not in ("-2", "-1", "0", "1", "2"):
return HttpResponseBadRequest() return HttpResponseBadRequest()
prio_up = request.GET.get("prio_up")
if prio_up not in ("-2", "-1", "0", "1", "2"):
return HttpResponseBadRequest()
if request.GET.get("pushover_unsubscribed") == "1": if request.GET.get("pushover_unsubscribed") == "1":
# Unsubscription: delete all Pushover channels for this user # Unsubscription: delete all Pushover channels for this user
Channel.objects.filter(user=request.user, kind="po").delete() Channel.objects.filter(user=request.user, kind="po").delete()
@ -899,7 +904,7 @@ def add_pushover(request):
# Subscription # Subscription
channel = Channel(user=request.team.user, kind="po") channel = Channel(user=request.team.user, kind="po")
channel.value = "%s|%s" % (key, prio) channel.value = "%s|%s|%s" % (key, prio, prio_up)
channel.save() channel.save()
channel.assign_all_checks() channel.assign_all_checks()

View File

@ -1,8 +1,3 @@
#add-pushover .radio {
margin-bottom: 1em;
}
#add-pushover .help { #add-pushover .help {
display: block; opacity: 0.6;
color: #888;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -54,7 +54,7 @@
{% elif ch.kind == "victorops" %} {% elif ch.kind == "victorops" %}
VictorOps VictorOps
{% elif ch.kind == "po" %} {% elif ch.kind == "po" %}
Pushover ({{ ch.po_value|last }} priority) Pushover ({{ ch.po_priority }} priority)
{% elif ch.kind == "slack" %} {% elif ch.kind == "slack" %}
Slack Slack
{% if ch.slack_team %} {% if ch.slack_team %}

View File

@ -1,5 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load humanize static hc_extras %} {% load compress humanize static hc_extras %}
{% block title %}Add Pushover - {% site_name %}{% endblock %} {% block title %}Add Pushover - {% site_name %}{% endblock %}
@ -56,7 +56,7 @@
<p> <p>
After logging in, go to "Integrations &rarr; Add Pushover". After logging in, go to "Integrations &rarr; Add Pushover".
Pushover supports different notification priorities from Pushover supports different notification priorities from
silent to "Emergency". Select your preferred priority silent to "Emergency". Select your preferred priorities
and click "Subscribe with Pushover". and click "Subscribe with Pushover".
</p> </p>
</div> </div>
@ -106,65 +106,72 @@
{% else %} {% else %}
<h2>Integration Settings</h2> <h2>Integration Settings</h2>
<form method="post" id="add-pushover" class="form-horizontal" action="{% url 'hc-add-pushover' %}"> <form id="add-pushover" method="post" class="form-horizontal" action="{% url 'hc-add-pushover' %}">
{% csrf_token %} {% csrf_token %}
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label">Notification priority</label> <label class="col-sm-3 control-label">Priority for "down" events</label>
<div class="col-sm-6"> <div class="col-sm-8">
<div class="radio"> <select name="po_priority" class="selectpicker form-control">
<label> <option
<input type="radio" name="po_priority" value="-2"> value="-2"
Lowest Priority. data-content="Lowest Priority. <span class='help'>Generates no notification on your device.</span>">
<span class="help"> Lowest Priority
Generates no notification/alert on your device. </option>
On iOS, the application badge number will be increased. <option
</span> value="-1"
</label> data-content="Low Priority. <span class='help'>Sends a quiet notification.</span>">
Low Priority
</option>
<option value="0" selected="selected">
Normal Priority
</option>
<option
value="1"
data-content="High Priority. <span class='help'>Bypasses user's quiet hours.</span>">
High Priority
</option>
<option
value="2"
data-content="Emergency Priority. <span class='help'>Repeated every {{po_retry_delay|hc_duration }} for at most {{ po_expiration|hc_duration }} until you acknowledge them.</span>">
Emergency Priority
</option>
</select>
</div>
</div> </div>
<div class="radio">
<label>
<input type="radio" name="po_priority" value="-1">
Low Priority.
<span class="help">
Sends a quiet notification.
</span>
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="po_priority" value="0" checked>
Normal Priority.
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="po_priority" value="1">
<span class="text-warning">High Priority.</span>
<span class="help">
Bypasses user's quiet hours.
</span>
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="po_priority" value="2">
<span class="text-danger">Emergency Priority.</span>
<span class="help">
The notification is repeated every
{{po_retry_delay|hc_duration }} for at most
{{ po_expiration|hc_duration }} until you
acknowledge them.
</span>
</label>
</div>
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <label class="col-sm-3 control-label">Priority for "up" events</label>
<div class="col-sm-8">
<select name="po_priority_up" class="selectpicker form-control">
<option
value="-2"
data-content="Lowest Priority. <span class='help'>Generates no notification on your device.</span>">
Lowest Priority
</option>
<option
value="-1"
data-content="Low Priority. <span class='help'>Sends a quiet notification.</span>">
Low Priority
</option>
<option value="0" selected="selected">
Normal Priority
</option>
<option
value="1"
data-content="High Priority. <span class='help'>Bypasses user's quiet hours.</span>">
High Priority
</option>
<option
value="2"
data-content="Emergency Priority. <span class='help'>Repeated every {{po_retry_delay|hc_duration }} for at most {{ po_expiration|hc_duration }} until you acknowledge them.</span>">
Emergency Priority
</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-8">
<button type="submit" class="btn btn-default"> <button type="submit" class="btn btn-default">
<img class="ai-icon" src="{% static 'img/integrations/po.png' %}" alt="Pushover" /> <img class="ai-icon" src="{% static 'img/integrations/po.png' %}" alt="Pushover" />
Subscribe with Pushover Subscribe with Pushover
@ -176,3 +183,11 @@
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block scripts %}
{% compress js %}
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/bootstrap-select.min.js' %}"></script>
{% endcompress %}
{% endblock %}