@@ -40,6 +40,7 @@ class ApiError(Enum):
40
40
INPUT_ERROR = 3
41
41
UNAUTHORIZED = 4
42
42
WRONG_SCHEME = 5
43
+ BAD_REQUEST = 6
43
44
44
45
45
46
def _error (error : ApiError , msg : str ) -> JsonResponse :
@@ -66,30 +67,40 @@ def get_client_ip(request) -> str:
66
67
return ip
67
68
68
69
69
- def ensure_https_in_ops (fn ):
70
+ # Checkers
71
+ def request_checker (checker , error_msg ):
70
72
"""
71
- Ensure that the view is called via an HTTPS request and return a JSON error
72
- payload if not.
73
+ Generic sanity check decorator on views.
73
74
74
- If DEBUG = True, it has no effect.
75
+ It accepts two parameters:
76
+ `checker`: a function that accepts a request and returns True if valid
77
+ `error_msg`: what to return as error message if request is invalid
78
+
79
+ In case of invalid requests, it returns a BAD_REQUEST error.
75
80
"""
76
- @wraps (fn )
77
- def wrapper (request , * args , ** kwargs ):
78
- if not DEBUG and not request .is_secure ():
79
- return _error (ApiError .WRONG_SCHEME , 'please use HTTPS' )
80
- return fn (request , * args , ** kwargs )
81
- return wrapper
81
+ def decorator (fn ):
82
+ @wraps (fn )
83
+ def wrapper (request , * args , ** kwargs ):
84
+ if not checker (request ):
85
+ return _error (ApiError .BAD_REQUEST , error_msg )
86
+ return fn (request , * args , ** kwargs )
87
+ return wrapper
88
+ return decorator
89
+
90
+
91
+ # Ensure that the view is called via an HTTPS request and return a JSON error
92
+ # payload if not. If DEBUG = True, it has no effect.
93
+ ensure_https_in_ops = request_checker (
94
+ lambda r : DEBUG or r .is_secure (), 'please user HTTPS'
95
+ )
82
96
97
+ # We use this instead of the bult-in decorator to return a JSON error
98
+ # payload instead of a simple 405.
99
+ ensure_post = request_checker (lambda r : r .method == 'POST' , 'please use POST' )
83
100
84
- def ensure_post (fn ):
85
- # We use this instead of the bult-in decorator to return a JSON error
86
- # payload instead of a simple 405.
87
- @wraps (fn )
88
- def wrapper (request , * args , ** kwargs ):
89
- if request .method != 'POST' :
90
- return _error (ApiError .WRONG_SCHEME , 'please use POST' )
91
- return fn (request , * args , ** kwargs )
92
- return wrapper
101
+ ensure_json_content_type = request_checker (
102
+ lambda r : r .content_type == 'application/json' , 'please send JSON'
103
+ )
93
104
94
105
95
106
def restrict_client_ip_to_allowed_list (fn ):
@@ -107,6 +118,7 @@ def wrapper(request, *args, **kwargs):
107
118
@csrf_exempt
108
119
@ensure_post
109
120
@ensure_https_in_ops
121
+ @ensure_json_content_type
110
122
@restrict_client_ip_to_allowed_list
111
123
def isauth (request ):
112
124
"""
0 commit comments