healthchecks/hc/api/decorators.py

72 lines
1.9 KiB
Python

import json
import re
from functools import wraps
from django.contrib.auth.models import User
from django.http import (HttpResponseBadRequest, HttpResponseForbidden,
JsonResponse)
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):
return JsonResponse({"error": msg}, status=400)
def check_api_key(f):
@wraps(f)
def wrapper(request, *args, **kwds):
request.json = {}
if request.body:
try:
request.json = json.loads(request.body.decode("utf-8"))
except ValueError:
return make_error("could not parse request body")
if "HTTP_X_API_KEY" in request.META:
api_key = request.META["HTTP_X_API_KEY"]
else:
api_key = request.json.get("api_key", "")
if api_key == "":
return make_error("wrong api_key")
try:
request.user = User.objects.get(profile__api_key=api_key)
except User.DoesNotExist:
return HttpResponseForbidden()
return f(request, *args, **kwds)
return wrapper
def validate_json(schema):
""" Validate request.json contents against `schema`.
Supports a tiny subset of JSON schema spec.
"""
def decorator(f):
@wraps(f)
def wrapper(request, *args, **kwds):
try:
validate(request.json, schema)
except ValidationError as e:
return make_error("json validation error: %s" % e)
return f(request, *args, **kwds)
return wrapper
return decorator