From 25d55347dbd7266a737d78d77c5c672bab03abee Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Sat, 20 Mar 2021 17:42:25 +0100 Subject: [PATCH] Support django-guardian's ObjectPermissionChecker --- aleksis/core/mixins.py | 5 +++++ aleksis/core/util/predicates.py | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py index 2d06ba0dc..1d347b802 100644 --- a/aleksis/core/mixins.py +++ b/aleksis/core/mixins.py @@ -21,6 +21,7 @@ from django.views.generic.edit import DeleteView, ModelFormMixin import reversion from guardian.admin import GuardedModelAdmin +from guardian.core import ObjectPermissionChecker from jsonstore.fields import IntegerField, JSONFieldMixin from material.base import Layout, LayoutNode from rules.contrib.admin import ObjectPermissionsModelAdmin @@ -332,6 +333,10 @@ class ExtensibleModel(models.Model, metaclass=_ExtensibleModelBase): """Dynamically add a new permission to a model.""" cls.extra_permissions.append((name, verbose_name)) + def set_object_permission_checker(self, checker: ObjectPermissionChecker): + """Annotate a ``ObjectPermissionChecker`` for use with permission system.""" + self._permission_checker = checker + def save(self, *args, **kwargs): """Ensure all functionality of our extensions that needs saving gets it.""" # For auto-created remote syncable fields diff --git a/aleksis/core/util/predicates.py b/aleksis/core/util/predicates.py index d107b425b..c456ee329 100644 --- a/aleksis/core/util/predicates.py +++ b/aleksis/core/util/predicates.py @@ -1,3 +1,5 @@ +from typing import Optional + from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User from django.db.models import Model @@ -7,6 +9,7 @@ from guardian.backends import ObjectPermissionBackend from guardian.shortcuts import get_objects_for_user from rules import predicate +from ..mixins import ExtensibleModel from ..models import Group from .core_helpers import get_content_type_by_perm, get_site_preferences from .core_helpers import has_person as has_person_helper @@ -25,8 +28,20 @@ def check_global_permission(user: User, perm: str) -> bool: return ModelBackend().has_perm(user, perm) -def check_object_permission(user: User, perm: str, obj: Model) -> bool: - """Check whether a user has a permission on a object.""" +def check_object_permission( + user: User, perm: str, obj: Model, checker_obj: Optional[ExtensibleModel] = None +) -> bool: + """Check whether a user has a permission on an object. + + You can provide a custom ``ObjectPermissionChecker`` for prefetching object permissions + by annotating an extensible model with ``set_object_permission_checker``. + This can be the provided object (``obj``) or a special object + which is only used to get the checker class (``checker_obj``). + """ + if not checker_obj: + checker_obj = obj + if hasattr(checker_obj, "_permission_checker"): + return checker_obj._permission_checker.has_perm(perm, obj) return ObjectPermissionBackend().has_perm(user, perm, obj) -- GitLab