Support custom model managers for check_access()

Allow app to specify which model manager will be used
when creating the queryset that is passed to check_access.

Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2019-07-30 03:07:17 -04:00
parent 2e1600c334
commit 3c9454160f
3 changed files with 34 additions and 16 deletions

View File

@@ -12,6 +12,7 @@ logger = logging.getLogger(__name__)
class ModelPermission(object):
_functions = {}
_inheritances = {}
_manager_names = {}
_registry = {}
@classmethod
@@ -97,6 +98,10 @@ class ModelPermission(object):
def get_inheritance(cls, model):
return cls._inheritances[model]
@classmethod
def get_manager_name(cls, model):
return cls._manager_names[model]
@classmethod
def register_function(cls, model, function):
cls._functions[model] = function
@@ -104,3 +109,7 @@ class ModelPermission(object):
@classmethod
def register_inheritance(cls, model, related):
cls._inheritances[model] = related
@classmethod
def register_manager(cls, model, manager_name):
cls._manager_names[model] = manager_name

View File

@@ -200,28 +200,37 @@ class AccessControlListManager(models.Manager):
return result
def check_access(self, obj, permissions, user, manager=None):
def check_access(self, obj, permissions, user):
# Allow specific managers for models that have more than one
# for example the Document model when checking for access for a trashed
# document.
if manager:
source_queryset = manager.all()
meta = getattr(obj, '_meta', None)
if not meta:
logger.debug(
ugettext(
'Object "%s" is not a model and cannot be checked for '
'access.'
) % force_text(obj)
)
return True
else:
meta = getattr(obj, '_meta', None)
if not meta:
logger.debug(
ugettext(
'Object "%s" is not a model and cannot be checked for '
'access.'
) % force_text(obj)
try:
manager_name = ModelPermission.get_manager_name(
model=meta.model
)
return True
else:
source_queryset = obj._meta.default_manager.all()
except KeyError:
manager_name = None
restricted_queryset = obj._meta.default_manager.none()
if manager_name:
manager = getattr(obj._meta.model, manager_name)
else:
manager = obj._meta.default_manager
source_queryset = manager.all()
restricted_queryset = manager.none()
for permission in permissions:
# Default relationship betweens permissions is OR
# TODO: Add support for AND relationship

View File

@@ -164,7 +164,7 @@ class APIDocumentPageImageView(generics.RetrieveAPIView):
AccessControlList.objects.check_access(
obj=document, permissions=(permission_required,),
user=self.request.user, manager=Document.passthrough
user=self.request.user
)
return document