From c5f64d4805936a9bed182a4f64d56106b0a588b6 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 25 May 2016 02:43:12 -0400 Subject: [PATCH] Make the acls app organizations aware. --- mayan/apps/acls/managers.py | 6 +-- .../0003_accesscontrollist_organization.py | 21 +++++++++ mayan/apps/acls/models.py | 7 +++ mayan/apps/acls/tests/test_models.py | 35 +++++++------- mayan/apps/acls/tests/test_views.py | 14 +++--- mayan/apps/acls/views.py | 23 +++++---- mayan/apps/organizations/management.py | 47 ------------------- 7 files changed, 70 insertions(+), 83 deletions(-) create mode 100644 mayan/apps/acls/migrations/0003_accesscontrollist_organization.py delete mode 100644 mayan/apps/organizations/management.py diff --git a/mayan/apps/acls/managers.py b/mayan/apps/acls/managers.py index e9bbb88b5b..7161407ccf 100644 --- a/mayan/apps/acls/managers.py +++ b/mayan/apps/acls/managers.py @@ -74,14 +74,14 @@ class AccessControlListManager(models.Manager): pass user_roles = [] - for group in user.groups.all(): + for group in user.organization_groups.all(): for role in group.roles.all(): if set(stored_permissions).intersection(set(self.get_inherited_permissions(role=role, obj=obj))): return True user_roles.append(role) - if not self.filter(content_type=ContentType.objects.get_for_model(obj), object_id=obj.pk, permissions__in=stored_permissions, role__in=user_roles).exists(): + if not self.model.on_organization.filter(content_type=ContentType.objects.get_for_model(obj), object_id=obj.pk, permissions__in=stored_permissions, role__in=user_roles).exists(): raise PermissionDenied(ugettext('Insufficient access.')) def filter_by_access(self, permission, user, queryset): @@ -89,7 +89,7 @@ class AccessControlListManager(models.Manager): return queryset user_roles = [] - for group in user.groups.all(): + for group in user.organization_groups.all(): for role in group.roles.all(): user_roles.append(role) diff --git a/mayan/apps/acls/migrations/0003_accesscontrollist_organization.py b/mayan/apps/acls/migrations/0003_accesscontrollist_organization.py new file mode 100644 index 0000000000..c716ca01da --- /dev/null +++ b/mayan/apps/acls/migrations/0003_accesscontrollist_organization.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import organizations.shortcuts + + +class Migration(migrations.Migration): + + dependencies = [ + ('organizations', '0002_add_data_default_organization'), + ('acls', '0002_auto_20150703_0513'), + ] + + operations = [ + migrations.AddField( + model_name='accesscontrollist', + name='organization', + field=models.ForeignKey(default=organizations.shortcuts.get_current_organization, to='organizations.Organization'), + ), + ] diff --git a/mayan/apps/acls/models.py b/mayan/apps/acls/models.py index 03db1cbebd..82014c7e25 100644 --- a/mayan/apps/acls/models.py +++ b/mayan/apps/acls/models.py @@ -8,6 +8,9 @@ from django.db import models from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ +from organizations.models import Organization +from organizations.managers import CurrentOrganizationManager +from organizations.shortcuts import get_current_organization from permissions.models import Role, StoredPermission from .managers import AccessControlListManager @@ -30,6 +33,9 @@ class AccessControlList(models.Model): ct_field='content_type', fk_field='object_id', ) + organization = models.ForeignKey( + Organization, default=get_current_organization + ) # TODO: limit choices to the permissions valid for the content_object permissions = models.ManyToManyField( StoredPermission, blank=True, related_name='acls', @@ -38,6 +44,7 @@ class AccessControlList(models.Model): role = models.ForeignKey(Role, related_name='acls', verbose_name=_('Role')) objects = AccessControlListManager() + on_organization = CurrentOrganizationManager() class Meta: unique_together = ('content_type', 'object_id', 'role') diff --git a/mayan/apps/acls/tests/test_models.py b/mayan/apps/acls/tests/test_models.py index 571350452c..ef21022cad 100644 --- a/mayan/apps/acls/tests/test_models.py +++ b/mayan/apps/acls/tests/test_models.py @@ -1,16 +1,17 @@ from __future__ import absolute_import, unicode_literals from django.contrib.auth import get_user_model -from django.contrib.auth.models import Group from django.core.exceptions import PermissionDenied from django.test import TestCase, override_settings from documents.models import Document, DocumentType from documents.permissions import permission_document_view from documents.tests import TEST_SMALL_DOCUMENT_PATH, TEST_DOCUMENT_TYPE +from organizations.utils import create_default_organization from permissions.classes import Permission from permissions.models import Role from permissions.tests.literals import TEST_ROLE_LABEL +from user_management.models import MayanGroup from user_management.tests.literals import TEST_USER_USERNAME, TEST_GROUP from ..models import AccessControlList @@ -21,11 +22,13 @@ TEST_DOCUMENT_TYPE_2 = 'test document type 2' @override_settings(OCR_AUTO_OCR=False) class PermissionTestCase(TestCase): def setUp(self): - self.document_type_1 = DocumentType.objects.create( + create_default_organization() + + self.document_type_1 = DocumentType.on_organization.create( label=TEST_DOCUMENT_TYPE ) - self.document_type_2 = DocumentType.objects.create( + self.document_type_2 = DocumentType.on_organization.create( label=TEST_DOCUMENT_TYPE_2 ) @@ -44,19 +47,19 @@ class PermissionTestCase(TestCase): file_object=file_object ) - self.user = get_user_model().objects.create( + self.user = get_user_model().on_organization.create( username=TEST_USER_USERNAME ) - self.group = Group.objects.create(name=TEST_GROUP) - self.role = Role.objects.create(label=TEST_ROLE_LABEL) + self.group = MayanGroup.on_organization.create(name=TEST_GROUP) + self.role = Role.on_organization.create(label=TEST_ROLE_LABEL) self.group.user_set.add(self.user) - self.role.groups.add(self.group) + self.role.organization_groups.add(self.group) Permission.invalidate_cache() def tearDown(self): - for document_type in DocumentType.objects.all(): + for document_type in DocumentType.on_organization.all(): document_type.delete() def test_check_access_without_permissions(self): @@ -75,7 +78,7 @@ class PermissionTestCase(TestCase): ) def test_check_access_with_acl(self): - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_1, role=self.role ) acl.permissions.add(permission_document_view.stored_permission) @@ -91,7 +94,7 @@ class PermissionTestCase(TestCase): def test_filtering_with_permissions(self): self.role.permissions.add(permission_document_view.stored_permission) - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_1, role=self.role ) acl.permissions.add(permission_document_view.stored_permission) @@ -104,7 +107,7 @@ class PermissionTestCase(TestCase): ) def test_check_access_with_inherited_acl(self): - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_type_1, role=self.role ) acl.permissions.add(permission_document_view.stored_permission) @@ -118,12 +121,12 @@ class PermissionTestCase(TestCase): self.fail('PermissionDenied exception was not expected.') def test_check_access_with_inherited_acl_and_local_acl(self): - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_type_1, role=self.role ) acl.permissions.add(permission_document_view.stored_permission) - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_3, role=self.role ) acl.permissions.add(permission_document_view.stored_permission) @@ -139,7 +142,7 @@ class PermissionTestCase(TestCase): def test_filtering_with_inherited_permissions(self): self.role.permissions.add(permission_document_view.stored_permission) - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_type_1, role=self.role ) acl.permissions.add(permission_document_view.stored_permission) @@ -155,12 +158,12 @@ class PermissionTestCase(TestCase): def test_filtering_with_inherited_permissions_and_local_acl(self): self.role.permissions.add(permission_document_view.stored_permission) - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_type_1, role=self.role ) acl.permissions.add(permission_document_view.stored_permission) - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_3, role=self.role ) acl.permissions.add(permission_document_view.stored_permission) diff --git a/mayan/apps/acls/tests/test_views.py b/mayan/apps/acls/tests/test_views.py index 52d0e74afc..c7347cd6c7 100644 --- a/mayan/apps/acls/tests/test_views.py +++ b/mayan/apps/acls/tests/test_views.py @@ -33,7 +33,7 @@ class AccessControlListViewTestCase(GenericDocumentViewTestCase): ) self.assertEquals(response.status_code, 403) - self.assertEqual(AccessControlList.objects.count(), 0) + self.assertEqual(AccessControlList.on_organization.count(), 0) def test_acl_create_view_with_permission(self): self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) @@ -49,7 +49,7 @@ class AccessControlListViewTestCase(GenericDocumentViewTestCase): ) self.assertContains(response, text='created', status_code=200) - self.assertEqual(AccessControlList.objects.count(), 1) + self.assertEqual(AccessControlList.on_organization.count(), 1) def test_acl_create_duplicate_view_with_permission(self): """ @@ -57,7 +57,7 @@ class AccessControlListViewTestCase(GenericDocumentViewTestCase): Result: Should redirect to existing ACL for object + role combination """ - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document, role=self.role ) @@ -76,8 +76,8 @@ class AccessControlListViewTestCase(GenericDocumentViewTestCase): self.assertContains( response, text='vailable permissions', status_code=200 ) - self.assertEqual(AccessControlList.objects.count(), 1) - self.assertEqual(AccessControlList.objects.first().pk, acl.pk) + self.assertEqual(AccessControlList.on_organization.count(), 1) + self.assertEqual(AccessControlList.on_organization.first().pk, acl.pk) def test_orphan_acl_create_view_with_permission(self): """ @@ -93,7 +93,7 @@ class AccessControlListViewTestCase(GenericDocumentViewTestCase): recent_entry = self.document.add_as_recent_document_for_user(self.user) - content_type = ContentType.objects.get_for_model(recent_entry) + content_type = ContentType.on_organization.get_for_model(recent_entry) view_arguments = { 'app_label': content_type.app_label, @@ -108,4 +108,4 @@ class AccessControlListViewTestCase(GenericDocumentViewTestCase): ) self.assertNotContains(response, text='optgroup', status_code=200) - self.assertEqual(AccessControlList.objects.count(), 1) + self.assertEqual(AccessControlList.on_organization.count(), 1) diff --git a/mayan/apps/acls/views.py b/mayan/apps/acls/views.py index 1d827fbd81..1fdc5e941a 100644 --- a/mayan/apps/acls/views.py +++ b/mayan/apps/acls/views.py @@ -26,7 +26,6 @@ logger = logging.getLogger(__name__) class ACLCreateView(SingleObjectCreateView): fields = ('role',) - model = AccessControlList def dispatch(self, request, *args, **kwargs): self.content_type = get_object_or_404( @@ -52,14 +51,9 @@ class ACLCreateView(SingleObjectCreateView): return super(ACLCreateView, self).dispatch(request, *args, **kwargs) - def get_instance_extra_data(self): - return { - 'content_object': self.content_object - } - def form_valid(self, form): try: - acl = AccessControlList.objects.get( + acl = AccessControlList.on_organization.get( content_type=self.content_type, object_id=self.content_object.pk, role=form.cleaned_data['role'] @@ -79,6 +73,14 @@ class ACLCreateView(SingleObjectCreateView): ) % self.content_object } + def get_instance_extra_data(self): + return { + 'content_object': self.content_object + } + + def get_queryset(self): + return AccessControlList.on_organization.all() + def get_success_url(self): if self.object.pk: return reverse('acls:acl_permissions', args=(self.object.pk,)) @@ -87,8 +89,6 @@ class ACLCreateView(SingleObjectCreateView): class ACLDeleteView(SingleObjectDeleteView): - model = AccessControlList - def dispatch(self, request, *args, **kwargs): acl = get_object_or_404(AccessControlList, pk=self.kwargs['pk']) @@ -118,6 +118,9 @@ class ACLDeleteView(SingleObjectDeleteView): ) ) + def get_queryset(self): + return AccessControlList.on_organization.all() + class ACLListView(SingleObjectListView): def dispatch(self, request, *args, **kwargs): @@ -152,7 +155,7 @@ class ACLListView(SingleObjectListView): } def get_queryset(self): - return AccessControlList.objects.filter( + return AccessControlList.on_organization.filter( content_type=self.content_type, object_id=self.content_object.pk ) diff --git a/mayan/apps/organizations/management.py b/mayan/apps/organizations/management.py deleted file mode 100644 index 800c1b81b8..0000000000 --- a/mayan/apps/organizations/management.py +++ /dev/null @@ -1,47 +0,0 @@ -from __future__ import unicode_literals - -from django.apps import apps -from django.core.management.color import no_style -from django.db import DEFAULT_DB_ALIAS, connections, router -from django.db.models import signals - - -def create_default_organization(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): - """ - Creates the default Organization object. - """ - - try: - Organization = apps.get_model('organizations', 'Organization') - except LookupError: - return - - if not router.allow_migrate(using, Organization): - return - - if not Organization.objects.using(using).exists(): - # The default settings set ORGANIZATION_ID = 1, and some tests in Django's test - # suite rely on this value. However, if database sequences are reused - # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that - # the next id will be 1, so we coerce it. See #15573 and #16353. This - # can also crop up outside of tests - see #15346. - if verbosity >= 2: - print("Creating default Organization object") - Organization(pk=1, label='Default').save(using=using) - - # We set an explicit pk instead of relying on auto-incrementation, - # so we need to reset the database sequence. See #17415. - sequence_sql = connections[using].ops.sequence_reset_sql(no_style(), [Organization]) - if sequence_sql: - if verbosity >= 2: - print('Resetting sequence') - with connections[using].cursor() as cursor: - for command in sequence_sql: - cursor.execute(command) - - Organization.objects.clear_cache() - - -signals.post_migrate.connect( - create_default_organization, sender=apps.get_app_config('organizations') -)