forked from GithubBackups/healthchecks
"Filtering Rules" dialog, an option to require HTTP POST. Fixes #297
This commit is contained in:
parent
89a5fbb7f9
commit
3f19181028
@ -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
hc/api/migrations/0065_auto_20191127_1240.py
Normal file
23
hc/api/migrations/0065_auto_20191127_1240.py
Normal 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),
|
||||
),
|
||||
]
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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
hc/front/tests/test_filtering_rules.py
Normal file
31
hc/front/tests/test_filtering_rules.py
Normal 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="alice@example.org", 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="alice@example.org", 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, "")
|
@ -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"),
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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…</button>
|
||||
data-target="#filtering-rules-modal"
|
||||
class="btn btn-sm btn-default">Filtering Rules…</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 %}
|
||||
|
@ -1,18 +1,44 @@
|
||||
{% load hc_extras %}
|
||||
|
||||
<div id="email-settings-modal" class="modal">
|
||||
<div id="filtering-rules-modal" class="modal">
|
||||
<div class="modal-dialog">
|
||||
<form
|
||||
action="{% url 'hc-email-settings' check.code %}"
|
||||
action="{% url 'hc-filtering-rules' check.code %}"
|
||||
class="form-horizontal"
|
||||
method="post">
|
||||
{% csrf_token %}
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="update-timeout-title">Inbound Email Settings</h4>
|
||||
<h4>Filtering Rules</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Allowed request methods for HTTP requests:</p>
|
||||
<label class="radio-container">
|
||||
<input
|
||||
type="radio"
|
||||
name="methods"
|
||||
value=""
|
||||
{% if check.methods == "" %} checked {% endif %}>
|
||||
<span class="radiomark"></span>
|
||||
HEAD, GET, POST, PUT
|
||||
</label>
|
||||
<label class="radio-container">
|
||||
<input
|
||||
type="radio"
|
||||
name="methods"
|
||||
value="POST"
|
||||
{% if check.methods == "POST" %} checked {% endif %}>
|
||||
<span class="radiomark"></span>
|
||||
Only POST
|
||||
<span class="help-block">
|
||||
If set, {% site_name %} will ignore HTTP requests
|
||||
using any other request method.
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<p>Filtering of Inbound Email Messages</p>
|
||||
<div class="form-group">
|
||||
<label for="update-name-input" class="col-sm-4 control-label">
|
||||
Subject Must Contain
|
Loading…
x
Reference in New Issue
Block a user