1
# Python
2 6
import logging
3

4
# Django REST Framework
5 6
from rest_framework.exceptions import MethodNotAllowed, PermissionDenied
6 6
from rest_framework import permissions
7 6
from rest_framework.permissions import IsAuthenticated
8

9
# CyBorgBackup
10 6
from cyborgbackup.main.models import * # noqa
11

12 6
logger = logging.getLogger('cyborgbackup.api.permissions')
13

14 6
__all__ = ['ModelAccessPermission', 'UserPermission', 'IsSuperUser', 'check_user_access']
15

16

17 6
def check_user_access(user, model_class, action, *args, **kwargs):
18
    '''
19
    Return True if user can perform action against model_class with the
20
    provided parameters.
21
    '''
22 0
    result = False
23 0
    userAction = 'cyborgbackup.{}_{}'.format(action, model_class.__name__.lower())
24 0
    result = user.has_perm(userAction)
25 0
    if not result and hasattr(model_class, 'can_{}'.format(action)):
26 0
        method_perms = getattr(model_class, 'can_{}'.format(action))
27 0
        result = method_perms(user, *args, **kwargs)
28 0
    return result
29

30

31 6
class ModelAccessPermission(permissions.BasePermission):
32
    '''
33
    Default permissions class to check user access based on the model and
34
    request method, optionally verifying the request data.
35
    '''
36

37 6
    def check_options_permissions(self, request, view, obj=None):
38
        # return self.check_get_permissions(request, view, obj)
39 0
        return True
40

41 6
    def check_head_permissions(self, request, view, obj=None):
42 0
        return self.check_get_permissions(request, view, obj)
43

44 6
    def check_get_permissions(self, request, view, obj=None):
45 0
        if hasattr(view, 'parent_model'):
46 0
            parent_obj = view.get_parent_object()
47 0
            if not check_user_access(request.user, view.parent_model, 'read',
48
                                     parent_obj):
49 0
                return False
50 0
        if not obj:
51 0
            return True
52 0
        return check_user_access(request.user, view.model, 'read', obj)
53

54 6
    def check_post_permissions(self, request, view, obj=None):
55 0
        if hasattr(view, 'parent_model'):
56 0
            parent_obj = view.get_parent_object()
57 0
            if not check_user_access(request.user, view.parent_model, 'read',
58
                                     parent_obj):
59 0
                return False
60 0
            if hasattr(view, 'parent_key'):
61 0
                if not check_user_access(request.user, view.model, 'add', {view.parent_key: parent_obj}):
62 0
                    return False
63 0
            return True
64 0
        elif hasattr(view, 'obj_permission_type'):
65
            # Generic object-centric view permission check without object not needed
66 0
            if not obj:
67 0
                return True
68
            # Permission check that happens when get_object() is called
69 0
            extra_kwargs = {}
70 0
            if view.obj_permission_type == 'admin':
71 0
                extra_kwargs['data'] = {}
72 0
            return check_user_access(
73
                request.user, view.model, view.obj_permission_type, obj,
74
                **extra_kwargs
75
            )
76
        else:
77 0
            if obj:
78 0
                return True
79 0
            return check_user_access(request.user, view.model, 'add', request.data)
80

81 6
    def check_put_permissions(self, request, view, obj=None):
82 0
        if not obj:
83
            # FIXME: For some reason this needs to return True
84
            # because it is first called with obj=None?
85 0
            return True
86 0
        if getattr(view, 'is_variable_data', False):
87 0
            return check_user_access(request.user, view.model, 'change', obj,
88
                                     dict(variables=request.data))
89
        else:
90 0
            return check_user_access(request.user, view.model, 'change', obj,
91
                                     request.data)
92

93 6
    def check_patch_permissions(self, request, view, obj=None):
94 0
        return self.check_put_permissions(request, view, obj)
95

96 6
    def check_delete_permissions(self, request, view, obj=None):
97 0
        if not obj:
98
            # FIXME: For some reason this needs to return True
99
            # because it is first called with obj=None?
100 0
            return True
101

102 0
        return check_user_access(request.user, view.model, 'delete', obj)
103

104 6
    def check_permissions(self, request, view, obj=None):
105
        '''
106
        Perform basic permissions checking before delegating to the appropriate
107
        method based on the request method.
108
        '''
109

110 6
        if request.method.upper() == 'OPTIONS':
111 0
            return True
112

113
        # Don't allow anonymous users. 401, not 403, hence no raised exception.
114 6
        if not request.user or request.user.is_anonymous:
115 6
            return False
116

117
        # Always allow superusers
118 6
        if getattr(view, 'always_allow_superuser', True) and request.user.is_superuser:
119 6
            return True
120

121
        # Check if view supports the request method before checking permission
122
        # based on request method.
123 0
        if request.method.upper() not in view.allowed_methods:
124 0
            raise MethodNotAllowed(request.method)
125

126
        # Check permissions for the given view and object, based on the request
127
        # method used.
128 0
        check_method = getattr(self, 'check_%s_permissions' % request.method.lower(), None)
129 0
        result = check_method and check_method(request, view, obj)
130 0
        if not result:
131 0
            raise PermissionDenied()
132

133 0
        return result
134

135 6
    def has_permission(self, request, view, obj=None):
136 6
        logger.debug('has_permission(user=%s method=%s, %s, %r)',
137
                     request.user, request.method,
138
                     view.__class__.__name__, obj)
139 6
        try:
140 6
            response = self.check_permissions(request, view, obj)
141 0
        except Exception as e:
142 0
            logger.debug('has_permission raised %r', e, exc_info=True)
143 0
            raise
144
        else:
145 6
            logger.debug('has_permission returned %r', response)
146 6
            return response
147

148 6
    def has_object_permission(self, request, view, obj):
149 6
        return self.has_permission(request, view, obj)
150

151

152 6
class UserPermission(ModelAccessPermission):
153 6
    def check_post_permissions(self, request, view, obj=None):
154 0
        if not request.data:
155 0
            return request.user.admin_of_organizations.exists()
156 0
        elif request.user.is_superuser:
157 0
            return True
158 0
        raise PermissionDenied()
159

160

161 6
class IsSuperUser(permissions.BasePermission):
162
    """
163
    Allows access only to admin users.
164
    """
165

166 6
    def has_permission(self, request, view):
167 0
        return request.user and request.user.is_superuser
168

169

170 6
class AllowOptionsAuthentication(IsAuthenticated):
171 6
    def has_permission(self, request, view):
172 6
        if request.method == 'OPTIONS':
173 0
            return True
174 6
        return request.user and request.user.is_authenticated

Read our documentation on viewing source code .

Loading