Completed
Push — master ( fe49eb...265317 )
by W
06:11
created

st2common.rbac.request_user_has_resource_api_permission()   B

Complexity

Conditions 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 4
dl 0
loc 22
rs 8.9197
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
"""
17
This module contains permission checking decorators for wrapping pecan request handler methods.
18
"""
19
20
from functools import wraps
21
22
import pecan
23
24
from st2common.rbac import utils
25
26
__all__ = [
27
    'request_user_is_admin',
28
    'request_user_is_system_admin',
29
    'request_user_has_permission',
30
    'request_user_has_resource_api_permission',
31
    'request_user_has_resource_db_permission'
32
]
33
34
35
def request_user_is_admin():
36
    def decorate(func):
37
        @wraps(func)
38
        def func_wrapper(*args, **kwargs):
39
            utils.assert_request_user_is_admin(request=pecan.request)
40
            return func(*args, **kwargs)
41
        return func_wrapper
42
    return decorate
43
44
45
def request_user_is_system_admin():
46
    def decorate(func):
47
        @wraps(func)
48
        def func_wrapper(*args, **kwargs):
49
            utils.assert_request_user_is_system_admin(request=pecan.request)
50
            return func(*args, **kwargs)
51
        return func_wrapper
52
    return decorate
53
54
55
def request_user_has_permission(permission_type):
56
    def decorate(func):
57
        @wraps(func)
58
        def func_wrapper(*args, **kwargs):
59
            utils.assert_request_user_has_permission(request=pecan.request,
60
                                                     permission_type=permission_type)
61
            return func(*args, **kwargs)
62
        return func_wrapper
63
    return decorate
64
65
66
def request_user_has_resource_api_permission(permission_type):
67
    """
68
    A decorator meant to wrap post Pecan REST controller methods
69
70
    This decorator assumes the first argument passed to the decorated function is a resource API
71
    object.
72
    """
73
    def decorate(func):
74
        function_name = func.__name__
75
        if function_name not in ['post']:
76
            raise Exception('This decorator should only be used to wrap post methods')
77
78
        @wraps(func)
79
        def func_wrapper(*args, **kwargs):
80
            resource_api = args[1]
81
82
            utils.assert_request_user_has_resource_api_permission(request=pecan.request,
83
                                                                  resource_api=resource_api,
84
                                                                  permission_type=permission_type)
85
            return func(*args, **kwargs)
86
        return func_wrapper
87
    return decorate
88
89
90
def request_user_has_resource_db_permission(permission_type):
91
    """
92
    A decorator meant to wrap post, put and delete Pecan REST controller methods.
93
94
    This decorator assumes the first argument passed to the decorated function is a resource
95
    reference or an ID.
96
97
    Internally, this decorator retrieves the object from the DB so it can perform the permission
98
    checking.
99
100
    Note: The same query happens inside the decorator function meaning this is not the most
101
    efficient approach and we should eventually cache the "get one" results.
102
    """
103
    valid_method_names = ['get_one', 'get', 'post', 'put', 'delete']
104
105
    def decorate(func):
106
        function_name = func.__name__
107
        if function_name not in valid_method_names:
108
            raise Exception('This decorator should only be used to wrap %s methods' %
109
                            (', '.join(valid_method_names)))
110
111
        @wraps(func)
112
        def func_wrapper(*args, **kwargs):
113
            controller_instance = args[0]
114
            resource_id = args[1]  # Note: This can either be id, name or ref
115
116
            get_one_db_method = controller_instance.get_one_db_method
117
            resource_db = get_one_db_method(resource_id)
118
            utils.assert_request_user_has_resource_db_permission(request=pecan.request,
119
                                                                 resource_db=resource_db,
120
                                                                 permission_type=permission_type)
121
            return func(*args, **kwargs)
122
        return func_wrapper
123
    return decorate
124
125
126
def request_user_has_webhook_permission(permission_type):
127
    """
128
    A decorator which checks that the currently logged-in user has a webhook post permission.
129
130
    Note: We need a special decorator for webhooks since Webhook objects don't actually exist in
131
    the DB right now.
132
    """
133
    from st2common.models.db.webhook import WebhookDB
134
135
    def decorate(func):
136
        @wraps(func)
137
        def func_wrapper(*args, **kwargs):
138
            hook = '/'.join(args[1:])  # TODO: There must be a better way to do this.
139
            webhook_db = WebhookDB(name=hook)
140
141
            resource_db = webhook_db
142
            utils.assert_request_user_has_resource_db_permission(request=pecan.request,
143
                                                                 resource_db=resource_db,
144
                                                                 permission_type=permission_type)
145
            return func(*args, **kwargs)
146
        return func_wrapper
147
    return decorate
148