diff --git a/awx/main/rbac.py b/awx/main/rbac.py index cd575808e0..064d4faba6 100644 --- a/awx/main/rbac.py +++ b/awx/main/rbac.py @@ -45,7 +45,7 @@ class CustomRbac(permissions.BasePermission): # because it is first called with obj=None? if getattr(view, 'is_variable_data', False): return check_user_access(request.user, view.model, 'change', obj, - {'variables': request.DATA}) + dict(variables=request.DATA)) else: return check_user_access(request.user, view.model, 'change', obj, request.DATA) @@ -57,23 +57,26 @@ class CustomRbac(permissions.BasePermission): return check_user_access(request.user, view.model, 'delete', obj) def _check_permissions(self, request, view, obj=None): - #if not obj and hasattr(view, 'get_object'): - # obj = view.get_object() + # Check that obj (if given) is active, otherwise raise a 404. active = getattr(obj, 'active', getattr(obj, 'is_active', True)) if callable(active): active = active() if not active: raise Http404() + # Don't allow anonymous users. 401, not 403, hence no raised exception. if not request.user or request.user.is_anonymous(): return False + # Don't allow inactive users (and respond with a 403). if not request.user.is_active: raise PermissionDenied('your account is inactive') + # Always allow superusers (as long as they are active). if request.user.is_superuser: return True + # Check permissions for the given view and object, based on the request # method used. check_method = getattr(self, '_check_%s_permissions' % \ @@ -81,9 +84,11 @@ class CustomRbac(permissions.BasePermission): result = check_method and check_method(request, view, obj) if not result: raise PermissionDenied() + return result # If no obj is given, check list permissions. + if obj is None: if getattr(view, 'list_permissions_check', None): if not view.list_permissions_check(request): @@ -92,13 +97,16 @@ class CustomRbac(permissions.BasePermission): raise Exception('internal error, list_permissions_check or ' 'item_permissions_check must be defined') return True + # Otherwise, check the item permissions for the given obj. + else: if not view.item_permissions_check(request, obj): raise PermissionDenied() return True def has_permission(self, request, view, obj=None): + logger.debug('has_permission(user=%s method=%s data=%r, %s, %r)', request.user, request.method, request.DATA, view.__class__.__name__, obj) @@ -117,16 +125,20 @@ class CustomRbac(permissions.BasePermission): class JobCallbackPermission(CustomRbac): def has_permission(self, request, view, obj=None): + # If another authentication method was used other than the one for job # callbacks, return True to fall through to the next permission class. if request.user or not request.auth: return super(JobCallbackPermission, self).has_permission(request, view, obj) + # FIXME: Verify that inventory or job event requested are for the same # job ID present in the auth token, etc. + #try: # job = Job.objects.get(active=True, status='running', pk=int(request.auth.split('-')[0])) #except Job.DoesNotExist: # return False + if view.model == Inventory and request.method.lower() in ('head', 'get'): return True elif view.model == JobEvent and request.method.lower() == 'post':