You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
3.0 KiB

10 years ago
8 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
8 years ago
  1. from datetime import timedelta as td
  2. from django.db.models import F
  3. from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse
  4. from django.utils import timezone
  5. from django.views.decorators.cache import never_cache
  6. from django.views.decorators.csrf import csrf_exempt
  7. from hc.api import schemas
  8. from hc.api.decorators import check_api_key, uuid_or_400, validate_json
  9. from hc.api.models import Check, Ping
  10. from hc.lib.badges import check_signature, get_badge_svg
  11. @csrf_exempt
  12. @uuid_or_400
  13. @never_cache
  14. def ping(request, code):
  15. try:
  16. check = Check.objects.get(code=code)
  17. except Check.DoesNotExist:
  18. return HttpResponseBadRequest()
  19. check.n_pings = F("n_pings") + 1
  20. check.last_ping = timezone.now()
  21. if check.status == "new":
  22. check.status = "up"
  23. check.save()
  24. check.refresh_from_db()
  25. ping = Ping(owner=check)
  26. headers = request.META
  27. ping.n = check.n_pings
  28. remote_addr = headers.get("HTTP_X_FORWARDED_FOR", headers["REMOTE_ADDR"])
  29. ping.remote_addr = remote_addr.split(",")[0]
  30. ping.scheme = headers.get("HTTP_X_FORWARDED_PROTO", "http")
  31. ping.method = headers["REQUEST_METHOD"]
  32. # If User-Agent is longer than 200 characters, truncate it:
  33. ping.ua = headers.get("HTTP_USER_AGENT", "")[:200]
  34. ping.save()
  35. response = HttpResponse("OK")
  36. response["Access-Control-Allow-Origin"] = "*"
  37. return response
  38. @csrf_exempt
  39. @check_api_key
  40. @validate_json(schemas.check)
  41. def checks(request):
  42. if request.method == "GET":
  43. q = Check.objects.filter(user=request.user)
  44. doc = {"checks": [check.to_dict() for check in q]}
  45. return JsonResponse(doc)
  46. elif request.method == "POST":
  47. check = Check(user=request.user)
  48. check.name = str(request.json.get("name", ""))
  49. check.tags = str(request.json.get("tags", ""))
  50. if "timeout" in request.json:
  51. check.timeout = td(seconds=request.json["timeout"])
  52. if "grace" in request.json:
  53. check.grace = td(seconds=request.json["grace"])
  54. check.save()
  55. # This needs to be done after saving the check, because of
  56. # the M2M relation between checks and channels:
  57. if request.json.get("channels") == "*":
  58. check.assign_all_channels()
  59. return JsonResponse(check.to_dict(), status=201)
  60. # If request is neither GET nor POST, return "405 Method not allowed"
  61. return HttpResponse(status=405)
  62. @never_cache
  63. def badge(request, username, signature, tag):
  64. if not check_signature(username, tag, signature):
  65. return HttpResponseBadRequest()
  66. status = "up"
  67. q = Check.objects.filter(user__username=username, tags__contains=tag)
  68. for check in q:
  69. if tag not in check.tags_list():
  70. continue
  71. if status == "up" and check.in_grace_period():
  72. status = "late"
  73. if check.get_status() == "down":
  74. status = "down"
  75. break
  76. svg = get_badge_svg(tag, status)
  77. return HttpResponse(svg, content_type="image/svg+xml")