summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/restful/decorators.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/pybind/mgr/restful/decorators.py')
-rw-r--r--src/pybind/mgr/restful/decorators.py82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/pybind/mgr/restful/decorators.py b/src/pybind/mgr/restful/decorators.py
new file mode 100644
index 000000000..d1d3fbcd5
--- /dev/null
+++ b/src/pybind/mgr/restful/decorators.py
@@ -0,0 +1,82 @@
+from __future__ import absolute_import
+
+from pecan import request, response
+from base64 import b64decode
+from functools import wraps
+
+import traceback
+
+from . import context
+
+
+# Handle authorization
+def auth(f):
+ @wraps(f)
+ def decorated(*args, **kwargs):
+ if not context.instance.enable_auth:
+ return f(*args, **kwargs)
+
+ if not request.authorization:
+ response.status = 401
+ response.headers['WWW-Authenticate'] = 'Basic realm="Login Required"'
+ return {'message': 'auth: No HTTP username/password'}
+
+ username, password = b64decode(request.authorization[1]).decode('utf-8').split(':')
+
+ # Check that the username exists
+ if username not in context.instance.keys:
+ response.status = 401
+ response.headers['WWW-Authenticate'] = 'Basic realm="Login Required"'
+ return {'message': 'auth: No such user'}
+
+ # Check the password
+ if context.instance.keys[username] != password:
+ response.status = 401
+ response.headers['WWW-Authenticate'] = 'Basic realm="Login Required"'
+ return {'message': 'auth: Incorrect password'}
+
+ return f(*args, **kwargs)
+ return decorated
+
+
+# Helper function to lock the function
+def lock(f):
+ @wraps(f)
+ def decorated(*args, **kwargs):
+ with context.instance.requests_lock:
+ return f(*args, **kwargs)
+ return decorated
+
+
+# Support ?page=N argument
+def paginate(f):
+ @wraps(f)
+ def decorated(*args, **kwargs):
+ _out = f(*args, **kwargs)
+
+ # Do not modify anything without a specific request
+ if not 'page' in kwargs:
+ return _out
+
+ # A pass-through for errors, etc
+ if not isinstance(_out, list):
+ return _out
+
+ # Parse the page argument
+ _page = kwargs['page']
+ try:
+ _page = int(_page)
+ except ValueError:
+ response.status = 500
+ return {'message': 'The requested page is not an integer'}
+
+ # Raise _page so that 0 is the first page and -1 is the last
+ _page += 1
+
+ if _page > 0:
+ _page *= 100
+ else:
+ _page = len(_out) - (_page*100)
+
+ return _out[_page - 100: _page]
+ return decorated