diff --git a/HISTORY.rst b/HISTORY.rst index a1b219b34a..4934047a97 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -124,7 +124,8 @@ characters. - Improve TestModelTestMixin. Allow specifying a base model. Fix passing the dynamic Meta class to the test model. - +- Support for proxy model permission inheritance. Proxy models + now get the permission inheritance from their base models. 3.2.9 (2019-11-03) ================== diff --git a/mayan/apps/acls/classes.py b/mayan/apps/acls/classes.py index 8e8b8c5db6..ff68ae1386 100644 --- a/mayan/apps/acls/classes.py +++ b/mayan/apps/acls/classes.py @@ -80,6 +80,10 @@ class ModelPermission(object): @classmethod def get_inheritance(cls, model): + # Proxy models get the inheritance from their base model + if model._meta.proxy: + model = model._meta.proxy_for_model + return cls._inheritances[model] @classmethod diff --git a/mayan/apps/acls/tests/mixins.py b/mayan/apps/acls/tests/mixins.py index c27979f15b..7b9ccbca5b 100644 --- a/mayan/apps/acls/tests/mixins.py +++ b/mayan/apps/acls/tests/mixins.py @@ -49,9 +49,8 @@ class ACLTestMixin(PermissionTestMixin, RoleTestMixin, TestModelTestMixin): # this avoids their Content Type from being looked up # in subsequent tests where they don't exists due to the database # transaction rollback. - for model in self._test_models: - ModelPermission.deregister(model=model) - self._test_models.remove(model) + #for model in self._test_models: + # ModelPermission.deregister(model=model) super(ACLTestMixin, self).tearDown() @@ -71,12 +70,12 @@ class ACLTestMixin(PermissionTestMixin, RoleTestMixin, TestModelTestMixin): 'object_id': self.test_object.pk } - def _setup_test_object(self, register_model_permissions=True): - self._create_test_model() - self._create_test_object() + def _setup_test_object(self, model_name=None, register_model_permissions=True): + self.TestModel = self._create_test_model(model_name=model_name) + self.test_object = self.TestModel.objects.create() if register_model_permissions: ModelPermission.register( - model=self.test_object._meta.model, permissions=( + model=self.TestModel, permissions=( permission_acl_edit, permission_acl_view, ) ) @@ -85,9 +84,23 @@ class ACLTestMixin(PermissionTestMixin, RoleTestMixin, TestModelTestMixin): if register_model_permissions: ModelPermission.register( - model=self.test_object._meta.model, permissions=( + model=self.TestModel, permissions=( self.test_permission, ) ) self._inject_test_object_content_type() + + def _setup_test_object_base(self): + self.test_object_base = self._setup_test_object( + model_name='TestModelBase' + ) + + def _setup_test_object_proxy(self): + self.TestModelProxy = self._create_test_model( + base_class=self.TestModel, model_name='TestModelProxy', + options={ + 'proxy': True + } + ) + self.test_object_proxy = self.TestModelProxy.objects.create() diff --git a/mayan/apps/acls/tests/test_models.py b/mayan/apps/acls/tests/test_models.py index a420039045..fa64bb4050 100644 --- a/mayan/apps/acls/tests/test_models.py +++ b/mayan/apps/acls/tests/test_models.py @@ -67,8 +67,10 @@ class PermissionTestCase(ACLTestMixin, BaseTestCase): def _setup_child_parent_test_objects(self): self._create_test_permission() - self._create_test_model(model_name='TestModelParent') - self._create_test_model( + self.TestModelParent = self._create_test_model( + model_name='TestModelParent' + ) + self.TestModelChild = self._create_test_model( fields={ 'parent': models.ForeignKey( on_delete=models.CASCADE, related_name='children', @@ -166,7 +168,7 @@ class PermissionTestCase(ACLTestMixin, BaseTestCase): class InheritedPermissionTestCase(ACLTestMixin, BaseTestCase): def test_retrieve_inherited_role_permission_not_model_applicable(self): - self._create_test_model() + self.TestModel = self._create_test_model() self.test_object = self.TestModel.objects.create() self._create_test_acl() self._create_test_permission() @@ -179,7 +181,7 @@ class InheritedPermissionTestCase(ACLTestMixin, BaseTestCase): self.assertTrue(self.test_permission.stored_permission not in queryset) def test_retrieve_inherited_role_permission_model_applicable(self): - self._create_test_model() + self.TestModel = self._create_test_model() self.test_object = self.TestModel.objects.create() self._create_test_acl() self._create_test_permission() @@ -199,8 +201,10 @@ class InheritedPermissionTestCase(ACLTestMixin, BaseTestCase): def test_retrieve_inherited_related_parent_child_permission(self): self._create_test_permission() - self._create_test_model(model_name='TestModelParent') - self._create_test_model( + self.TestModelParent = self._create_test_model( + model_name='TestModelParent' + ) + self.TestModelChild = self._create_test_model( fields={ 'parent': models.ForeignKey( on_delete=models.CASCADE, related_name='children', @@ -240,8 +244,10 @@ class InheritedPermissionTestCase(ACLTestMixin, BaseTestCase): ): self._create_test_permission() - self._create_test_model(model_name='TestModelGrandParent') - self._create_test_model( + self.TestModelGrandParent = self._create_test_model( + model_name='TestModelGrandParent' + ) + self.TestModelParent = self._create_test_model( fields={ 'parent': models.ForeignKey( on_delete=models.CASCADE, related_name='children', @@ -249,7 +255,7 @@ class InheritedPermissionTestCase(ACLTestMixin, BaseTestCase): ) }, model_name='TestModelParent' ) - self._create_test_model( + self.TestModelChild = self._create_test_model( fields={ 'parent': models.ForeignKey( on_delete=models.CASCADE, related_name='children', @@ -294,3 +300,84 @@ class InheritedPermissionTestCase(ACLTestMixin, BaseTestCase): ) self.assertTrue(self.test_permission.stored_permission in queryset) + + +class ProxyModelPermissionTestCase(ACLTestMixin, BaseTestCase): + def test_proxy_model_filtering_no_permission(self): + self._setup_test_object_base() + self._setup_test_object_proxy() + + proxy_object = self.TestModelProxy.objects.get(pk=self.test_object.pk) + + self.assertFalse( + proxy_object in AccessControlList.objects.restrict_queryset( + permission=self.test_permission, + queryset=self.TestModelProxy.objects.all(), + user=self._test_case_user + ) + ) + + def test_proxy_model_filtering_with_access(self): + self._setup_test_object_base() + self._setup_test_object_proxy() + + self.grant_access( + obj=self.test_object, permission=self.test_permission + ) + + proxy_object = self.TestModelProxy.objects.get(pk=self.test_object.pk) + + self.assertTrue( + proxy_object in AccessControlList.objects.restrict_queryset( + permission=self.test_permission, + queryset=self.TestModelProxy.objects.all(), + user=self._test_case_user + ) + ) + + def test_proxy_model_inheritance_with_access(self): + self._create_test_permission() + + self.TestModelParent = self._create_test_model( + model_name='TestModelParent' + ) + self.TestModelChild = self._create_test_model( + fields={ + 'parent': models.ForeignKey( + on_delete=models.CASCADE, related_name='children', + to='TestModelParent', + ) + }, model_name='TestModelChild' + ) + self.TestModelProxy = self._create_test_model( + base_class=self.TestModelChild, model_name='TestModelProxy', + options={ + 'proxy': True + } + ) + + ModelPermission.register( + model=self.TestModelParent, permissions=( + self.test_permission, + ) + ) + ModelPermission.register_inheritance( + model=self.TestModelChild, related='parent', + ) + + parent = self.TestModelParent.objects.create() + child = self.TestModelChild.objects.create(parent=parent) + + self.grant_access( + obj=parent, permission=self.test_permission + ) + + proxy_object = self.TestModelProxy.objects.get(pk=child.pk) + + self.assertTrue( + proxy_object in AccessControlList.objects.restrict_queryset( + permission=self.test_permission, + queryset=self.TestModelProxy.objects.all(), + user=self._test_case_user + ) + )