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.

84 lines
2.4 KiB

  1. import json
  2. from functools import wraps
  3. from django.contrib.auth.models import User
  4. from django.db.models import Q
  5. from django.http import JsonResponse
  6. from hc.lib.jsonschema import ValidationError, validate
  7. def error(msg, status=400):
  8. return JsonResponse({"error": msg}, status=status)
  9. def authorize(f):
  10. @wraps(f)
  11. def wrapper(request, *args, **kwds):
  12. if "HTTP_X_API_KEY" in request.META:
  13. api_key = request.META["HTTP_X_API_KEY"]
  14. else:
  15. api_key = str(request.json.get("api_key", ""))
  16. if len(api_key) != 32:
  17. return error("missing api key", 401)
  18. try:
  19. request.user = User.objects.get(profile__api_key=api_key)
  20. except User.DoesNotExist:
  21. return error("wrong api key", 401)
  22. return f(request, *args, **kwds)
  23. return wrapper
  24. def authorize_read(f):
  25. @wraps(f)
  26. def wrapper(request, *args, **kwds):
  27. if "HTTP_X_API_KEY" in request.META:
  28. api_key = request.META["HTTP_X_API_KEY"]
  29. else:
  30. api_key = str(request.json.get("api_key", ""))
  31. if len(api_key) != 32:
  32. return error("missing api key", 401)
  33. write_key_match = Q(profile__api_key=api_key)
  34. read_key_match = Q(profile__api_key_readonly=api_key)
  35. try:
  36. request.user = User.objects.get(write_key_match | read_key_match)
  37. except User.DoesNotExist:
  38. return error("wrong api key", 401)
  39. return f(request, *args, **kwds)
  40. return wrapper
  41. def validate_json(schema=None):
  42. """ Parse request json and validate it against `schema`.
  43. Put the parsed result in `request.json`.
  44. If schema is None then only parse and don't validate.
  45. Supports a limited subset of JSON schema spec.
  46. """
  47. def decorator(f):
  48. @wraps(f)
  49. def wrapper(request, *args, **kwds):
  50. if request.body:
  51. try:
  52. request.json = json.loads(request.body.decode())
  53. except ValueError:
  54. return error("could not parse request body")
  55. else:
  56. request.json = {}
  57. if schema:
  58. try:
  59. validate(request.json, schema)
  60. except ValidationError as e:
  61. return error("json validation error: %s" % e)
  62. return f(request, *args, **kwds)
  63. return wrapper
  64. return decorator