forked from GithubBackups/healthchecks
Preliminary Django 2 support
This commit is contained in:
parent
9bc0f1b82a
commit
ef6e1870d9
@ -81,7 +81,7 @@ class Profile(models.Model):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def prepare_token(self, salt):
|
def prepare_token(self, salt):
|
||||||
token = urlsafe_b64encode(os.urandom(24)).decode("utf-8")
|
token = urlsafe_b64encode(os.urandom(24)).decode()
|
||||||
self.token = make_password(token, salt)
|
self.token = make_password(token, salt)
|
||||||
self.save()
|
self.save()
|
||||||
return token
|
return token
|
||||||
|
@ -1,36 +1,36 @@
|
|||||||
from django.conf.urls import url
|
from django.urls import path
|
||||||
from hc.accounts import views
|
from hc.accounts import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^login/$', views.login, name="hc-login"),
|
path('login/', views.login, name="hc-login"),
|
||||||
url(r'^logout/$', views.logout, name="hc-logout"),
|
path('logout/', views.logout, name="hc-logout"),
|
||||||
url(r'^login_link_sent/$',
|
path('login_link_sent/',
|
||||||
views.login_link_sent, name="hc-login-link-sent"),
|
views.login_link_sent, name="hc-login-link-sent"),
|
||||||
|
|
||||||
url(r'^link_sent/$',
|
path('link_sent/',
|
||||||
views.link_sent, name="hc-link-sent"),
|
views.link_sent, name="hc-link-sent"),
|
||||||
|
|
||||||
url(r'^check_token/([\w-]+)/([\w-]+)/$',
|
path('check_token/<slug:username>/<slug:token>/',
|
||||||
views.check_token, name="hc-check-token"),
|
views.check_token, name="hc-check-token"),
|
||||||
|
|
||||||
url(r'^profile/$', views.profile, name="hc-profile"),
|
path('profile/', views.profile, name="hc-profile"),
|
||||||
url(r'^profile/notifications/$', views.notifications, name="hc-notifications"),
|
path('profile/notifications/', views.notifications, name="hc-notifications"),
|
||||||
url(r'^profile/badges/$', views.badges, name="hc-badges"),
|
path('profile/badges/', views.badges, name="hc-badges"),
|
||||||
url(r'^close/$', views.close, name="hc-close"),
|
path('close/', views.close, name="hc-close"),
|
||||||
|
|
||||||
url(r'^unsubscribe_reports/([\w\:-]+)/$',
|
path('unsubscribe_reports/<str:username>/',
|
||||||
views.unsubscribe_reports, name="hc-unsubscribe-reports"),
|
views.unsubscribe_reports, name="hc-unsubscribe-reports"),
|
||||||
|
|
||||||
url(r'^set_password/([\w-]+)/$',
|
path('set_password/<slug:token>/',
|
||||||
views.set_password, name="hc-set-password"),
|
views.set_password, name="hc-set-password"),
|
||||||
|
|
||||||
url(r'^change_email/done/$',
|
path('change_email/done/',
|
||||||
views.change_email_done, name="hc-change-email-done"),
|
views.change_email_done, name="hc-change-email-done"),
|
||||||
|
|
||||||
url(r'^change_email/([\w-]+)/$',
|
path('change_email/<slug:token>/',
|
||||||
views.change_email, name="hc-change-email"),
|
views.change_email, name="hc-change-email"),
|
||||||
|
|
||||||
url(r'^switch_team/([\w-]+)/$',
|
path('switch_team/<slug:target_username>/',
|
||||||
views.switch_team, name="hc-switch-team"),
|
views.switch_team, name="hc-switch-team"),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
@ -363,7 +363,7 @@ def unsubscribe_reports(request, username):
|
|||||||
# This is here for backwards compatibility and will be removed
|
# This is here for backwards compatibility and will be removed
|
||||||
# at some point.
|
# at some point.
|
||||||
try:
|
try:
|
||||||
signing.Signer().unsign(request.GET.get("token"))
|
signing.Signer().unsign(request.GET.get("token", ""))
|
||||||
except signing.BadSignature:
|
except signing.BadSignature:
|
||||||
return render(request, "bad_link.html")
|
return render(request, "bad_link.html")
|
||||||
|
|
||||||
|
@ -1,24 +1,10 @@
|
|||||||
import json
|
import json
|
||||||
import re
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.http import (HttpResponseBadRequest, HttpResponseForbidden,
|
from django.http import HttpResponseForbidden, JsonResponse
|
||||||
JsonResponse)
|
|
||||||
from hc.lib.jsonschema import ValidationError, validate
|
from hc.lib.jsonschema import ValidationError, validate
|
||||||
|
|
||||||
RE_UUID = re.compile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
|
|
||||||
|
|
||||||
|
|
||||||
def uuid_or_400(f):
|
|
||||||
@wraps(f)
|
|
||||||
def wrapper(request, *args, **kwds):
|
|
||||||
if not RE_UUID.match(args[0]):
|
|
||||||
return HttpResponseBadRequest()
|
|
||||||
|
|
||||||
return f(request, *args, **kwds)
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
def make_error(msg):
|
def make_error(msg):
|
||||||
return JsonResponse({"error": msg}, status=400)
|
return JsonResponse({"error": msg}, status=400)
|
||||||
@ -30,7 +16,7 @@ def check_api_key(f):
|
|||||||
request.json = {}
|
request.json = {}
|
||||||
if request.body:
|
if request.body:
|
||||||
try:
|
try:
|
||||||
request.json = json.loads(request.body.decode("utf-8"))
|
request.json = json.loads(request.body.decode())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return make_error("could not parse request body")
|
return make_error("could not parse request body")
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ class Channel(models.Model):
|
|||||||
|
|
||||||
def make_token(self):
|
def make_token(self):
|
||||||
seed = "%s%s" % (self.code, settings.SECRET_KEY)
|
seed = "%s%s" % (self.code, settings.SECRET_KEY)
|
||||||
seed = seed.encode("utf8")
|
seed = seed.encode()
|
||||||
return hashlib.sha1(seed).hexdigest()
|
return hashlib.sha1(seed).hexdigest()
|
||||||
|
|
||||||
def send_verify_link(self):
|
def send_verify_link(self):
|
||||||
|
@ -17,7 +17,7 @@ class BadgeTestCase(BaseTestCase):
|
|||||||
|
|
||||||
def test_it_returns_svg(self):
|
def test_it_returns_svg(self):
|
||||||
sig = base64_hmac(str(self.alice.username), "foo", settings.SECRET_KEY)
|
sig = base64_hmac(str(self.alice.username), "foo", settings.SECRET_KEY)
|
||||||
sig = sig[:8].decode("utf-8")
|
sig = sig[:8]
|
||||||
url = "/badge/%s/%s/foo.svg" % (self.alice.username, sig)
|
url = "/badge/%s/%s/foo.svg" % (self.alice.username, sig)
|
||||||
|
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
|
@ -102,7 +102,7 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
self.assertEqual(args[1], "http://example.com")
|
self.assertEqual(args[1], "http://example.com")
|
||||||
|
|
||||||
# spaces should not have been urlencoded:
|
# spaces should not have been urlencoded:
|
||||||
payload = kwargs["data"].decode("utf-8")
|
payload = kwargs["data"].decode()
|
||||||
self.assertTrue(payload.startswith("The Time Is 2"))
|
self.assertTrue(payload.startswith("The Time Is 2"))
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
|
@ -38,7 +38,7 @@ class PauseTestCase(BaseTestCase):
|
|||||||
r = self.client.post(url, "", content_type="application/json",
|
r = self.client.post(url, "", content_type="application/json",
|
||||||
HTTP_X_API_KEY="abc")
|
HTTP_X_API_KEY="abc")
|
||||||
|
|
||||||
self.assertEqual(r.status_code, 400)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_handles_missing_check(self):
|
def test_it_handles_missing_check(self):
|
||||||
url = "/api/v1/checks/07c2f548-9850-4b27-af5d-6c9dc157ec02/pause"
|
url = "/api/v1/checks/07c2f548-9850-4b27-af5d-6c9dc157ec02/pause"
|
||||||
|
@ -48,12 +48,12 @@ class PingTestCase(TestCase):
|
|||||||
|
|
||||||
def test_it_handles_bad_uuid(self):
|
def test_it_handles_bad_uuid(self):
|
||||||
r = self.client.get("/ping/not-uuid/")
|
r = self.client.get("/ping/not-uuid/")
|
||||||
self.assertEqual(r.status_code, 400)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_rejects_alternative_uuid_formats(self):
|
def test_it_rejects_alternative_uuid_formats(self):
|
||||||
# This uuid is missing separators. uuid.UUID() would accept it.
|
# This uuid is missing separators. uuid.UUID() would accept it.
|
||||||
r = self.client.get("/ping/07c2f54898504b27af5d6c9dc157ec02/")
|
r = self.client.get("/ping/07c2f54898504b27af5d6c9dc157ec02/")
|
||||||
self.assertEqual(r.status_code, 400)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_handles_missing_check(self):
|
def test_it_handles_missing_check(self):
|
||||||
r = self.client.get("/ping/07c2f548-9850-4b27-af5d-6c9dc157ec02/")
|
r = self.client.get("/ping/07c2f548-9850-4b27-af5d-6c9dc157ec02/")
|
||||||
|
@ -69,7 +69,7 @@ class UpdateCheckTestCase(BaseTestCase):
|
|||||||
|
|
||||||
def test_it_handles_invalid_uuid(self):
|
def test_it_handles_invalid_uuid(self):
|
||||||
r = self.post("not-an-uuid", {"api_key": "abc"})
|
r = self.post("not-an-uuid", {"api_key": "abc"})
|
||||||
self.assertEqual(r.status_code, 400)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_handles_missing_check(self):
|
def test_it_handles_missing_check(self):
|
||||||
made_up_code = "07c2f548-9850-4b27-af5d-6c9dc157ec02"
|
made_up_code = "07c2f548-9850-4b27-af5d-6c9dc157ec02"
|
||||||
|
@ -184,7 +184,7 @@ class Webhook(HttpTransport):
|
|||||||
|
|
||||||
if self.channel.post_data:
|
if self.channel.post_data:
|
||||||
payload = self.prepare(self.channel.post_data, check)
|
payload = self.prepare(self.channel.post_data, check)
|
||||||
return self.post(url, data=payload.encode("utf-8"), headers=headers)
|
return self.post(url, data=payload.encode(), headers=headers)
|
||||||
else:
|
else:
|
||||||
return self.get(url, headers=headers)
|
return self.get(url, headers=headers)
|
||||||
|
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
from django.conf.urls import url
|
from django.urls import path
|
||||||
|
|
||||||
from hc.api import views
|
from hc.api import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^ping/([\w-]+)/$', views.ping, name="hc-ping-slash"),
|
path('ping/<uuid:code>/', views.ping, name="hc-ping-slash"),
|
||||||
url(r'^ping/([\w-]+)$', views.ping, name="hc-ping"),
|
path('ping/<uuid:code>', views.ping, name="hc-ping"),
|
||||||
url(r'^api/v1/checks/$', views.checks),
|
path('api/v1/checks/', views.checks),
|
||||||
url(r'^api/v1/checks/([\w-]+)$', views.update, name="hc-api-update"),
|
path('api/v1/checks/<uuid:code>', views.update, name="hc-api-update"),
|
||||||
url(r'^api/v1/checks/([\w-]+)/pause$', views.pause, name="hc-api-pause"),
|
path('api/v1/checks/<uuid:code>/pause', views.pause, name="hc-api-pause"),
|
||||||
url(r'^api/v1/notifications/([\w-]+)/bounce$', views.bounce,
|
path('api/v1/notifications/<uuid:code>/bounce', views.bounce,
|
||||||
name="hc-api-bounce"),
|
name="hc-api-bounce"),
|
||||||
|
|
||||||
url(r'^badge/([\w-]+)/([\w-]{8})/([\w-]+).svg$', views.badge,
|
path('badge/<slug:username>/<slug:signature>/<slug:tag>.svg', views.badge,
|
||||||
name="hc-badge"),
|
name="hc-badge"),
|
||||||
|
|
||||||
url(r'^badge/([\w-]+)/([\w-]{8}).svg$', views.badge,
|
path('badge/<slug:username>/<slug:signature>.svg', views.badge,
|
||||||
{"tag": "*"}, name="hc-badge-all"),
|
{"tag": "*"}, name="hc-badge-all"),
|
||||||
|
|
||||||
url(r'^badge/([\w-]+)/([\w-]{8})/([\w-]+).json$', views.badge,
|
path('badge/<slug:username>/<slug:signature>/<slug:tag>.json', views.badge,
|
||||||
{"format": "json"}, name="hc-badge-json"),
|
{"format": "json"}, name="hc-badge-json"),
|
||||||
|
|
||||||
url(r'^badge/([\w-]+)/([\w-]{8}).json$', views.badge,
|
path('badge/<slug:username>/<slug:signature>.json', views.badge,
|
||||||
{"format": "json", "tag": "*"}, name="hc-badge-json-all"),
|
{"format": "json", "tag": "*"}, name="hc-badge-json-all"),
|
||||||
|
|
||||||
url(r'^api/v1/status/$', views.status),
|
path('api/v1/status/', views.status),
|
||||||
]
|
]
|
||||||
|
@ -11,13 +11,12 @@ from django.views.decorators.csrf import csrf_exempt
|
|||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
|
|
||||||
from hc.api import schemas
|
from hc.api import schemas
|
||||||
from hc.api.decorators import check_api_key, uuid_or_400, validate_json
|
from hc.api.decorators import check_api_key, validate_json
|
||||||
from hc.api.models import Check, Notification
|
from hc.api.models import Check, Notification
|
||||||
from hc.lib.badges import check_signature, get_badge_svg
|
from hc.lib.badges import check_signature, get_badge_svg
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@uuid_or_400
|
|
||||||
@never_cache
|
@never_cache
|
||||||
def ping(request, code):
|
def ping(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = get_object_or_404(Check, code=code)
|
||||||
@ -28,8 +27,9 @@ def ping(request, code):
|
|||||||
scheme = headers.get("HTTP_X_FORWARDED_PROTO", "http")
|
scheme = headers.get("HTTP_X_FORWARDED_PROTO", "http")
|
||||||
method = headers["REQUEST_METHOD"]
|
method = headers["REQUEST_METHOD"]
|
||||||
ua = headers.get("HTTP_USER_AGENT", "")
|
ua = headers.get("HTTP_USER_AGENT", "")
|
||||||
|
body = request.body.decode()
|
||||||
|
|
||||||
check.ping(remote_addr, scheme, method, ua, request.body)
|
check.ping(remote_addr, scheme, method, ua, body)
|
||||||
|
|
||||||
response = HttpResponse("OK")
|
response = HttpResponse("OK")
|
||||||
response["Access-Control-Allow-Origin"] = "*"
|
response["Access-Control-Allow-Origin"] = "*"
|
||||||
@ -127,7 +127,6 @@ def checks(request):
|
|||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@uuid_or_400
|
|
||||||
@check_api_key
|
@check_api_key
|
||||||
@validate_json(schemas.check)
|
@validate_json(schemas.check)
|
||||||
def update(request, code):
|
def update(request, code):
|
||||||
@ -150,7 +149,6 @@ def update(request, code):
|
|||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@require_POST
|
@require_POST
|
||||||
@uuid_or_400
|
|
||||||
@check_api_key
|
@check_api_key
|
||||||
def pause(request, code):
|
def pause(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = get_object_or_404(Check, code=code)
|
||||||
@ -194,7 +192,6 @@ def badge(request, username, signature, tag, format="svg"):
|
|||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@uuid_or_400
|
|
||||||
def bounce(request, code):
|
def bounce(request, code):
|
||||||
notification = get_object_or_404(Notification, code=code)
|
notification = get_object_or_404(Notification, code=code)
|
||||||
|
|
||||||
@ -203,7 +200,7 @@ def bounce(request, code):
|
|||||||
if td.total_seconds() > 600:
|
if td.total_seconds() > 600:
|
||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
notification.error = request.body[:200]
|
notification.error = request.body.decode()[:200]
|
||||||
notification.save()
|
notification.save()
|
||||||
|
|
||||||
notification.channel.email_verified = False
|
notification.channel.email_verified = False
|
||||||
|
@ -38,7 +38,7 @@ class LogTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
assert r.status_code == 400
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_handles_missing_uuid(self):
|
def test_it_handles_missing_uuid(self):
|
||||||
# Valid UUID but there is no check for it:
|
# Valid UUID but there is no check for it:
|
||||||
|
@ -31,7 +31,7 @@ class RemoveChannelTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(url)
|
r = self.client.post(url)
|
||||||
assert r.status_code == 400
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_checks_owner(self):
|
def test_it_checks_owner(self):
|
||||||
url = "/integrations/%s/remove/" % self.channel.code
|
url = "/integrations/%s/remove/" % self.channel.code
|
||||||
|
@ -32,7 +32,7 @@ class RemoveCheckTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(url)
|
r = self.client.post(url)
|
||||||
assert r.status_code == 400
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_checks_owner(self):
|
def test_it_checks_owner(self):
|
||||||
url = "/checks/%s/remove/" % self.check.code
|
url = "/checks/%s/remove/" % self.check.code
|
||||||
|
@ -46,7 +46,7 @@ class UpdateNameTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(url, data=payload)
|
r = self.client.post(url, data=payload)
|
||||||
assert r.status_code == 400
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_handles_missing_uuid(self):
|
def test_it_handles_missing_uuid(self):
|
||||||
# Valid UUID but there is no check for it:
|
# Valid UUID but there is no check for it:
|
||||||
|
@ -128,7 +128,7 @@ class UpdateTimeoutTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(url, data=payload)
|
r = self.client.post(url, data=payload)
|
||||||
assert r.status_code == 400
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_handles_missing_uuid(self):
|
def test_it_handles_missing_uuid(self):
|
||||||
# Valid UUID but there is no check for it:
|
# Valid UUID but there is no check for it:
|
||||||
|
@ -1,55 +1,55 @@
|
|||||||
from django.conf.urls import include, url
|
from django.urls import include, path
|
||||||
|
|
||||||
from hc.front import views
|
from hc.front import views
|
||||||
|
|
||||||
check_urls = [
|
check_urls = [
|
||||||
url(r'^name/$', views.update_name, name="hc-update-name"),
|
path('name/', views.update_name, name="hc-update-name"),
|
||||||
url(r'^timeout/$', views.update_timeout, name="hc-update-timeout"),
|
path('timeout/', views.update_timeout, name="hc-update-timeout"),
|
||||||
url(r'^pause/$', views.pause, name="hc-pause"),
|
path('pause/', views.pause, name="hc-pause"),
|
||||||
url(r'^remove/$', views.remove_check, name="hc-remove-check"),
|
path('remove/', views.remove_check, name="hc-remove-check"),
|
||||||
url(r'^log/$', views.log, name="hc-log"),
|
path('log/', views.log, name="hc-log"),
|
||||||
url(r'^last_ping/$', views.ping_details, name="hc-last-ping"),
|
path('last_ping/', views.ping_details, name="hc-last-ping"),
|
||||||
url(r'^pings/([\d]+)/$', views.ping_details, name="hc-ping-details"),
|
path('pings/<int:n>/', views.ping_details, name="hc-ping-details"),
|
||||||
]
|
]
|
||||||
|
|
||||||
channel_urls = [
|
channel_urls = [
|
||||||
url(r'^$', views.channels, name="hc-channels"),
|
path('', views.channels, name="hc-channels"),
|
||||||
url(r'^add_email/$', views.add_email, name="hc-add-email"),
|
path('add_email/', views.add_email, name="hc-add-email"),
|
||||||
url(r'^add_webhook/$', views.add_webhook, name="hc-add-webhook"),
|
path('add_webhook/', views.add_webhook, name="hc-add-webhook"),
|
||||||
url(r'^add_pd/$', views.add_pd, name="hc-add-pd"),
|
path('add_pd/', views.add_pd, name="hc-add-pd"),
|
||||||
url(r'^add_pd/([\w]{12})/$', views.add_pd, name="hc-add-pd-state"),
|
path('add_pd/<str:state>/', views.add_pd, name="hc-add-pd-state"),
|
||||||
url(r'^add_pagertree/$', views.add_pagertree, name="hc-add-pagertree"),
|
path('add_pagertree/', views.add_pagertree, name="hc-add-pagertree"),
|
||||||
url(r'^add_slack/$', views.add_slack, name="hc-add-slack"),
|
path('add_slack/', views.add_slack, name="hc-add-slack"),
|
||||||
url(r'^add_slack_btn/$', views.add_slack_btn, name="hc-add-slack-btn"),
|
path('add_slack_btn/', views.add_slack_btn, name="hc-add-slack-btn"),
|
||||||
url(r'^add_hipchat/$', views.add_hipchat, name="hc-add-hipchat"),
|
path('add_hipchat/', views.add_hipchat, name="hc-add-hipchat"),
|
||||||
url(r'^hipchat/capabilities/$', views.hipchat_capabilities, name="hc-hipchat-capabilities"),
|
path('hipchat/capabilities/', views.hipchat_capabilities, name="hc-hipchat-capabilities"),
|
||||||
url(r'^add_pushbullet/$', views.add_pushbullet, name="hc-add-pushbullet"),
|
path('add_pushbullet/', views.add_pushbullet, name="hc-add-pushbullet"),
|
||||||
url(r'^add_discord/$', views.add_discord, name="hc-add-discord"),
|
path('add_discord/', views.add_discord, name="hc-add-discord"),
|
||||||
url(r'^add_pushover/$', views.add_pushover, name="hc-add-pushover"),
|
path('add_pushover/', views.add_pushover, name="hc-add-pushover"),
|
||||||
url(r'^add_opsgenie/$', views.add_opsgenie, name="hc-add-opsgenie"),
|
path('add_opsgenie/', views.add_opsgenie, name="hc-add-opsgenie"),
|
||||||
url(r'^add_victorops/$', views.add_victorops, name="hc-add-victorops"),
|
path('add_victorops/', views.add_victorops, name="hc-add-victorops"),
|
||||||
url(r'^telegram/bot/$', views.telegram_bot, name="hc-telegram-webhook"),
|
path('telegram/bot/', views.telegram_bot, name="hc-telegram-webhook"),
|
||||||
url(r'^add_telegram/$', views.add_telegram, name="hc-add-telegram"),
|
path('add_telegram/', views.add_telegram, name="hc-add-telegram"),
|
||||||
url(r'^add_sms/$', views.add_sms, name="hc-add-sms"),
|
path('add_sms/', views.add_sms, name="hc-add-sms"),
|
||||||
url(r'^add_zendesk/$', views.add_zendesk, name="hc-add-zendesk"),
|
path('add_zendesk/', views.add_zendesk, name="hc-add-zendesk"),
|
||||||
url(r'^([\w-]+)/checks/$', views.channel_checks, name="hc-channel-checks"),
|
path('<uuid:code>/checks/', views.channel_checks, name="hc-channel-checks"),
|
||||||
url(r'^([\w-]+)/remove/$', views.remove_channel, name="hc-remove-channel"),
|
path('<uuid:code>/remove/', views.remove_channel, name="hc-remove-channel"),
|
||||||
url(r'^([\w-]+)/verify/([\w-]+)/$', views.verify_email,
|
path('<uuid:code>/verify/<slug:token>/', views.verify_email,
|
||||||
name="hc-verify-email"),
|
name="hc-verify-email"),
|
||||||
url(r'^([\w-]+)/unsub/([\w-]+)/$', views.unsubscribe_email,
|
path('<uuid:code>/unsub/<slug:token>/', views.unsubscribe_email,
|
||||||
name="hc-unsubscribe-alerts"),
|
name="hc-unsubscribe-alerts"),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', views.index, name="hc-index"),
|
path('', views.index, name="hc-index"),
|
||||||
url(r'^checks/$', views.my_checks, name="hc-checks"),
|
path('checks/', views.my_checks, name="hc-checks"),
|
||||||
url(r'^checks/add/$', views.add_check, name="hc-add-check"),
|
path('checks/add/', views.add_check, name="hc-add-check"),
|
||||||
url(r'^checks/cron_preview/$', views.cron_preview),
|
path('checks/cron_preview/', views.cron_preview),
|
||||||
url(r'^checks/status/$', views.status),
|
path('checks/status/', views.status),
|
||||||
url(r'^checks/([\w-]+)/', include(check_urls)),
|
path('checks/<uuid:code>/', include(check_urls)),
|
||||||
url(r'^integrations/', include(channel_urls)),
|
path('integrations/', include(channel_urls)),
|
||||||
|
|
||||||
url(r'^docs/$', views.docs, name="hc-docs"),
|
path('docs/', views.docs, name="hc-docs"),
|
||||||
url(r'^docs/api/$', views.docs_api, name="hc-docs-api"),
|
path('docs/api/', views.docs_api, name="hc-docs-api"),
|
||||||
url(r'^docs/cron/$', views.docs_cron, name="hc-docs-cron"),
|
path('docs/cron/', views.docs_cron, name="hc-docs-cron"),
|
||||||
]
|
]
|
||||||
|
@ -17,7 +17,6 @@ from django.utils import timezone
|
|||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
from hc.api.decorators import uuid_or_400
|
|
||||||
from hc.api.models import (DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check,
|
from hc.api.models import (DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check,
|
||||||
Ping, Notification)
|
Ping, Notification)
|
||||||
from hc.api.transports import Telegram
|
from hc.api.transports import Telegram
|
||||||
@ -178,7 +177,6 @@ def add_check(request):
|
|||||||
|
|
||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
@uuid_or_400
|
|
||||||
def update_name(request, code):
|
def update_name(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = get_object_or_404(Check, code=code)
|
||||||
if check.user_id != request.team.user.id:
|
if check.user_id != request.team.user.id:
|
||||||
@ -195,7 +193,6 @@ def update_name(request, code):
|
|||||||
|
|
||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
@uuid_or_400
|
|
||||||
def update_timeout(request, code):
|
def update_timeout(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = get_object_or_404(Check, code=code)
|
||||||
if check.user != request.team.user:
|
if check.user != request.team.user:
|
||||||
@ -273,7 +270,6 @@ def ping_details(request, code, n=None):
|
|||||||
|
|
||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
@uuid_or_400
|
|
||||||
def pause(request, code):
|
def pause(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = get_object_or_404(Check, code=code)
|
||||||
if check.user_id != request.team.user.id:
|
if check.user_id != request.team.user.id:
|
||||||
@ -287,7 +283,6 @@ def pause(request, code):
|
|||||||
|
|
||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
@uuid_or_400
|
|
||||||
def remove_check(request, code):
|
def remove_check(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = get_object_or_404(Check, code=code)
|
||||||
if check.user != request.team.user:
|
if check.user != request.team.user:
|
||||||
@ -299,7 +294,6 @@ def remove_check(request, code):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@uuid_or_400
|
|
||||||
def log(request, code):
|
def log(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = get_object_or_404(Check, code=code)
|
||||||
if check.user != request.team.user:
|
if check.user != request.team.user:
|
||||||
@ -384,7 +378,6 @@ def channels(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@uuid_or_400
|
|
||||||
def channel_checks(request, code):
|
def channel_checks(request, code):
|
||||||
channel = get_object_or_404(Channel, code=code)
|
channel = get_object_or_404(Channel, code=code)
|
||||||
if channel.user_id != request.team.user.id:
|
if channel.user_id != request.team.user.id:
|
||||||
@ -402,7 +395,6 @@ def channel_checks(request, code):
|
|||||||
return render(request, "front/channel_checks.html", ctx)
|
return render(request, "front/channel_checks.html", ctx)
|
||||||
|
|
||||||
|
|
||||||
@uuid_or_400
|
|
||||||
def verify_email(request, code, token):
|
def verify_email(request, code, token):
|
||||||
channel = get_object_or_404(Channel, code=code)
|
channel = get_object_or_404(Channel, code=code)
|
||||||
if channel.make_token() == token:
|
if channel.make_token() == token:
|
||||||
@ -413,7 +405,6 @@ def verify_email(request, code, token):
|
|||||||
return render(request, "bad_link.html")
|
return render(request, "bad_link.html")
|
||||||
|
|
||||||
|
|
||||||
@uuid_or_400
|
|
||||||
def unsubscribe_email(request, code, token):
|
def unsubscribe_email(request, code, token):
|
||||||
channel = get_object_or_404(Channel, code=code)
|
channel = get_object_or_404(Channel, code=code)
|
||||||
if channel.make_token() != token:
|
if channel.make_token() != token:
|
||||||
@ -428,7 +419,6 @@ def unsubscribe_email(request, code, token):
|
|||||||
|
|
||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
@uuid_or_400
|
|
||||||
def remove_channel(request, code):
|
def remove_channel(request, code):
|
||||||
# user may refresh the page during POST and cause two deletion attempts
|
# user may refresh the page during POST and cause two deletion attempts
|
||||||
channel = Channel.objects.filter(code=code).first()
|
channel = Channel.objects.filter(code=code).first()
|
||||||
@ -503,7 +493,7 @@ def add_pd(request, state=None):
|
|||||||
if settings.PD_VENDOR_KEY is None:
|
if settings.PD_VENDOR_KEY is None:
|
||||||
raise Http404("pagerduty integration is not available")
|
raise Http404("pagerduty integration is not available")
|
||||||
|
|
||||||
if state and request.user.is_authenticated():
|
if state and request.user.is_authenticated:
|
||||||
if "pd" not in request.session:
|
if "pd" not in request.session:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
@ -537,6 +527,7 @@ def add_pd(request, state=None):
|
|||||||
ctx = {"page": "channels", "connect_url": connect_url}
|
ctx = {"page": "channels", "connect_url": connect_url}
|
||||||
return render(request, "integrations/add_pd.html", ctx)
|
return render(request, "integrations/add_pd.html", ctx)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def add_pagertree(request):
|
def add_pagertree(request):
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
@ -840,7 +831,7 @@ def add_victorops(request):
|
|||||||
@require_POST
|
@require_POST
|
||||||
def telegram_bot(request):
|
def telegram_bot(request):
|
||||||
try:
|
try:
|
||||||
doc = json.loads(request.body.decode("utf-8"))
|
doc = json.loads(request.body.decode())
|
||||||
jsonschema.validate(doc, telegram_callback)
|
jsonschema.validate(doc, telegram_callback)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
|
@ -45,7 +45,7 @@ def get_badge_svg(tag, status):
|
|||||||
|
|
||||||
def check_signature(username, tag, sig):
|
def check_signature(username, tag, sig):
|
||||||
ours = base64_hmac(str(username), tag, settings.SECRET_KEY)
|
ours = base64_hmac(str(username), tag, settings.SECRET_KEY)
|
||||||
ours = ours[:8].decode("utf-8")
|
ours = ours[:8]
|
||||||
return ours == sig
|
return ours == sig
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from hc.accounts.models import Profile
|
from hc.accounts.models import Profile
|
||||||
from hc.payments.models import Subscription
|
from hc.payments.models import Subscription
|
||||||
|
|
||||||
|
@ -1,39 +1,39 @@
|
|||||||
from django.conf.urls import url
|
from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^pricing/$',
|
path('pricing/',
|
||||||
views.pricing,
|
views.pricing,
|
||||||
name="hc-pricing"),
|
name="hc-pricing"),
|
||||||
|
|
||||||
url(r'^accounts/profile/billing/$',
|
path('accounts/profile/billing/',
|
||||||
views.billing,
|
views.billing,
|
||||||
name="hc-billing"),
|
name="hc-billing"),
|
||||||
|
|
||||||
url(r'^accounts/profile/billing/history/$',
|
path('accounts/profile/billing/history/',
|
||||||
views.billing_history,
|
views.billing_history,
|
||||||
name="hc-billing-history"),
|
name="hc-billing-history"),
|
||||||
|
|
||||||
url(r'^accounts/profile/billing/address/$',
|
path('accounts/profile/billing/address/',
|
||||||
views.address,
|
views.address,
|
||||||
name="hc-billing-address"),
|
name="hc-billing-address"),
|
||||||
|
|
||||||
url(r'^accounts/profile/billing/payment_method/$',
|
path('accounts/profile/billing/payment_method/',
|
||||||
views.payment_method,
|
views.payment_method,
|
||||||
name="hc-payment-method"),
|
name="hc-payment-method"),
|
||||||
|
|
||||||
url(r'^invoice/pdf/([\w-]+)/$',
|
path('invoice/pdf/<slug:transaction_id>/',
|
||||||
views.pdf_invoice,
|
views.pdf_invoice,
|
||||||
name="hc-invoice-pdf"),
|
name="hc-invoice-pdf"),
|
||||||
|
|
||||||
url(r'^pricing/set_plan/$',
|
path('pricing/set_plan/',
|
||||||
views.set_plan,
|
views.set_plan,
|
||||||
name="hc-set-plan"),
|
name="hc-set-plan"),
|
||||||
|
|
||||||
url(r'^pricing/get_client_token/$',
|
path('pricing/get_client_token/',
|
||||||
views.get_client_token,
|
views.get_client_token,
|
||||||
name="hc-get-client-token"),
|
name="hc-get-client-token"),
|
||||||
|
|
||||||
url(r'^pricing/charge/$', views.charge_webhook),
|
path('pricing/charge/', views.charge_webhook),
|
||||||
]
|
]
|
||||||
|
14
hc/urls.py
14
hc/urls.py
@ -1,13 +1,13 @@
|
|||||||
from django.conf.urls import include, url
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.urls import include, path
|
||||||
|
|
||||||
from hc.accounts.views import login as hc_login
|
from hc.accounts.views import login as hc_login
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^admin/login/', hc_login, {"show_password": True}),
|
path('admin/login/', hc_login, {"show_password": True}),
|
||||||
url(r'^admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
url(r'^accounts/', include('hc.accounts.urls')),
|
path('accounts/', include('hc.accounts.urls')),
|
||||||
url(r'^', include('hc.api.urls')),
|
path('', include('hc.api.urls')),
|
||||||
url(r'^', include('hc.front.urls')),
|
path('', include('hc.front.urls')),
|
||||||
url(r'^', include('hc.payments.urls'))
|
path('', include('hc.payments.urls'))
|
||||||
]
|
]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
croniter
|
croniter
|
||||||
Django==1.11.6
|
Django==2.0.4
|
||||||
django_compressor==2.1
|
django_compressor==2.1
|
||||||
psycopg2==2.7.3.2
|
psycopg2==2.7.3.2
|
||||||
pytz==2016.7
|
pytz==2016.7
|
||||||
|
Loading…
x
Reference in New Issue
Block a user