Skip to content

Commit

Permalink
Merge pull request #16 from nnseva/cached-admin-permission-checks
Browse files Browse the repository at this point in the history
Admin permission checks are cached on the request instance
  • Loading branch information
nnseva committed Nov 21, 2023
2 parents ac0bf4f + 69fe92a commit abee008
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 7 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ jobs:
max-parallel: 2
matrix:
include:
- python-version: "2.7"
toxenv: py27-django{1.10,1.11}
- python-version: "3.6"
toxenv: py36-django{1.10,1.11,2.0,2.1,2.2,3.0}
- python-version: "3.7"
Expand Down
2 changes: 1 addition & 1 deletion access/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.1.1b2"
__version__ = "0.1.2b1"
28 changes: 25 additions & 3 deletions access/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,23 +201,23 @@ def has_basic_change_permission(self, request, obj=None):
if manager.check_changeable(self.model, request) is False:
return False
if obj:
return bool(manager.apply_changeable(obj.__class__.objects.filter(id=obj.id), request))
return self._check_request_object_ability(obj, 'changeable', request)
return True

def has_delete_permission(self, request, obj=None):
manager = AccessManager(self.model)
if manager.check_deleteable(self.model, request) is False:
return False
if obj:
return bool(manager.apply_deleteable(obj.__class__.objects.filter(id=obj.id), request))
return self._check_request_object_ability(obj, 'deleteable', request)
return True

def has_view_permission(self, request, obj=None):
manager = AccessManager(self.model)
if manager.check_visible(self.model, request) is False:
return False
if obj:
return bool(manager.apply_visible(obj.__class__.objects.filter(id=obj.id), request))
return self._check_request_object_ability(obj, 'visible', request)
return True

def has_module_permission(self, request):
Expand Down Expand Up @@ -477,6 +477,28 @@ def clean(form):

return super(AccessControlMixin, self).get_formset(request, obj=obj, **kw)

def _get_request_ability_cache(self, request):
"""
Returns the request ability cache to avoid twice requests
for individual model instance ability
"""
if not hasattr(request, '--request-ability-cache'):
setattr(request, '--request-ability-cache', {})
return getattr(request, '--request-ability-cache')

def _check_request_object_ability(self, obj, ability, request):
"""
Checks and caches individual model instance ability
"""
model_name = '%s.%s' % (obj._meta.app_label, obj._meta.model_name)
pk = obj.pk
perm = self._get_request_ability_cache(request).get((model_name, pk, ability), None)
if perm is None:
manager = AccessManager(obj.__class__)
perm = bool(manager.apply_able(ability, obj.__class__.objects.filter(id=obj.id), request).exists())
self._get_request_ability_cache(request)[(model_name, pk, ability)] = perm
return perm


class AccessModelAdmin(AccessControlMixin, ModelAdmin):
pass
Expand Down
1 change: 0 additions & 1 deletion access/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ def check_able(self, ability, model, request):
return ret

def __getattr__(self, name):
method = None
prefix = 'apply_'
if name.startswith(prefix):
ability = name[len(prefix):]
Expand Down

0 comments on commit abee008

Please sign in to comment.