1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-06-22 02:18:21 +02:00

The memoization doesn't work when objects don't have a primary key.

This commit is contained in:
Yohann D'ANELLO
2020-04-02 14:50:28 +02:00
parent 8ad464ae0c
commit be42801709
7 changed files with 28 additions and 14 deletions

View File

@ -114,8 +114,16 @@ class PermissionBackend(ModelBackend):
query = query | perm.query
return query
@staticmethod
@memoize
def has_perm(self, user_obj, perm, obj=None):
def check_perm(user_obj, perm, obj=None):
"""
Check is the given user has the permission over a given object.
The result is then memoized.
Exception: for add permissions, since the object is not hashable since it doesn't have any
primary key, the result is not memoized. Moreover, the right could change
(e.g. for a transaction, the balance of the user could change)
"""
if user_obj is None or isinstance(user_obj, AnonymousUser):
return False
@ -134,10 +142,13 @@ class PermissionBackend(ModelBackend):
perm_field = perm[2] if len(perm) == 3 else None
ct = ContentType.objects.get_for_model(obj)
if any(permission.applies(obj, perm_type, perm_field)
for permission in self.permissions(user_obj, ct, perm_type)):
for permission in PermissionBackend.permissions(user_obj, ct, perm_type)):
return True
return False
def has_perm(self, user_obj, perm, obj=None):
return PermissionBackend.check_perm(user_obj, perm, obj)
def has_module_perms(self, user_obj, app_label):
return False

View File

@ -49,7 +49,10 @@ def memoize(f):
# lru_cache makes the job of memoization
# We store only the 512 latest data per session. It has to be enough.
sess_funs[sess_key] = lru_cache(512)(f)
return sess_funs[sess_key](*args, **kwargs)
try:
return sess_funs[sess_key](*args, **kwargs)
except TypeError: # For add permissions, objects are not hashable (not yet created). Don't memoize this case.
return f(*args, **kwargs)
func.func_name = f.__name__

View File

@ -44,7 +44,7 @@ class StrongDjangoObjectPermissions(DjangoObjectPermissions):
perms = self.get_required_object_permissions(request.method, model_cls)
# if not user.has_perms(perms, obj):
if not all(PermissionBackend().has_perm(user, perm, obj) for perm in perms):
if not all(PermissionBackend.check_perm(user, perm, obj) for perm in perms):
# If the user does not have permissions we need to determine if
# they have read permissions to see 403, or not, and simply see
# a 404 response.

View File

@ -44,7 +44,7 @@ def pre_save_object(sender, instance, **kwargs):
# We check if the user can change the model
# If the user has all right on a model, then OK
if PermissionBackend().has_perm(user, app_label + ".change_" + model_name, instance):
if PermissionBackend.check_perm(user, app_label + ".change_" + model_name, instance):
return
# In the other case, we check if he/she has the right to change one field
@ -56,11 +56,11 @@ def pre_save_object(sender, instance, **kwargs):
# If the field wasn't modified, no need to check the permissions
if old_value == new_value:
continue
if not PermissionBackend().has_perm(user, app_label + ".change_" + model_name + "_" + field_name, instance):
if not PermissionBackend.check_perm(user, app_label + ".change_" + model_name + "_" + field_name, instance):
raise PermissionDenied
else:
# We check if the user has right to add the object
has_perm = PermissionBackend().has_perm(user, app_label + ".add_" + model_name, instance)
has_perm = PermissionBackend.check_perm(user, app_label + ".add_" + model_name, instance)
if not has_perm:
raise PermissionDenied
@ -87,5 +87,5 @@ def pre_delete_object(instance, **kwargs):
model_name = model_name_full[1]
# We check if the user has rights to delete the object
if not PermissionBackend().has_perm(user, app_label + ".delete_" + model_name, instance):
if not PermissionBackend.check_perm(user, app_label + ".delete_" + model_name, instance):
raise PermissionDenied

View File

@ -54,7 +54,7 @@ def model_list(model_name, t="view"):
def has_perm(perm, obj):
return PermissionBackend().has_perm(get_current_authenticated_user(), perm, obj)
return PermissionBackend.check_perm(get_current_authenticated_user(), perm, obj)
def can_create_transaction():
@ -77,7 +77,7 @@ def can_create_transaction():
amount=0,
reason="Check permissions",
)
session["can_create_transaction"] = PermissionBackend().has_perm(user, "note.add_transaction", empty_transaction)
session["can_create_transaction"] = PermissionBackend.check_perm(user, "note.add_transaction", empty_transaction)
return session.get("can_create_transaction") == 1