Browse Source

"Filtering Rules" dialog, an option to require HTTP POST. Fixes #297

pull/313/head
Pēteris Caune 5 years ago
parent
commit
3f19181028
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
12 changed files with 129 additions and 15 deletions
  1. +8
    -0
      CHANGELOG.md
  2. +23
    -0
      hc/api/migrations/0065_auto_20191127_1240.py
  3. +2
    -0
      hc/api/models.py
  4. +15
    -0
      hc/api/tests/test_ping.py
  5. +3
    -0
      hc/api/views.py
  6. +2
    -1
      hc/front/forms.py
  7. +31
    -0
      hc/front/tests/test_filtering_rules.py
  8. +1
    -1
      hc/front/urls.py
  9. +4
    -3
      hc/front/views.py
  10. +2
    -2
      static/js/details.js
  11. +8
    -4
      templates/front/details.html
  12. +30
    -4
      templates/front/filtering_rules_modal.html

+ 8
- 0
CHANGELOG.md View File

@ -1,6 +1,12 @@
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased
### Improvements
- "Filtering Rules" dialog, an option to require HTTP POST (#297)
## 1.11.0 - 2019-11-22
### Improvements
@ -14,6 +20,7 @@ All notable changes to this project will be documented in this file.
- On mobile, "My Checks" page, always show the gear (Details) button (#286)
- Make log events fit better on mobile screens
## 1.10.0 - 2019-10-21
### Improvements
@ -80,6 +87,7 @@ All notable changes to this project will be documented in this file.
- Show the Description section even if the description is missing. (#246)
- Include the description in email alerts. (#247)
## 1.6.0 - 2019-04-01
### Improvements


+ 23
- 0
hc/api/migrations/0065_auto_20191127_1240.py View File

@ -0,0 +1,23 @@
# Generated by Django 2.2.6 on 2019-11-27 12:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0064_auto_20191119_1346'),
]
operations = [
migrations.AddField(
model_name='check',
name='methods',
field=models.CharField(blank=True, max_length=30),
),
migrations.AlterField(
model_name='channel',
name='kind',
field=models.CharField(choices=[('email', 'Email'), ('webhook', 'Webhook'), ('hipchat', 'HipChat'), ('slack', 'Slack'), ('pd', 'PagerDuty'), ('pagertree', 'PagerTree'), ('pagerteam', 'Pager Team'), ('po', 'Pushover'), ('pushbullet', 'Pushbullet'), ('opsgenie', 'OpsGenie'), ('victorops', 'VictorOps'), ('discord', 'Discord'), ('telegram', 'Telegram'), ('sms', 'SMS'), ('zendesk', 'Zendesk'), ('trello', 'Trello'), ('matrix', 'Matrix'), ('whatsapp', 'WhatsApp'), ('apprise', 'Apprise'), ('mattermost', 'Mattermost'), ('msteams', 'Microsoft Teams'), ('shell', 'Shell Command')], max_length=20),
),
]

+ 2
- 0
hc/api/models.py View File

@ -72,6 +72,8 @@ class Check(models.Model):
schedule = models.CharField(max_length=100, default="* * * * *")
tz = models.CharField(max_length=36, default="UTC")
subject = models.CharField(max_length=100, blank=True)
methods = models.CharField(max_length=30, blank=True)
n_pings = models.IntegerField(default=0)
last_ping = models.DateTimeField(null=True, blank=True)
last_start = models.DateTimeField(null=True, blank=True)


+ 15
- 0
hc/api/tests/test_ping.py View File

@ -186,3 +186,18 @@ class PingTestCase(BaseTestCase):
self.check.refresh_from_db()
self.assertTrue(self.check.last_duration.total_seconds() >= 10)
def test_it_requires_post(self):
self.check.methods = "POST"
self.check.save()
r = self.client.get("/ping/%s/" % self.check.code)
self.assertEqual(r.status_code, 200)
self.check.refresh_from_db()
self.assertEqual(self.check.status, "new")
self.assertIsNone(self.check.last_ping)
ping = Ping.objects.latest("id")
self.assertEqual(ping.scheme, "http")
self.assertEqual(ping.kind, "ign")

+ 3
- 0
hc/api/views.py View File

@ -34,6 +34,9 @@ def ping(request, code, action="success"):
ua = headers.get("HTTP_USER_AGENT", "")
body = request.body.decode()
if check.methods == "POST" and method != "POST":
action = "ign"
check.ping(remote_addr, scheme, method, ua, body, action)
response = HttpResponse("OK")


+ 2
- 1
hc/front/forms.py View File

@ -62,8 +62,9 @@ class NameTagsForm(forms.Form):
return " ".join(result)
class EmailSettingsForm(forms.Form):
class FilteringRulesForm(forms.Form):
subject = forms.CharField(max_length=100)
methods = forms.ChoiceField(required=False, choices=(("", "Any"), ("POST", "POST")))
class TimeoutForm(forms.Form):


+ 31
- 0
hc/front/tests/test_filtering_rules.py View File

@ -0,0 +1,31 @@
from hc.api.models import Check
from hc.test import BaseTestCase
class FilteringRulesTestCase(BaseTestCase):
def setUp(self):
super(FilteringRulesTestCase, self).setUp()
self.check = Check.objects.create(project=self.project)
self.url = "/checks/%s/filtering_rules/" % self.check.code
self.redirect_url = "/checks/%s/details/" % self.check.code
def test_it_works(self):
self.client.login(username="[email protected]", password="password")
r = self.client.post(self.url, data={"subject": "SUCCESS", "methods": "POST"})
self.assertRedirects(r, self.redirect_url)
self.check.refresh_from_db()
self.assertEqual(self.check.subject, "SUCCESS")
self.assertEqual(self.check.methods, "POST")
def test_it_clears_method(self):
self.check.method = "POST"
self.check.save()
self.client.login(username="[email protected]", password="password")
r = self.client.post(self.url, data={"subject": "SUCCESS", "methods": ""})
self.assertRedirects(r, self.redirect_url)
self.check.refresh_from_db()
self.assertEqual(self.check.methods, "")

+ 1
- 1
hc/front/urls.py View File

@ -5,7 +5,7 @@ from hc.front import views
check_urls = [
path("name/", views.update_name, name="hc-update-name"),
path("details/", views.details, name="hc-details"),
path("email_settings/", views.email_settings, name="hc-email-settings"),
path("filtering_rules/", views.filtering_rules, name="hc-filtering-rules"),
path("timeout/", views.update_timeout, name="hc-update-timeout"),
path("pause/", views.pause, name="hc-pause"),
path("remove/", views.remove_check, name="hc-remove-check"),


+ 4
- 3
hc/front/views.py View File

@ -45,7 +45,7 @@ from hc.front.forms import (
AddWebhookForm,
ChannelNameForm,
CronForm,
EmailSettingsForm,
FilteringRulesForm,
NameTagsForm,
TimeoutForm,
)
@ -334,11 +334,12 @@ def update_name(request, code):
@require_POST
@login_required
def email_settings(request, code):
def filtering_rules(request, code):
check = _get_check_for_user(request, code)
form = EmailSettingsForm(request.POST)
form = FilteringRulesForm(request.POST)
if form.is_valid():
check.subject = form.cleaned_data["subject"]
check.methods = form.cleaned_data["methods"]
check.save()
return redirect("hc-details", code)


+ 2
- 2
static/js/details.js View File

@ -25,7 +25,7 @@ $(function () {
$("#ping-now").click(function(e) {
var button = this;
$.get(this.dataset.url, function() {
$.post(this.dataset.url, function() {
button.textContent = "Success!";
});
});
@ -119,7 +119,7 @@ $(function () {
format == "local" ? dt.local() : dt.tz(format);
$(".date", row).text(dt.format("MMM D"));
$(".time", row).text(dt.format("HH:mm"));
$(".time", row).text(dt.format("HH:mm"));
})
// The table is initially hidden to avoid flickering as we convert dates.


+ 8
- 4
templates/front/details.html View File

@ -67,7 +67,11 @@
<div id="how-to-ping" class="details-block">
<h2>How To Ping</h2>
<div>
<p>Keep this check up by making HTTP requests to this URL:</p>
<p>
Keep this check up by making HTTP
{% if check.methods == "POST" %}POST{% endif %}
requests to this URL:
</p>
<code>{{ check.url }}</code>
<p>
{% if check.subject %}
@ -90,8 +94,8 @@
<div class="text-right">
<button
data-toggle="modal"
data-target="#email-settings-modal"
class="btn btn-sm btn-default">Email Settings&hellip;</button>
data-target="#filtering-rules-modal"
class="btn btn-sm btn-default">Filtering Rules&hellip;</button>
<button
data-toggle="modal"
data-target="#show-usage-modal"
@ -281,7 +285,7 @@
{% include "front/update_timeout_modal.html" %}
{% include "front/show_usage_modal.html" %}
{% include "front/remove_check_modal.html" %}
{% include "front/email_settings_modal.html" %}
{% include "front/filtering_rules_modal.html" %}
{% include "front/copy_modal.html" %}
{% endblock %}


templates/front/email_settings_modal.html → templates/front/filtering_rules_modal.html View File


Loading…
Cancel
Save