summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/restful/decorators.py
blob: 11840a9913a670dedd779aab1f8d6a5bf0c4e264 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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