diff --git a/HISTORY.rst b/HISTORY.rst index 172bbcb0e5..109d0b33cd 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -208,6 +208,7 @@ * Use copyfileobj to save documents to files * Add user logged in and logged out events. * Add transaction handling in more places. +* Update ACLs tests to use ephimeral models. 3.1.11 (2019-04-XX) =================== diff --git a/docs/releases/3.2.rst b/docs/releases/3.2.rst index 40a78a23a2..090556a73d 100644 --- a/docs/releases/3.2.rst +++ b/docs/releases/3.2.rst @@ -241,6 +241,7 @@ Other changes * Add user logged in and logged out events. * Add transaction handling in more places: Checkouts, documents, metadata, tags. +* Update ACLs tests to use ephimeral models. Removals -------- diff --git a/mayan/apps/acls/classes.py b/mayan/apps/acls/classes.py index d7ffae9b28..d07b308aac 100644 --- a/mayan/apps/acls/classes.py +++ b/mayan/apps/acls/classes.py @@ -12,6 +12,12 @@ class ModelPermission(object): _proxies = {} _registry = {} + @classmethod + def clear(cls): + cls._inheritances = {} + cls._proxies = {} + cls._registry = {} + @classmethod def register(cls, model, permissions): from django.contrib.contenttypes.fields import GenericRelation diff --git a/mayan/apps/acls/tests/mixins.py b/mayan/apps/acls/tests/mixins.py index 700a60709f..a86ea639c6 100644 --- a/mayan/apps/acls/tests/mixins.py +++ b/mayan/apps/acls/tests/mixins.py @@ -34,6 +34,10 @@ class ACLTestCaseMixin(RoleTestCaseMixin, UserTestCaseMixin): class ACLTestMixin(PermissionTestMixin, RoleTestMixin, TestModelTestMixin): auto_create_test_role = True + auto_create_test_object = False + + def _clear_model_permissions(self): + ModelPermission.clear() def _create_test_acl(self): self.test_acl = AccessControlList.objects.create( @@ -45,6 +49,9 @@ class ACLTestMixin(PermissionTestMixin, RoleTestMixin, TestModelTestMixin): if self.auto_create_test_role: self._create_test_role() + if self.auto_create_test_object: + self._setup_test_object() + def _inject_test_object_content_type(self): self.test_object_content_type = ContentType.objects.get_for_model( model=self.test_object @@ -52,7 +59,7 @@ class ACLTestMixin(PermissionTestMixin, RoleTestMixin, TestModelTestMixin): self.test_content_object_view_kwargs = { 'app_label': self.test_object_content_type.app_label, - 'model_name': self.test_object_content_type.model, + 'model': self.test_object_content_type.model, 'object_id': self.test_object.pk } diff --git a/mayan/apps/acls/tests/test_links.py b/mayan/apps/acls/tests/test_links.py index e5016bd497..fd45f8f253 100644 --- a/mayan/apps/acls/tests/test_links.py +++ b/mayan/apps/acls/tests/test_links.py @@ -1,9 +1,8 @@ from __future__ import unicode_literals -from django.contrib.contenttypes.models import ContentType from django.urls import reverse -from mayan.apps.documents.tests import GenericDocumentViewTestCase +from mayan.apps.common.tests import GenericViewTestCase from ..links import ( link_acl_delete, link_acl_list, link_acl_create, link_acl_permissions @@ -13,40 +12,34 @@ from ..permissions import permission_acl_edit, permission_acl_view from .mixins import ACLTestMixin -class ACLsLinksTestCase(ACLTestMixin, GenericDocumentViewTestCase): +class ACLsLinksTestCase(ACLTestMixin, GenericViewTestCase): def setUp(self): super(ACLsLinksTestCase, self).setUp() - self.test_object = self.test_document + self._setup_test_object() - def test_document_acl_create_link(self): + def test_object_acl_create_link(self): self.grant_access( - obj=self.test_document, permission=permission_acl_edit + obj=self.test_object, permission=permission_acl_edit ) - self.add_test_view(test_object=self.document) + self.add_test_view(test_object=self.test_object) context = self.get_test_view() resolved_link = link_acl_create.resolve(context=context) self.assertNotEqual(resolved_link, None) - content_type = ContentType.objects.get_for_model(self.test_document) - kwargs = { - 'app_label': content_type.app_label, - 'model': content_type.model, - 'object_id': self.document.pk - } - self.assertEqual( resolved_link.url, reverse( - viewname=link_acl_create.view, kwargs=kwargs + viewname=link_acl_create.view, + kwargs=self.test_content_object_view_kwargs ) ) - def test_document_acl_delete_link(self): + def test_object_acl_delete_link(self): self._create_test_acl() self.grant_access( - obj=self.test_document, permission=permission_acl_edit + obj=self.test_object, permission=permission_acl_edit ) self.add_test_view(test_object=self.test_acl) @@ -61,11 +54,11 @@ class ACLsLinksTestCase(ACLTestMixin, GenericDocumentViewTestCase): ) ) - def test_document_acl_edit_link(self): + def test_object_acl_edit_link(self): self._create_test_acl() self.grant_access( - obj=self.test_document, permission=permission_acl_edit + obj=self.test_object, permission=permission_acl_edit ) self.add_test_view(test_object=self.test_acl) @@ -81,25 +74,19 @@ class ACLsLinksTestCase(ACLTestMixin, GenericDocumentViewTestCase): ) ) - def test_document_acl_list_link(self): + def test_object_acl_list_link(self): self.grant_access( - obj=self.test_document, permission=permission_acl_view + obj=self.test_object, permission=permission_acl_view ) - self.add_test_view(test_object=self.test_document) + self.add_test_view(test_object=self.test_object) context = self.get_test_view() resolved_link = link_acl_list.resolve(context=context) self.assertNotEqual(resolved_link, None) - content_type = ContentType.objects.get_for_model(self.test_document) - kwargs = { - 'app_label': content_type.app_label, - 'model': content_type.model, - 'object_id': self.test_document.pk - } - self.assertEqual( resolved_link.url, reverse( - viewname=link_acl_list.view, kwargs=kwargs + viewname=link_acl_list.view, + kwargs=self.test_content_object_view_kwargs ) ) diff --git a/mayan/apps/acls/tests/test_models.py b/mayan/apps/acls/tests/test_models.py index 0f144dc985..c5f4caa847 100644 --- a/mayan/apps/acls/tests/test_models.py +++ b/mayan/apps/acls/tests/test_models.py @@ -1,14 +1,9 @@ from __future__ import absolute_import, unicode_literals from django.core.exceptions import PermissionDenied +from django.db import models from mayan.apps.common.tests import BaseTestCase -from mayan.apps.documents.models import Document, DocumentType -from mayan.apps.documents.permissions import permission_document_view -from mayan.apps.documents.tests import ( - TEST_SMALL_DOCUMENT_PATH, TEST_DOCUMENT_TYPE_LABEL, - TEST_DOCUMENT_TYPE_2_LABEL -) from ..classes import ModelPermission from ..models import AccessControlList @@ -17,138 +12,154 @@ from .mixins import ACLTestMixin class PermissionTestCase(ACLTestMixin, BaseTestCase): - def setUp(self): - super(PermissionTestCase, self).setUp() - self.document_type_1 = DocumentType.objects.create( - label=TEST_DOCUMENT_TYPE_LABEL - ) - - self.document_type_2 = DocumentType.objects.create( - label=TEST_DOCUMENT_TYPE_2_LABEL - ) - - with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object: - self.document_1 = self.document_type_1.new_document( - file_object=file_object - ) - - with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object: - self.document_2 = self.document_type_1.new_document( - file_object=file_object - ) - - with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object: - self.document_3 = self.document_type_2.new_document( - file_object=file_object - ) - - def tearDown(self): - for document_type in DocumentType.objects.all(): - document_type.delete() - super(PermissionTestCase, self).tearDown() + auto_create_test_object = False def test_check_access_without_permissions(self): + self._setup_test_object() + with self.assertRaises(PermissionDenied): AccessControlList.objects.check_access( - permissions=(permission_document_view,), - user=self._test_case_user, obj=self.document_1 + obj=self.test_object, + permissions=(self.test_permission,), + user=self._test_case_user, ) def test_filtering_without_permissions(self): - self.assertQuerysetEqual( + self._setup_test_object() + + self.assertEqual( AccessControlList.objects.filter_by_access( - permission=permission_document_view, user=self._test_case_user, - queryset=Document.objects.all() - ), [] + permission=self.test_permission, + queryset=self.test_object._meta.model._default_manager.all(), + user=self._test_case_user + ).count(), 0 ) def test_check_access_with_acl(self): + self._setup_test_object() + self.grant_access( - obj=self.document_1, permission=permission_document_view + obj=self.test_object, permission=self.test_permission ) try: AccessControlList.objects.check_access( - obj=self.document_1, permissions=(permission_document_view,), + obj=self.test_object, permissions=(self.test_permission,), user=self._test_case_user, ) except PermissionDenied: self.fail('PermissionDenied exception was not expected.') def test_filtering_with_permissions(self): + self._setup_test_object() + self.grant_access( - obj=self.document_1, permission=permission_document_view + obj=self.test_object, permission=self.test_permission ) - self.assertQuerysetEqual( - AccessControlList.objects.filter_by_access( - permission=permission_document_view, - queryset=Document.objects.all(), user=self._test_case_user - ), (repr(self.document_1),) + self.assertTrue( + self.test_object in AccessControlList.objects.filter_by_access( + permission=self.test_permission, + queryset=self.test_object._meta.model._default_manager.all(), + user=self._test_case_user + ) + ) + + def _setup_child_parent_test_objects(self): + self._create_test_permission() + self._create_test_model(model_name='TestModelParent') + self._create_test_model( + fields={ + 'parent': models.ForeignKey( + on_delete=models.CASCADE, related_name='children', + to='TestModelParent', + ) + }, model_name='TestModelChild' + ) + + ModelPermission.register( + model=self.TestModelParent, permissions=( + self.test_permission, + ) + ) + ModelPermission.register( + model=self.TestModelChild, permissions=( + self.test_permission, + ) + ) + ModelPermission.register_inheritance( + model=self.TestModelChild, related='parent', + ) + + self.test_object_parent = self.TestModelParent.objects.create() + self.test_object_child = self.TestModelChild.objects.create( + parent=self.test_object_parent ) def test_check_access_with_inherited_acl(self): + self._setup_child_parent_test_objects() + self.grant_access( - obj=self.document_type_1, permission=permission_document_view + obj=self.test_object_parent, permission=self.test_permission ) try: AccessControlList.objects.check_access( - obj=self.document_1, permissions=(permission_document_view,), + obj=self.test_object_child, permissions=(self.test_permission,), user=self._test_case_user ) except PermissionDenied: self.fail('PermissionDenied exception was not expected.') def test_check_access_with_inherited_acl_and_local_acl(self): + self._setup_child_parent_test_objects() + self.grant_access( - obj=self.document_type_1, permission=permission_document_view + obj=self.test_object_parent, permission=self.test_permission ) self.grant_access( - obj=self.document_3, permission=permission_document_view + obj=self.test_object_child, permission=self.test_permission ) try: AccessControlList.objects.check_access( - obj=self.document_3, permissions=(permission_document_view,), + obj=self.test_object_child, permissions=(self.test_permission,), user=self._test_case_user ) except PermissionDenied: self.fail('PermissionDenied exception was not expected.') def test_filtering_with_inherited_permissions(self): + self._setup_child_parent_test_objects() + self.grant_access( - obj=self.document_type_1, permission=permission_document_view + obj=self.test_object_parent, permission=self.test_permission ) result = AccessControlList.objects.filter_by_access( - permission=permission_document_view, - queryset=Document.objects.all(), user=self._test_case_user + permission=self.test_permission, + queryset=self.test_object_child._meta.model._default_manager.all(), + user=self._test_case_user ) - - # Since document_1 and document_2 are of document_type_1 - # they are the only ones that should be returned - - self.assertTrue(self.document_1 in result) - self.assertTrue(self.document_2 in result) - self.assertTrue(self.document_3 not in result) + self.assertTrue(self.test_object_child in result) def test_filtering_with_inherited_permissions_and_local_acl(self): - self.grant_permission(permission=permission_document_view) + self._setup_child_parent_test_objects() + + self.grant_permission(permission=self.test_permission) self.grant_access( - obj=self.document_type_1, permission=permission_document_view + obj=self.test_object_parent, permission=self.test_permission ) self.grant_access( - obj=self.document_3, permission=permission_document_view + obj=self.test_object_child, permission=self.test_permission ) result = AccessControlList.objects.filter_by_access( - permission=permission_document_view, - queryset=Document.objects.all(), user=self._test_case_user, + permission=self.test_permission, + queryset=self.test_object_child._meta.model._default_manager.all(), + user=self._test_case_user, ) - self.assertTrue(self.document_1 in result) - self.assertTrue(self.document_2 in result) - self.assertTrue(self.document_3 in result) + self.assertTrue(self.test_object_child in result) class InheritedPermissionTestCase(ACLTestMixin, BaseTestCase): @@ -182,3 +193,100 @@ class InheritedPermissionTestCase(ACLTestMixin, BaseTestCase): obj=self.test_object, role=self.test_role ) self.assertTrue(self.test_permission.stored_permission in queryset) + + def test_retrieve_inherited_related_parent_child_permission(self): + self._create_test_permission() + + self._create_test_model(model_name='TestModelParent') + self._create_test_model( + fields={ + 'parent': models.ForeignKey( + on_delete=models.CASCADE, related_name='children', + to='TestModelParent', + ) + }, model_name='TestModelChild' + ) + + ModelPermission.register( + model=self.TestModelParent, permissions=( + self.test_permission, + ) + ) + ModelPermission.register( + model=self.TestModelChild, permissions=( + self.test_permission, + ) + ) + ModelPermission.register_inheritance( + model=self.TestModelChild, related='parent', + ) + + parent = self.TestModelParent.objects.create() + child = self.TestModelChild.objects.create(parent=parent) + + AccessControlList.objects.grant( + obj=parent, permission=self.test_permission, role=self.test_role + ) + queryset = AccessControlList.objects.get_inherited_permissions( + obj=child, role=self.test_role + ) + + self.assertTrue(self.test_permission.stored_permission in queryset) + + def test_retrieve_inherited_related_grandparent_parent_child_permission(self): + self._create_test_permission() + + self._create_test_model(model_name='TestModelGrandParent') + self._create_test_model( + fields={ + 'parent': models.ForeignKey( + on_delete=models.CASCADE, related_name='children', + to='TestModelGrandParent', + ) + }, model_name='TestModelParent' + ) + self._create_test_model( + fields={ + 'parent': models.ForeignKey( + on_delete=models.CASCADE, related_name='children', + to='TestModelParent', + ) + }, model_name='TestModelChild' + ) + + ModelPermission.register( + model=self.TestModelGrandParent, permissions=( + self.test_permission, + ) + ) + ModelPermission.register( + model=self.TestModelParent, permissions=( + self.test_permission, + ) + ) + ModelPermission.register( + model=self.TestModelChild, permissions=( + self.test_permission, + ) + ) + ModelPermission.register_inheritance( + model=self.TestModelChild, related='parent', + ) + ModelPermission.register_inheritance( + model=self.TestModelParent, related='parent', + ) + + grandparent = self.TestModelGrandParent.objects.create() + parent = self.TestModelParent.objects.create(parent=grandparent) + child = self.TestModelChild.objects.create(parent=parent) + + AccessControlList.objects.grant( + obj=grandparent, permission=self.test_permission, + role=self.test_role + ) + + queryset = AccessControlList.objects.get_inherited_permissions( + obj=child, role=self.test_role + ) + + self.assertTrue(self.test_permission.stored_permission in queryset) diff --git a/mayan/apps/acls/tests/test_views.py b/mayan/apps/acls/tests/test_views.py index 3e56940acc..3fc9c63198 100644 --- a/mayan/apps/acls/tests/test_views.py +++ b/mayan/apps/acls/tests/test_views.py @@ -1,8 +1,6 @@ from __future__ import absolute_import, unicode_literals -from django.contrib.contenttypes.models import ContentType - -from mayan.apps.documents.tests import GenericDocumentViewTestCase +from mayan.apps.common.tests import GenericViewTestCase from ..models import AccessControlList from ..permissions import permission_acl_edit, permission_acl_view @@ -10,25 +8,17 @@ from ..permissions import permission_acl_edit, permission_acl_view from .mixins import ACLTestMixin -class AccessControlListViewTestCase(ACLTestMixin, GenericDocumentViewTestCase): +class AccessControlListViewTestCase(ACLTestMixin, GenericViewTestCase): def setUp(self): super(AccessControlListViewTestCase, self).setUp() - - content_type = ContentType.objects.get_for_model(self.test_document) - - self.view_arguments = { - 'app_label': content_type.app_label, - 'model': content_type.model, - 'object_id': self.test_document.pk - } - - self.test_object = self.test_document + self._setup_test_object() def _request_test_acl_create_get_view(self): return self.get( - viewname='acls:acl_create', kwargs=self.view_arguments, data={ + viewname='acls:acl_create', + kwargs=self.test_content_object_view_kwargs, data={ 'role': self.test_role.pk - }, follow=True + } ) def test_acl_create_get_view_no_permission(self): @@ -41,22 +31,21 @@ class AccessControlListViewTestCase(ACLTestMixin, GenericDocumentViewTestCase): def test_acl_create_get_view_with_access(self): self.grant_access( - obj=self.test_document, permission=permission_acl_edit + obj=self.test_object, permission=permission_acl_edit ) acl_count = AccessControlList.objects.count() response = self._request_test_acl_create_get_view() - self.assertContains( - response=response, text=self.test_document.label, status_code=200 - ) + self.assertEquals(response.status_code, 200) self.assertEqual(AccessControlList.objects.count(), acl_count) def _request_test_acl_create_post_view(self): return self.post( - viewname='acls:acl_create', kwargs=self.view_arguments, data={ + viewname='acls:acl_create', + kwargs=self.test_content_object_view_kwargs, data={ 'role': self.test_role.pk - }, follow=True + } ) def test_acl_create_view_post_no_permission(self): @@ -69,13 +58,14 @@ class AccessControlListViewTestCase(ACLTestMixin, GenericDocumentViewTestCase): def test_acl_create_view_post_with_access(self): self.grant_access( - obj=self.test_document, permission=permission_acl_edit + obj=self.test_object, permission=permission_acl_edit ) acl_count = AccessControlList.objects.count() response = self._request_test_acl_create_post_view() - self.assertContains(response=response, text='created', status_code=200) + self.assertEquals(response.status_code, 302) + self.assertEqual(AccessControlList.objects.count(), acl_count + 1) def test_orphan_acl_create_view_with_permission(self): @@ -85,48 +75,36 @@ class AccessControlListViewTestCase(ACLTestMixin, GenericDocumentViewTestCase): """ self.grant_permission(permission=permission_acl_edit) - recent_entry = self.test_document.add_as_recent_document_for_user( - self._test_case_user - ) - - content_type = ContentType.objects.get_for_model(recent_entry) - - view_arguments = { - 'app_label': content_type.app_label, - 'model': content_type.model, - 'object_id': recent_entry.pk - } + self._clear_model_permissions() response = self.post( - viewname='acls:acl_create', kwargs=view_arguments, data={ + viewname='acls:acl_create', + kwargs=self.test_content_object_view_kwargs, data={ 'role': self.test_role.pk }, follow=True ) - self.assertNotContains(response, text='optgroup', status_code=200) + self.assertNotContains( + response=response, text='optgroup', status_code=200 + ) + self.assertEqual(AccessControlList.objects.count(), 1) def test_acl_list_view_no_permission(self): self._create_test_acl() response = self.get( - viewname='acls:acl_list', kwargs=self.view_arguments - ) - - self.assertNotContains( - response=response, text=self.document.label, status_code=403 - ) - self.assertNotContains( - response=response, text='otal: 1', status_code=403 + viewname='acls:acl_list', + kwargs=self.test_content_object_view_kwargs ) + self.assertEqual(response.status_code, 403) def test_acl_list_view_with_permission(self): self.grant_access( - obj=self.test_document, permission=permission_acl_view + obj=self.test_object, permission=permission_acl_view ) response = self.get( - viewname='acls:acl_list', kwargs=self.view_arguments - ) - self.assertContains( - response=response, text=self.test_document.label, status_code=200 + viewname='acls:acl_list', + kwargs=self.test_content_object_view_kwargs ) + self.assertEqual(response.status_code, 200)