Add ACL filter support for case 6
Support inherited field of a related field that is Generic Foreign Key. Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
This commit is contained in:
@@ -21,22 +21,6 @@ class ModelPermission(object):
|
||||
# TODO: Find method to revert the add_to_class('acls'...)
|
||||
# delattr doesn't work.
|
||||
|
||||
@classmethod
|
||||
def register(cls, model, permissions):
|
||||
from django.contrib.contenttypes.fields import GenericRelation
|
||||
|
||||
cls._registry.setdefault(model, [])
|
||||
for permission in permissions:
|
||||
cls._registry[model].append(permission)
|
||||
|
||||
AccessControlList = apps.get_model(
|
||||
app_label='acls', model_name='AccessControlList'
|
||||
)
|
||||
|
||||
model.add_to_class(
|
||||
name='acls', value=GenericRelation(AccessControlList)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_classes(cls, as_content_type=False):
|
||||
ContentType = apps.get_model(
|
||||
@@ -116,6 +100,22 @@ class ModelPermission(object):
|
||||
def get_manager_name(cls, model):
|
||||
return cls._manager_names[model]
|
||||
|
||||
@classmethod
|
||||
def register(cls, model, permissions):
|
||||
from django.contrib.contenttypes.fields import GenericRelation
|
||||
|
||||
cls._registry.setdefault(model, [])
|
||||
for permission in permissions:
|
||||
cls._registry[model].append(permission)
|
||||
|
||||
AccessControlList = apps.get_model(
|
||||
app_label='acls', model_name='AccessControlList'
|
||||
)
|
||||
|
||||
model.add_to_class(
|
||||
name='acls', value=GenericRelation(AccessControlList)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def register_function(cls, model, function):
|
||||
cls._functions[model] = function
|
||||
|
||||
@@ -45,8 +45,8 @@ class AccessControlListManager(models.Manager):
|
||||
# 4: No related field, but has an inherited related field, solved by
|
||||
# recursion, branches to #2 or #3.
|
||||
# 5: Inherited field of a related field
|
||||
# -- Not addressed yet --
|
||||
# 6: Inherited field of a related field that is Generic Foreign Key
|
||||
# -- Not addressed yet --
|
||||
# 7: Has a related function
|
||||
result = []
|
||||
|
||||
@@ -58,10 +58,28 @@ class AccessControlListManager(models.Manager):
|
||||
if isinstance(related_field, GenericForeignKey):
|
||||
# Case 3: Generic Foreign Key, multiple ContentTypes + object
|
||||
# id combinations
|
||||
# Also handles case #6 using the parent related field
|
||||
# reference template.
|
||||
|
||||
# Craft a double underscore reference to a previous related
|
||||
# field in the case where multiple related fields are
|
||||
# associated.
|
||||
# Example: object_layer__content_type
|
||||
recuisive_related_reference = '__'.join(related_field_name.split('__')[0:-1])
|
||||
|
||||
# If there is at least one parent related field we add a
|
||||
# double underscore to make it a valid filter template.
|
||||
if recuisive_related_reference:
|
||||
recuisive_related_reference = '{}__'.format(recuisive_related_reference)
|
||||
|
||||
content_type_object_id_queryset = queryset.annotate(
|
||||
ct_fk_combination=Concat(
|
||||
related_field.ct_field, Value('-'),
|
||||
related_field.fk_field, output_field=CharField()
|
||||
'{}{}'.format(
|
||||
recuisive_related_reference, related_field.ct_field
|
||||
), Value('-'),
|
||||
'{}{}'.format(
|
||||
recuisive_related_reference, related_field.fk_field
|
||||
), output_field=CharField()
|
||||
)
|
||||
).values('ct_fk_combination')
|
||||
|
||||
@@ -75,8 +93,7 @@ class AccessControlListManager(models.Manager):
|
||||
ct_fk_combination__in=content_type_object_id_queryset
|
||||
).values('object_id')
|
||||
|
||||
field_lookup = 'object_id__in'
|
||||
|
||||
field_lookup = '{}object_id__in'.format(recuisive_related_reference)
|
||||
result.append(Q(**{field_lookup: acl_filter}))
|
||||
else:
|
||||
# Case 2: Related field of a single type, single ContentType,
|
||||
@@ -97,6 +114,7 @@ class AccessControlListManager(models.Manager):
|
||||
|
||||
# Case 5: Related field, has an inherited related field itself
|
||||
# Bubble up permssion check
|
||||
# Recurse and reduce
|
||||
# TODO: Add relationship support: OR or AND
|
||||
# TODO: OR for document pages, version, doc, and types
|
||||
# TODO: AND for new cabinet levels ACLs
|
||||
|
||||
Reference in New Issue
Block a user