Browse Source

Preliminary Django 2 support

pull/165/head
Pēteris Caune 7 years ago
parent
commit
ef6e1870d9
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
25 changed files with 143 additions and 169 deletions
  1. +1
    -1
      hc/accounts/models.py
  2. +23
    -23
      hc/accounts/urls.py
  3. +1
    -1
      hc/accounts/views.py
  4. +2
    -16
      hc/api/decorators.py
  5. +1
    -1
      hc/api/models.py
  6. +1
    -1
      hc/api/tests/test_badge.py
  7. +1
    -1
      hc/api/tests/test_notify.py
  8. +1
    -1
      hc/api/tests/test_pause.py
  9. +2
    -2
      hc/api/tests/test_ping.py
  10. +1
    -1
      hc/api/tests/test_update_check.py
  11. +1
    -1
      hc/api/transports.py
  12. +17
    -17
      hc/api/urls.py
  13. +4
    -7
      hc/api/views.py
  14. +1
    -1
      hc/front/tests/test_log.py
  15. +1
    -1
      hc/front/tests/test_remove_channel.py
  16. +1
    -1
      hc/front/tests/test_remove_check.py
  17. +1
    -1
      hc/front/tests/test_update_name.py
  18. +1
    -1
      hc/front/tests/test_update_timeout.py
  19. +43
    -43
      hc/front/urls.py
  20. +3
    -12
      hc/front/views.py
  21. +1
    -1
      hc/lib/badges.py
  22. +1
    -1
      hc/payments/admin.py
  23. +26
    -26
      hc/payments/urls.py
  24. +7
    -7
      hc/urls.py
  25. +1
    -1
      requirements.txt

+ 1
- 1
hc/accounts/models.py View File

@ -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


+ 23
- 23
hc/accounts/urls.py View File

@ -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"),
url(r'^logout/$', views.logout, name="hc-logout"),
url(r'^login_link_sent/$',
views.login_link_sent, name="hc-login-link-sent"),
path('login/', views.login, name="hc-login"),
path('logout/', views.logout, name="hc-logout"),
path('login_link_sent/',
views.login_link_sent, name="hc-login-link-sent"),
url(r'^link_sent/$',
views.link_sent, name="hc-link-sent"),
path('link_sent/',
views.link_sent, name="hc-link-sent"),
url(r'^check_token/([\w-]+)/([\w-]+)/$',
views.check_token, name="hc-check-token"),
path('check_token/<slug:username>/<slug:token>/',
views.check_token, name="hc-check-token"),
url(r'^profile/$', views.profile, name="hc-profile"),
url(r'^profile/notifications/$', views.notifications, name="hc-notifications"),
url(r'^profile/badges/$', views.badges, name="hc-badges"),
url(r'^close/$', views.close, name="hc-close"),
path('profile/', views.profile, name="hc-profile"),
path('profile/notifications/', views.notifications, name="hc-notifications"),
path('profile/badges/', views.badges, name="hc-badges"),
path('close/', views.close, name="hc-close"),
url(r'^unsubscribe_reports/([\w\:-]+)/$',
views.unsubscribe_reports, name="hc-unsubscribe-reports"),
path('unsubscribe_reports/<str:username>/',
views.unsubscribe_reports, name="hc-unsubscribe-reports"),
url(r'^set_password/([\w-]+)/$',
views.set_password, name="hc-set-password"),
path('set_password/<slug:token>/',
views.set_password, name="hc-set-password"),
url(r'^change_email/done/$',
views.change_email_done, name="hc-change-email-done"),
path('change_email/done/',
views.change_email_done, name="hc-change-email-done"),
url(r'^change_email/([\w-]+)/$',
views.change_email, name="hc-change-email"),
path('change_email/<slug:token>/',
views.change_email, name="hc-change-email"),
url(r'^switch_team/([\w-]+)/$',
views.switch_team, name="hc-switch-team"),
path('switch_team/<slug:target_username>/',
views.switch_team, name="hc-switch-team"),
] ]

+ 1
- 1
hc/accounts/views.py View File

@ -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")


+ 2
- 16
hc/api/decorators.py View File

@ -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,
JsonResponse)
from django.http import HttpResponseForbidden, 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")


+ 1
- 1
hc/api/models.py View File

@ -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):


+ 1
- 1
hc/api/tests/test_badge.py View File

@ -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)


+ 1
- 1
hc/api/tests/test_notify.py View File

@ -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")


+ 1
- 1
hc/api/tests/test_pause.py View File

@ -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"


+ 2
- 2
hc/api/tests/test_ping.py View File

@ -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/")


+ 1
- 1
hc/api/tests/test_update_check.py View File

@ -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"


+ 1
- 1
hc/api/transports.py View File

@ -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)


+ 17
- 17
hc/api/urls.py View File

@ -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"),
url(r'^ping/([\w-]+)$', views.ping, name="hc-ping"),
url(r'^api/v1/checks/$', views.checks),
url(r'^api/v1/checks/([\w-]+)$', views.update, name="hc-api-update"),
url(r'^api/v1/checks/([\w-]+)/pause$', views.pause, name="hc-api-pause"),
url(r'^api/v1/notifications/([\w-]+)/bounce$', views.bounce,
name="hc-api-bounce"),
path('ping/<uuid:code>/', views.ping, name="hc-ping-slash"),
path('ping/<uuid:code>', views.ping, name="hc-ping"),
path('api/v1/checks/', views.checks),
path('api/v1/checks/<uuid:code>', views.update, name="hc-api-update"),
path('api/v1/checks/<uuid:code>/pause', views.pause, name="hc-api-pause"),
path('api/v1/notifications/<uuid:code>/bounce', views.bounce,
name="hc-api-bounce"),
url(r'^badge/([\w-]+)/([\w-]{8})/([\w-]+).svg$', views.badge,
name="hc-badge"),
path('badge/<slug:username>/<slug:signature>/<slug:tag>.svg', views.badge,
name="hc-badge"),
url(r'^badge/([\w-]+)/([\w-]{8}).svg$', views.badge,
{"tag": "*"}, name="hc-badge-all"),
path('badge/<slug:username>/<slug:signature>.svg', views.badge,
{"tag": "*"}, name="hc-badge-all"),
url(r'^badge/([\w-]+)/([\w-]{8})/([\w-]+).json$', views.badge,
{"format": "json"}, name="hc-badge-json"),
path('badge/<slug:username>/<slug:signature>/<slug:tag>.json', views.badge,
{"format": "json"}, name="hc-badge-json"),
url(r'^badge/([\w-]+)/([\w-]{8}).json$', views.badge,
{"format": "json", "tag": "*"}, name="hc-badge-json-all"),
path('badge/<slug:username>/<slug:signature>.json', views.badge,
{"format": "json", "tag": "*"}, name="hc-badge-json-all"),
url(r'^api/v1/status/$', views.status),
path('api/v1/status/', views.status),
] ]

+ 4
- 7
hc/api/views.py View File

@ -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


+ 1
- 1
hc/front/tests/test_log.py View File

@ -38,7 +38,7 @@ class LogTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password") self.client.login(username="[email protected]", 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:


+ 1
- 1
hc/front/tests/test_remove_channel.py View File

@ -31,7 +31,7 @@ class RemoveChannelTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password") self.client.login(username="[email protected]", 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


+ 1
- 1
hc/front/tests/test_remove_check.py View File

@ -32,7 +32,7 @@ class RemoveCheckTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password") self.client.login(username="[email protected]", 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


+ 1
- 1
hc/front/tests/test_update_name.py View File

@ -46,7 +46,7 @@ class UpdateNameTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password") self.client.login(username="[email protected]", 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
- 1
hc/front/tests/test_update_timeout.py View File

@ -128,7 +128,7 @@ class UpdateTimeoutTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password") self.client.login(username="[email protected]", 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:


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

@ -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"),
url(r'^timeout/$', views.update_timeout, name="hc-update-timeout"),
url(r'^pause/$', views.pause, name="hc-pause"),
url(r'^remove/$', views.remove_check, name="hc-remove-check"),
url(r'^log/$', views.log, name="hc-log"),
url(r'^last_ping/$', views.ping_details, name="hc-last-ping"),
url(r'^pings/([\d]+)/$', views.ping_details, name="hc-ping-details"),
path('name/', views.update_name, name="hc-update-name"),
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"),
path('log/', views.log, name="hc-log"),
path('last_ping/', views.ping_details, name="hc-last-ping"),
path('pings/<int:n>/', views.ping_details, name="hc-ping-details"),
] ]
channel_urls = [ channel_urls = [
url(r'^$', views.channels, name="hc-channels"),
url(r'^add_email/$', views.add_email, name="hc-add-email"),
url(r'^add_webhook/$', views.add_webhook, name="hc-add-webhook"),
url(r'^add_pd/$', views.add_pd, name="hc-add-pd"),
url(r'^add_pd/([\w]{12})/$', views.add_pd, name="hc-add-pd-state"),
url(r'^add_pagertree/$', views.add_pagertree, name="hc-add-pagertree"),
url(r'^add_slack/$', views.add_slack, name="hc-add-slack"),
url(r'^add_slack_btn/$', views.add_slack_btn, name="hc-add-slack-btn"),
url(r'^add_hipchat/$', views.add_hipchat, name="hc-add-hipchat"),
url(r'^hipchat/capabilities/$', views.hipchat_capabilities, name="hc-hipchat-capabilities"),
url(r'^add_pushbullet/$', views.add_pushbullet, name="hc-add-pushbullet"),
url(r'^add_discord/$', views.add_discord, name="hc-add-discord"),
url(r'^add_pushover/$', views.add_pushover, name="hc-add-pushover"),
url(r'^add_opsgenie/$', views.add_opsgenie, name="hc-add-opsgenie"),
url(r'^add_victorops/$', views.add_victorops, name="hc-add-victorops"),
url(r'^telegram/bot/$', views.telegram_bot, name="hc-telegram-webhook"),
url(r'^add_telegram/$', views.add_telegram, name="hc-add-telegram"),
url(r'^add_sms/$', views.add_sms, name="hc-add-sms"),
url(r'^add_zendesk/$', views.add_zendesk, name="hc-add-zendesk"),
url(r'^([\w-]+)/checks/$', views.channel_checks, name="hc-channel-checks"),
url(r'^([\w-]+)/remove/$', views.remove_channel, name="hc-remove-channel"),
url(r'^([\w-]+)/verify/([\w-]+)/$', views.verify_email,
name="hc-verify-email"),
url(r'^([\w-]+)/unsub/([\w-]+)/$', views.unsubscribe_email,
name="hc-unsubscribe-alerts"),
path('', views.channels, name="hc-channels"),
path('add_email/', views.add_email, name="hc-add-email"),
path('add_webhook/', views.add_webhook, name="hc-add-webhook"),
path('add_pd/', views.add_pd, name="hc-add-pd"),
path('add_pd/<str:state>/', views.add_pd, name="hc-add-pd-state"),
path('add_pagertree/', views.add_pagertree, name="hc-add-pagertree"),
path('add_slack/', views.add_slack, name="hc-add-slack"),
path('add_slack_btn/', views.add_slack_btn, name="hc-add-slack-btn"),
path('add_hipchat/', views.add_hipchat, name="hc-add-hipchat"),
path('hipchat/capabilities/', views.hipchat_capabilities, name="hc-hipchat-capabilities"),
path('add_pushbullet/', views.add_pushbullet, name="hc-add-pushbullet"),
path('add_discord/', views.add_discord, name="hc-add-discord"),
path('add_pushover/', views.add_pushover, name="hc-add-pushover"),
path('add_opsgenie/', views.add_opsgenie, name="hc-add-opsgenie"),
path('add_victorops/', views.add_victorops, name="hc-add-victorops"),
path('telegram/bot/', views.telegram_bot, name="hc-telegram-webhook"),
path('add_telegram/', views.add_telegram, name="hc-add-telegram"),
path('add_sms/', views.add_sms, name="hc-add-sms"),
path('add_zendesk/', views.add_zendesk, name="hc-add-zendesk"),
path('<uuid:code>/checks/', views.channel_checks, name="hc-channel-checks"),
path('<uuid:code>/remove/', views.remove_channel, name="hc-remove-channel"),
path('<uuid:code>/verify/<slug:token>/', views.verify_email,
name="hc-verify-email"),
path('<uuid:code>/unsub/<slug:token>/', views.unsubscribe_email,
name="hc-unsubscribe-alerts"),
] ]
urlpatterns = [ urlpatterns = [
url(r'^$', views.index, name="hc-index"),
url(r'^checks/$', views.my_checks, name="hc-checks"),
url(r'^checks/add/$', views.add_check, name="hc-add-check"),
url(r'^checks/cron_preview/$', views.cron_preview),
url(r'^checks/status/$', views.status),
url(r'^checks/([\w-]+)/', include(check_urls)),
url(r'^integrations/', include(channel_urls)),
path('', views.index, name="hc-index"),
path('checks/', views.my_checks, name="hc-checks"),
path('checks/add/', views.add_check, name="hc-add-check"),
path('checks/cron_preview/', views.cron_preview),
path('checks/status/', views.status),
path('checks/<uuid:code>/', include(check_urls)),
path('integrations/', include(channel_urls)),
url(r'^docs/$', views.docs, name="hc-docs"),
url(r'^docs/api/$', views.docs_api, name="hc-docs-api"),
url(r'^docs/cron/$', views.docs_cron, name="hc-docs-cron"),
path('docs/', views.docs, name="hc-docs"),
path('docs/api/', views.docs_api, name="hc-docs-api"),
path('docs/cron/', views.docs_cron, name="hc-docs-cron"),
] ]

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

@ -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()


+ 1
- 1
hc/lib/badges.py View File

@ -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
- 1
hc/payments/admin.py View File

@ -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


+ 26
- 26
hc/payments/urls.py View File

@ -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/$',
views.pricing,
name="hc-pricing"),
path('pricing/',
views.pricing,
name="hc-pricing"),
url(r'^accounts/profile/billing/$',
views.billing,
name="hc-billing"),
path('accounts/profile/billing/',
views.billing,
name="hc-billing"),
url(r'^accounts/profile/billing/history/$',
views.billing_history,
name="hc-billing-history"),
path('accounts/profile/billing/history/',
views.billing_history,
name="hc-billing-history"),
url(r'^accounts/profile/billing/address/$',
views.address,
name="hc-billing-address"),
path('accounts/profile/billing/address/',
views.address,
name="hc-billing-address"),
url(r'^accounts/profile/billing/payment_method/$',
views.payment_method,
name="hc-payment-method"),
path('accounts/profile/billing/payment_method/',
views.payment_method,
name="hc-payment-method"),
url(r'^invoice/pdf/([\w-]+)/$',
views.pdf_invoice,
name="hc-invoice-pdf"),
path('invoice/pdf/<slug:transaction_id>/',
views.pdf_invoice,
name="hc-invoice-pdf"),
url(r'^pricing/set_plan/$',
views.set_plan,
name="hc-set-plan"),
path('pricing/set_plan/',
views.set_plan,
name="hc-set-plan"),
url(r'^pricing/get_client_token/$',
views.get_client_token,
name="hc-get-client-token"),
path('pricing/get_client_token/',
views.get_client_token,
name="hc-get-client-token"),
url(r'^pricing/charge/$', views.charge_webhook),
path('pricing/charge/', views.charge_webhook),
] ]

+ 7
- 7
hc/urls.py View File

@ -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}),
url(r'^admin/', admin.site.urls),
url(r'^accounts/', include('hc.accounts.urls')),
url(r'^', include('hc.api.urls')),
url(r'^', include('hc.front.urls')),
url(r'^', include('hc.payments.urls'))
path('admin/login/', hc_login, {"show_password": True}),
path('admin/', admin.site.urls),
path('accounts/', include('hc.accounts.urls')),
path('', include('hc.api.urls')),
path('', include('hc.front.urls')),
path('', include('hc.payments.urls'))
] ]

+ 1
- 1
requirements.txt View File

@ -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…
Cancel
Save