From 0917bd57b39f9aaa1fb2d53954f68a6fbc93ec7f Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Mon, 19 Aug 2019 23:16:09 -0400 Subject: [PATCH] Add ACL filter support for case 6 Support inherited field of a related field that is Generic Foreign Key. Signed-off-by: Roberto Rosario --- mayan/apps/acls/classes.py | 32 ++++++++++++++++---------------- mayan/apps/acls/managers.py | 28 +++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/mayan/apps/acls/classes.py b/mayan/apps/acls/classes.py index 867de95834..8e8b8c5db6 100644 --- a/mayan/apps/acls/classes.py +++ b/mayan/apps/acls/classes.py @@ -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 diff --git a/mayan/apps/acls/managers.py b/mayan/apps/acls/managers.py index d66f280a7b..422d6ab586 100644 --- a/mayan/apps/acls/managers.py +++ b/mayan/apps/acls/managers.py @@ -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