From 6e92cba947e2af28898635819e4e941d095a3aea Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Mon, 6 May 2019 17:11:59 +0200 Subject: [PATCH 5/8] manager: differentiate perm granted while ignoring auth level (#33515) 95% of the uses of can_{action} permission attributes should be done while ignoring authentication levels, because they control buttons display in templates. But for the remaining part, we need to know if the permission is really accessible to the user, which is currently hard to tell. This commit adds an explicit way to do so by introducing could_{action} attributes, that represent permissions granted when ignoring authentication levels. can_{action} attributes now represent permissions that the user is really able to use. Hence we'll have to replace can_ attributes by could_ in most places, while leaving them be in the places that actually motivate this commit. --- src/authentic2/manager/views.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/authentic2/manager/views.py b/src/authentic2/manager/views.py index 2ac55639..62bf1676 100644 --- a/src/authentic2/manager/views.py +++ b/src/authentic2/manager/views.py @@ -38,6 +38,7 @@ from django_select2.views import AutoResponseView from gadjo.templatetags.gadjo import xstatic +from django_rbac.exceptions import InsufficientAuthLevel from django_rbac.utils import get_ou_model from authentic2.data_transfer import export_site, import_site, DataImportError, ImportContext @@ -102,27 +103,37 @@ class PermissionMixin(object): '''Control access to views based on permissions''' permissions = None + @staticmethod + def can_and_could(user, perm, auth_level, obj=None): + try: + can = could = user.has_perm(perm, obj, auth_level=auth_level) if obj \ + else user.has_perm_any(perm, auth_level=auth_level) + except InsufficientAuthLevel: + can = False + could = True + return can, could + def authorize(self, request, *args, **kwargs): auth_level = request.session.get('auth_level', 1) if hasattr(self, 'model'): app_label = self.model._meta.app_label model_name = self.model._meta.model_name add_perm = '%s.add_%s' % (app_label, model_name) - self.can_add = request.user.has_perm_any(add_perm) + self.can_add, self.could_add = \ + self.can_and_could(request.user, add_perm, auth_level) if hasattr(self, 'get_object') \ and ((hasattr(self, 'pk_url_kwarg') and self.pk_url_kwarg in self.kwargs) or (hasattr(self, 'slug_url_kwarg') and self.slug_url_kwarg in self.kwargs)): self.object = self.get_object() - view_perm = '%s.view_%s' % (app_label, model_name) - change_perm = '%s.change_%s' % (app_label, model_name) - delete_perm = '%s.delete_%s' % (app_label, model_name) - self.can_view = request.user.has_perm(view_perm, self.object) - self.can_change = request.user.has_perm(change_perm, - self.object) - self.can_delete = request.user.has_perm(delete_perm, - self.object) + actions = ('view', 'change', 'delete') + for action in actions: + perm = '%s.%s_%s' % (app_label, action, model_name) + can, could = self.can_and_could(request.user, perm, auth_level, + self.object) + setattr(self, 'can_' + action, can) + setattr(self, 'could_' + action, could) if self.permissions \ and not request.user.has_perms( self.permissions, self.object, auth_level=auth_level): -- 2.20.1