From db1673dd0a650ed457a4f2c0fef2fa30cb699bb5 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Mon, 30 May 2016 15:37:58 -0400 Subject: [PATCH] Convert sources app to use organizations. --- mayan/apps/sources/api_views.py | 4 +- mayan/apps/sources/apps.py | 2 +- mayan/apps/sources/forms.py | 7 +- mayan/apps/sources/handlers.py | 10 +-- .../migrations/0011_source_organization.py | 21 ++++++ mayan/apps/sources/models.py | 68 ++++++++++++++++-- mayan/apps/sources/tasks.py | 10 +-- mayan/apps/sources/tests/literals.py | 6 ++ mayan/apps/sources/tests/test_models.py | 30 +++++--- .../sources/tests/test_organization_views.py | 71 +++++++++++++++++++ mayan/apps/sources/tests/test_views.py | 45 ++++++------ mayan/apps/sources/views.py | 70 +++++++++--------- mayan/apps/sources/wizards.py | 2 +- 13 files changed, 263 insertions(+), 83 deletions(-) create mode 100644 mayan/apps/sources/migrations/0011_source_organization.py create mode 100644 mayan/apps/sources/tests/literals.py create mode 100644 mayan/apps/sources/tests/test_organization_views.py diff --git a/mayan/apps/sources/api_views.py b/mayan/apps/sources/api_views.py index c825a4bae2..32f581e1f9 100644 --- a/mayan/apps/sources/api_views.py +++ b/mayan/apps/sources/api_views.py @@ -40,7 +40,7 @@ class APIStagingSourceListView(generics.ListAPIView): """ serializer_class = StagingFolderSerializer - queryset = StagingFolderSource.objects.all() + queryset = StagingFolderSource.on_organization.all() class APIStagingSourceView(generics.RetrieveAPIView): @@ -48,7 +48,7 @@ class APIStagingSourceView(generics.RetrieveAPIView): Details of the selected staging folders and the files it contains. """ serializer_class = StagingFolderSerializer - queryset = StagingFolderSource.objects.all() + queryset = StagingFolderSource.on_organization.all() class APIStagingSourceFileImageView(generics.GenericAPIView): diff --git a/mayan/apps/sources/apps.py b/mayan/apps/sources/apps.py index 076e4206b5..c1dcde7f14 100644 --- a/mayan/apps/sources/apps.py +++ b/mayan/apps/sources/apps.py @@ -56,7 +56,7 @@ class SourcesApp(MayanAppConfig): 'feed to Mayan EDMS, create at least a web form source to ' 'be able to upload documents from a browser.' ), - condition=lambda: not Source.objects.exists(), + condition=lambda: not Source.on_organization.exists(), view='sources:setup_source_list' ) diff --git a/mayan/apps/sources/forms.py b/mayan/apps/sources/forms.py index 5a6848511c..747fba5e38 100644 --- a/mayan/apps/sources/forms.py +++ b/mayan/apps/sources/forms.py @@ -9,8 +9,8 @@ from django.utils.translation import ugettext_lazy as _ from documents.forms import DocumentForm from .models import ( - IMAPEmail, POP3Email, StagingFolderSource, WebFormSource, - WatchFolderSource + IMAPEmail, POP3Email, StagingFolderSource, WatchFolderSource, + WebFormSource ) logger = logging.getLogger(__name__) @@ -80,6 +80,9 @@ class WebFormUploadFormHTML5(WebFormUploadForm): class WebFormSetupForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + super(WebFormSetupForm, self).__init__(*args, **kwargs) + class Meta: fields = ('label', 'enabled', 'uncompress') model = WebFormSource diff --git a/mayan/apps/sources/handlers.py b/mayan/apps/sources/handlers.py index 7204cab63e..664d55a230 100644 --- a/mayan/apps/sources/handlers.py +++ b/mayan/apps/sources/handlers.py @@ -9,8 +9,8 @@ from .literals import SOURCE_UNCOMPRESS_CHOICE_ASK def create_default_document_source(sender, **kwargs): WebFormSource = get_model('sources', 'WebFormSource') - if not WebFormSource.objects.count(): - WebFormSource.objects.create( + if not WebFormSource.on_organization.count(): + WebFormSource.on_organization.create( label=_('Default'), uncompress=SOURCE_UNCOMPRESS_CHOICE_ASK ) @@ -32,11 +32,11 @@ def initialize_periodic_tasks(sender, **kwargs): IMAPEmail = get_model('sources', 'IMAPEmail') WatchFolderSource = get_model('sources', 'WatchFolderSource') - for source in POP3Email.objects.filter(enabled=True): + for source in POP3Email.on_organization.filter(enabled=True): source.save() - for source in IMAPEmail.objects.filter(enabled=True): + for source in IMAPEmail.on_organization.filter(enabled=True): source.save() - for source in WatchFolderSource.objects.filter(enabled=True): + for source in WatchFolderSource.on_organization.filter(enabled=True): source.save() diff --git a/mayan/apps/sources/migrations/0011_source_organization.py b/mayan/apps/sources/migrations/0011_source_organization.py new file mode 100644 index 0000000000..d4ee4273bc --- /dev/null +++ b/mayan/apps/sources/migrations/0011_source_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'), + ('sources', '0010_auto_20151001_0055'), + ] + + operations = [ + migrations.AddField( + model_name='source', + name='organization', + field=models.ForeignKey(default=organizations.shortcuts.get_current_organization, to='organizations.Organization'), + ), + ] diff --git a/mayan/apps/sources/models.py b/mayan/apps/sources/models.py index ed8cc90c6b..d0c6ffb073 100644 --- a/mayan/apps/sources/models.py +++ b/mayan/apps/sources/models.py @@ -11,6 +11,7 @@ import poplib import yaml +from django.conf import settings from django.core.exceptions import ValidationError from django.core.files import File from django.core.files.base import ContentFile @@ -18,7 +19,7 @@ from django.db import models, transaction from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ -from model_utils.managers import InheritanceManager +from model_utils.managers import InheritanceManager, InheritanceQuerySet from common.compressed_files import CompressedFile, NotACompressedFile from converter.literals import DIMENSION_SEPARATOR @@ -28,7 +29,9 @@ from documents.models import Document, DocumentType from documents.settings import setting_language from metadata.api import save_metadata_list, set_bulk_metadata from metadata.models import MetadataType -from tags.models import Tag +from organizations.models import Organization +from organizations.managers import CurrentOrganizationManager +from organizations.shortcuts import get_current_organization from .classes import Attachment, SourceUploadedFile, StagingFile from .literals import ( @@ -43,12 +46,24 @@ from .literals import ( logger = logging.getLogger(__name__) +class OrganizationSourceManager(InheritanceManager, CurrentOrganizationManager): + def get_queryset(self): + return InheritanceQuerySet(self.model).filter( + **{self._get_field_name() + '__id': settings.ORGANIZATION_ID} + ) + + + @python_2_unicode_compatible class Source(models.Model): + organization = models.ForeignKey( + Organization, default=get_current_organization + ) label = models.CharField(max_length=64, verbose_name=_('Label')) enabled = models.BooleanField(default=True, verbose_name=_('Enabled')) objects = InheritanceManager() + on_organization = OrganizationSourceManager() @classmethod def class_fullname(cls): @@ -63,7 +78,7 @@ class Source(models.Model): def upload_document(self, file_object, document_type, description=None, label=None, language=None, metadata_dict_list=None, metadata_dictionary=None, tag_ids=None, user=None): try: with transaction.atomic(): - document = Document.objects.create( + document = Document.on_organization.create( description=description or '', document_type=document_type, label=label or file_object.name, language=language or setting_language.value @@ -93,7 +108,7 @@ class Source(models.Model): ) if tag_ids: - for tag in Tag.objects.filter(pk__in=tag_ids): + for tag in Tag.on_organization.filter(pk__in=tag_ids): tag.documents.add(document) except Exception as exception: @@ -147,6 +162,7 @@ class Source(models.Model): class InteractiveSource(Source): objects = InheritanceManager() + on_organization = OrganizationSourceManager() class Meta: verbose_name = _('Interactive source') @@ -183,6 +199,9 @@ class StagingFolderSource(InteractiveSource): verbose_name=_('Delete after upload') ) + objects = InheritanceManager() + on_organization = OrganizationSourceManager() + def get_preview_size(self): dimensions = [] dimensions.append(unicode(self.preview_width)) @@ -248,6 +267,12 @@ class WebFormSource(InteractiveSource): def get_upload_file_object(self, form_data): return SourceUploadedFile(source=self, file=form_data['file']) + # Custom model managers are not inherited is base class is not abstract. + # This will change in Django 1.10 + # https://docs.djangoproject.com/en/1.8/topics/db/managers/#custom-managers-and-model-inheritance + objects = InheritanceManager() + on_organization = OrganizationSourceManager() + class Meta: verbose_name = _('Web form') verbose_name_plural = _('Web forms') @@ -256,6 +281,11 @@ class WebFormSource(InteractiveSource): class OutOfProcessSource(Source): is_interactive = False + # Custom model managers are not inherited is base class is not abstract. + # This will change in Django 1.10 + # https://docs.djangoproject.com/en/1.8/topics/db/managers/#custom-managers-and-model-inheritance + on_organization = OrganizationSourceManager() + class Meta: verbose_name = _('Out of process') verbose_name_plural = _('Out of process') @@ -280,6 +310,12 @@ class IntervalBaseModel(OutOfProcessSource): max_length=1, verbose_name=_('Uncompress') ) + # Custom model managers are not inherited is base class is not abstract. + # This will change in Django 1.10 + # https://docs.djangoproject.com/en/1.8/topics/db/managers/#custom-managers-and-model-inheritance + objects = InheritanceManager() + on_organization = OrganizationSourceManager() + def _get_periodic_task_name(self, pk=None): return 'check_interval_source-%i' % (pk or self.pk) @@ -368,6 +404,12 @@ class EmailBaseModel(IntervalBaseModel): ), verbose_name=_('Store email body') ) + # Custom model managers are not inherited is base class is not abstract. + # This will change in Django 1.10 + # https://docs.djangoproject.com/en/1.8/topics/db/managers/#custom-managers-and-model-inheritance + objects = InheritanceManager() + on_organization = OrganizationSourceManager() + def clean(self): if self.subject_metadata_type: if self.subject_metadata_type.pk not in self.document_type.metadata.values_list('metadata_type', flat=True): @@ -488,6 +530,12 @@ class POP3Email(EmailBaseModel): default=DEFAULT_POP3_TIMEOUT, verbose_name=_('Timeout') ) + # Custom model managers are not inherited is base class is not abstract. + # This will change in Django 1.10 + # https://docs.djangoproject.com/en/1.8/topics/db/managers/#custom-managers-and-model-inheritance + objects = InheritanceManager() + on_organization = OrganizationSourceManager() + def check_source(self): logger.debug('Starting POP3 email fetch') logger.debug('host: %s', self.host) @@ -535,6 +583,12 @@ class IMAPEmail(EmailBaseModel): max_length=64, verbose_name=_('Mailbox') ) + # Custom model managers are not inherited is base class is not abstract. + # This will change in Django 1.10 + # https://docs.djangoproject.com/en/1.8/topics/db/managers/#custom-managers-and-model-inheritance + objects = InheritanceManager() + on_organization = OrganizationSourceManager() + # http://www.doughellmann.com/PyMOTW/imaplib/ def check_source(self): logger.debug('Starting IMAP email fetch') @@ -579,6 +633,12 @@ class WatchFolderSource(IntervalBaseModel): verbose_name=_('Folder path') ) + # Custom model managers are not inherited is base class is not abstract. + # This will change in Django 1.10 + # https://docs.djangoproject.com/en/1.8/topics/db/managers/#custom-managers-and-model-inheritance + objects = InheritanceManager() + on_organization = OrganizationSourceManager() + def check_source(self): # Force self.folder_path to unicode to avoid os.listdir returning # str for non-latin filenames, gh-issue #163 diff --git a/mayan/apps/sources/tasks.py b/mayan/apps/sources/tasks.py index 6d26b7fa8d..4faa10265b 100644 --- a/mayan/apps/sources/tasks.py +++ b/mayan/apps/sources/tasks.py @@ -21,7 +21,7 @@ def task_check_interval_source(source_id): app_label='sources', model_name='Source' ) - source = Source.objects.get_subclass(pk=source_id) + source = Source.on_organization.get_subclass(pk=source_id) if source.enabled: try: source.check_source() @@ -49,14 +49,14 @@ def task_upload_document(self, source_id, document_type_id, shared_uploaded_file ) try: - document_type = DocumentType.objects.get(pk=document_type_id) - source = Source.objects.get_subclass(pk=source_id) + document_type = DocumentType.on_organization.get(pk=document_type_id) + source = Source.on_organization.get_subclass(pk=source_id) shared_upload = SharedUploadedFile.objects.get( pk=shared_uploaded_file_id ) if user_id: - user = get_user_model().objects.get(pk=user_id) + user = get_user_model().on_organization.get(pk=user_id) else: user = None @@ -96,7 +96,7 @@ def task_source_handle_upload(self, document_type_id, shared_uploaded_file_id, s ) try: - document_type = DocumentType.objects.get(pk=document_type_id) + document_type = DocumentType.on_organization.get(pk=document_type_id) shared_upload = SharedUploadedFile.objects.get( pk=shared_uploaded_file_id ) diff --git a/mayan/apps/sources/tests/literals.py b/mayan/apps/sources/tests/literals.py new file mode 100644 index 0000000000..e95a75bdd4 --- /dev/null +++ b/mayan/apps/sources/tests/literals.py @@ -0,0 +1,6 @@ +from __future__ import unicode_literals + +TEST_SOURCE_LABEL = 'test source label' +TEST_SOURCE_EDITED_LABEL = 'test source label edited' +TEST_SOURCE_UNCOMPRESS_N = 'n' +TEST_STAGING_PREVIEW_WIDTH = 640 diff --git a/mayan/apps/sources/tests/test_models.py b/mayan/apps/sources/tests/test_models.py index d5713455b6..2aeab65e73 100644 --- a/mayan/apps/sources/tests/test_models.py +++ b/mayan/apps/sources/tests/test_models.py @@ -14,6 +14,8 @@ from documents.tests import ( TEST_NON_ASCII_DOCUMENT_FILENAME, TEST_NON_ASCII_DOCUMENT_PATH, TEST_NON_ASCII_COMPRESSED_DOCUMENT_PATH ) +from organizations.models import Organization +from organizations.utils import create_default_organization from user_management.tests import ( TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME ) @@ -29,7 +31,8 @@ class UploadDocumentTestCase(TestCase): """ def setUp(self): - self.document_type = DocumentType.objects.create( + create_default_organization() + self.document_type = DocumentType.on_organization.create( label=TEST_DOCUMENT_TYPE ) @@ -43,6 +46,9 @@ class UploadDocumentTestCase(TestCase): self.document_type.delete() self.admin_user.delete() + Organization.objects.all().delete() + Organization.objects.clear_cache() + def test_issue_gh_163(self): """ Non-ASCII chars in document name failing in upload via watch folder @@ -52,15 +58,15 @@ class UploadDocumentTestCase(TestCase): temporary_directory = tempfile.mkdtemp() shutil.copy(TEST_NON_ASCII_DOCUMENT_PATH, temporary_directory) - watch_folder = WatchFolderSource.objects.create( + watch_folder = WatchFolderSource.on_organization.create( document_type=self.document_type, folder_path=temporary_directory, uncompress=SOURCE_UNCOMPRESS_CHOICE_Y ) watch_folder.check_source() - self.assertEqual(Document.objects.count(), 1) + self.assertEqual(Document.on_organization.count(), 1) - document = Document.objects.first() + document = Document.on_organization.first() self.assertEqual(document.exists(), True) self.assertEqual(document.size, 17436) @@ -77,9 +83,9 @@ class UploadDocumentTestCase(TestCase): ) watch_folder.check_source() - document = Document.objects.all()[1] + document = Document.on_organization.all()[1] - self.assertEqual(Document.objects.count(), 2) + self.assertEqual(Document.on_organization.count(), 2) self.assertEqual(document.exists(), True) self.assertEqual(document.size, 17436) @@ -95,12 +101,16 @@ class UploadDocumentTestCase(TestCase): @override_settings(OCR_AUTO_OCR=False) class CompressedUploadsTestCase(TestCase): def setUp(self): - self.document_type = DocumentType.objects.create( + create_default_organization() + + self.document_type = DocumentType.on_organization.create( label=TEST_DOCUMENT_TYPE ) def tearDown(self): self.document_type.delete() + Organization.objects.all().delete() + Organization.objects.clear_cache() def test_upload_compressed_file(self): source = WebFormSource( @@ -114,14 +124,14 @@ class CompressedUploadsTestCase(TestCase): expand=(source.uncompress == SOURCE_UNCOMPRESS_CHOICE_Y) ) - self.assertEqual(Document.objects.count(), 2) + self.assertEqual(Document.on_organization.count(), 2) self.assertTrue( - 'first document.pdf' in Document.objects.values_list( + 'first document.pdf' in Document.on_organization.values_list( 'label', flat=True ) ) self.assertTrue( - 'second document.pdf' in Document.objects.values_list( + 'second document.pdf' in Document.on_organization.values_list( 'label', flat=True ) ) diff --git a/mayan/apps/sources/tests/test_organization_views.py b/mayan/apps/sources/tests/test_organization_views.py new file mode 100644 index 0000000000..c1b1ee016b --- /dev/null +++ b/mayan/apps/sources/tests/test_organization_views.py @@ -0,0 +1,71 @@ +from __future__ import unicode_literals + +from organizations.tests.test_organization_views import OrganizationViewTestCase + +from ..models import WebFormSource +from ..utils import get_class, get_form_class, get_upload_form_class + +from .literals import ( + TEST_SOURCE_LABEL, TEST_SOURCE_EDITED_LABEL, TEST_SOURCE_UNCOMPRESS_N +) + + +class SourceOrganizationViewTestCase(OrganizationViewTestCase): + def create_source(self): + with self.settings(ORGANIZATION_ID=self.organization_a.pk): + self.source = WebFormSource.on_organization.create( + enabled=True, label=TEST_SOURCE_LABEL, + uncompress=TEST_SOURCE_UNCOMPRESS_N + ) + + def test_source_create_view(self): + # Create a source for organization A + with self.settings(ORGANIZATION_ID=self.organization_a.pk): + response = self.post( + 'sources:setup_source_create', + args=(WebFormSource.source_type,), data={ + 'label': TEST_SOURCE_LABEL, + 'uncompress': TEST_SOURCE_UNCOMPRESS_N + } + ) + self.assertNotContains(response, text='danger', status_code=302) + self.assertEqual(WebFormSource.on_organization.count(), 1) + + with self.settings(ORGANIZATION_ID=self.organization_b.pk): + self.assertEqual(WebFormSource.on_organization.count(), 0) + + def test_source_delete_view(self): + self.create_source() + + with self.settings(ORGANIZATION_ID=self.organization_b.pk): + response = self.post( + 'sources:setup_source_delete', args=(self.source.pk,) + ) + self.assertEqual(response.status_code, 404) + + def test_source_edit_view(self): + self.create_source() + + with self.settings(ORGANIZATION_ID=self.organization_b.pk): + # Make sure admin for organization B cannot edit the source + response = self.post( + 'sources:setup_source_edit', args=(self.source.pk,), data={ + 'label': TEST_SOURCE_EDITED_LABEL + } + ) + + self.assertEqual(response.status_code, 404) + + def test_source_list_view(self): + self.create_source() + + with self.settings(ORGANIZATION_ID=self.organization_b.pk): + # Make sure admin for organization B cannot find the source for + # organization A + response = self.get( + 'sources:setup_source_list', + ) + + self.assertNotContains( + response, text=self.source.label, status_code=200 + ) diff --git a/mayan/apps/sources/tests/test_views.py b/mayan/apps/sources/tests/test_views.py index 2ad5038f77..7e35f318e5 100644 --- a/mayan/apps/sources/tests/test_views.py +++ b/mayan/apps/sources/tests/test_views.py @@ -18,6 +18,8 @@ from documents.tests import ( TEST_DOCUMENT_TYPE ) from documents.tests.test_views import GenericDocumentViewTestCase +from organizations.models import Organization +from organizations.utils import create_default_organization from user_management.tests import ( TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME, TEST_USER_PASSWORD, TEST_USER_USERNAME @@ -30,15 +32,15 @@ from ..permissions import ( permission_sources_setup_view, permission_staging_file_delete ) -TEST_SOURCE_LABEL = 'test source' -TEST_SOURCE_UNCOMPRESS_N = 'n' -TEST_STAGING_PREVIEW_WIDTH = 640 +from .literals import ( + TEST_SOURCE_LABEL, TEST_SOURCE_UNCOMPRESS_N, TEST_STAGING_PREVIEW_WIDTH +) class DocumentUploadTestCase(GenericDocumentViewTestCase): def setUp(self): super(DocumentUploadTestCase, self).setUp() - self.source = WebFormSource.objects.create( + self.source = WebFormSource.on_organization.create( enabled=True, label=TEST_SOURCE_LABEL, uncompress=TEST_SOURCE_UNCOMPRESS_N ) @@ -61,7 +63,7 @@ class DocumentUploadTestCase(GenericDocumentViewTestCase): ) self.assertEqual(response.status_code, 403) - self.assertEqual(Document.objects.count(), 0) + self.assertEqual(Document.on_organization.count(), 0) def test_upload_wizard_with_permission(self): self.client.login( @@ -83,7 +85,7 @@ class DocumentUploadTestCase(GenericDocumentViewTestCase): ) self.assertTrue(b'queued' in response.content) - self.assertEqual(Document.objects.count(), 1) + self.assertEqual(Document.on_organization.count(), 1) def test_upload_wizard_with_document_type_access(self): """ @@ -97,7 +99,7 @@ class DocumentUploadTestCase(GenericDocumentViewTestCase): # Create an access control entry giving the role the document # create permission for the selected document type. - acl = AccessControlList.objects.create( + acl = AccessControlList.on_organization.create( content_object=self.document_type, role=self.role ) acl.permissions.add(permission_document_create.stored_permission) @@ -113,13 +115,14 @@ class DocumentUploadTestCase(GenericDocumentViewTestCase): ) self.assertTrue(b'queued' in response.content) - self.assertEqual(Document.objects.count(), 1) + self.assertEqual(Document.on_organization.count(), 1) @override_settings(OCR_AUTO_OCR=False) class DocumentUploadIssueTestCase(TestCase): def setUp(self): - self.document_type = DocumentType.objects.create( + create_default_organization() + self.document_type = DocumentType.on_organization.create( label=TEST_DOCUMENT_TYPE ) @@ -131,6 +134,8 @@ class DocumentUploadIssueTestCase(TestCase): def tearDown(self): self.document_type.delete() + Organization.objects.all().delete() + Organization.objects.clear_cache() def test_issue_25(self): # Login the admin user @@ -146,7 +151,7 @@ class DocumentUploadIssueTestCase(TestCase): 'sources:setup_source_create', args=(SOURCE_CHOICE_WEB_FORM,) ), {'label': 'test', 'uncompress': 'n', 'enabled': True} ) - self.assertEqual(WebFormSource.objects.count(), 1) + self.assertEqual(WebFormSource.on_organization.count(), 1) # Upload the test document with open(TEST_SMALL_DOCUMENT_PATH) as file_descriptor: @@ -157,9 +162,9 @@ class DocumentUploadIssueTestCase(TestCase): 'document_type_id': self.document_type.pk } ) - self.assertEqual(Document.objects.count(), 1) + self.assertEqual(Document.on_organization.count(), 1) - document = Document.objects.first() + document = Document.on_organization.first() # Test for issue 25 during creation # ** description fields was removed from upload from ** self.assertEqual(document.description, '') @@ -178,7 +183,7 @@ class DocumentUploadIssueTestCase(TestCase): } ) # Fetch document again and test description - document = Document.objects.first() + document = Document.on_organization.first() self.assertEqual(document.description, TEST_DOCUMENT_DESCRIPTION) @@ -240,7 +245,7 @@ class StagingFolderTestCase(GenericViewTestCase): username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD ) - staging_folder = StagingFolderSource.objects.create( + staging_folder = StagingFolderSource.on_organization.create( label=TEST_SOURCE_LABEL, folder_path=self.temporary_directory, preview_width=TEST_STAGING_PREVIEW_WIDTH, @@ -269,7 +274,7 @@ class StagingFolderTestCase(GenericViewTestCase): permission_staging_file_delete.stored_permission ) - staging_folder = StagingFolderSource.objects.create( + staging_folder = StagingFolderSource.on_organization.create( label=TEST_SOURCE_LABEL, folder_path=self.temporary_directory, preview_width=TEST_STAGING_PREVIEW_WIDTH, @@ -292,7 +297,7 @@ class StagingFolderTestCase(GenericViewTestCase): class SourcesTestCase(GenericDocumentViewTestCase): def create_web_source(self): - self.source = WebFormSource.objects.create( + self.source = WebFormSource.on_organization.create( enabled=True, label=TEST_SOURCE_LABEL, uncompress=TEST_SOURCE_UNCOMPRESS_N ) @@ -343,7 +348,7 @@ class SourcesTestCase(GenericDocumentViewTestCase): } ) - webform_source = WebFormSource.objects.first() + webform_source = WebFormSource.on_organization.first() self.assertEqual(webform_source.label, TEST_SOURCE_LABEL) self.assertEqual(webform_source.uncompress, TEST_SOURCE_UNCOMPRESS_N) @@ -368,7 +373,7 @@ class SourcesTestCase(GenericDocumentViewTestCase): ) self.assertEqual(response.status_code, 403) - self.assertEqual(WebFormSource.objects.count(), 0) + self.assertEqual(WebFormSource.on_organization.count(), 0) def test_source_delete_view_with_permission(self): self.create_web_source() @@ -390,7 +395,7 @@ class SourcesTestCase(GenericDocumentViewTestCase): ) self.assertEqual(response.status_code, 200) - self.assertEqual(WebFormSource.objects.count(), 0) + self.assertEqual(WebFormSource.on_organization.count(), 0) def test_source_delete_view_no_permission(self): self.create_web_source() @@ -409,4 +414,4 @@ class SourcesTestCase(GenericDocumentViewTestCase): ) self.assertEqual(response.status_code, 403) - self.assertEqual(WebFormSource.objects.count(), 1) + self.assertEqual(WebFormSource.on_organization.count(), 1) diff --git a/mayan/apps/sources/views.py b/mayan/apps/sources/views.py index 288cfcd40d..f5d9d3f461 100644 --- a/mayan/apps/sources/views.py +++ b/mayan/apps/sources/views.py @@ -23,6 +23,7 @@ from documents.permissions import ( from documents.tasks import task_upload_new_version from metadata.api import decode_metadata_from_url from navigation import Link +from organizations.models import Organization from permissions import Permission from .forms import ( @@ -49,14 +50,6 @@ from .utils import get_class, get_form_class, get_upload_form_class class SourceLogListView(SingleObjectListView): view_permission = permission_sources_setup_view - def get_source(self): - return get_object_or_404( - Source.objects.select_subclasses(), pk=self.kwargs['pk'] - ) - - def get_queryset(self): - return self.get_source().logs.all() - def get_extra_context(self): return { 'hide_object': True, @@ -64,6 +57,14 @@ class SourceLogListView(SingleObjectListView): 'title': _('Log entries for source: %s') % self.get_source(), } + def get_queryset(self): + return self.get_source().logs.all() + + def get_source(self): + return get_object_or_404( + Source.on_organization.select_subclasses(), pk=self.kwargs['pk'] + ) + class UploadBaseView(MultiFormView): template_name = 'appearance/generic_form.html' @@ -91,13 +92,13 @@ class UploadBaseView(MultiFormView): def get_active_tab_links(document=None): tab_links = [] - web_forms = WebFormSource.objects.filter(enabled=True) + web_forms = WebFormSource.on_organization.filter(enabled=True) for web_form in web_forms: tab_links.append( UploadBaseView.get_tab_link_for_source(web_form, document) ) - staging_folders = StagingFolderSource.objects.filter(enabled=True) + staging_folders = StagingFolderSource.on_organization.filter(enabled=True) for staging_folder in staging_folders: tab_links.append( UploadBaseView.get_tab_link_for_source( @@ -114,15 +115,15 @@ class UploadBaseView(MultiFormView): def dispatch(self, request, *args, **kwargs): if 'source_id' in kwargs: self.source = get_object_or_404( - Source.objects.filter(enabled=True).select_subclasses(), + Source.on_organization.filter(enabled=True).select_subclasses(), pk=kwargs['source_id'] ) else: - self.source = InteractiveSource.objects.filter( + self.source = InteractiveSource.on_organization.filter( enabled=True ).select_subclasses().first() - if not InteractiveSource.objects.filter(enabled=True).exists(): + if not InteractiveSource.on_organization.filter(enabled=True).exists(): messages.error( request, _( @@ -450,9 +451,6 @@ class SetupSourceCreateView(SingleObjectCreateView): post_action_redirect = reverse_lazy('sources:setup_source_list') view_permission = permission_sources_setup_create - def get_form_class(self): - return get_form_class(self.kwargs['source_type']) - def get_extra_context(self): return { 'object': self.kwargs['source_type'], @@ -461,48 +459,54 @@ class SetupSourceCreateView(SingleObjectCreateView): ) % get_class(self.kwargs['source_type']).class_fullname(), } + def get_form_class(self): + return get_form_class(self.kwargs['source_type']) + + def get_instance_extra_data(self): + return {'organization': Organization.objects.get_current()} + class SetupSourceDeleteView(SingleObjectDeleteView): post_action_redirect = reverse_lazy('sources:setup_source_list') view_permission = permission_sources_setup_delete - def get_object(self): - return get_object_or_404( - Source.objects.select_subclasses(), pk=self.kwargs['pk'] - ) - - def get_form_class(self): - return get_form_class(self.get_object().source_type) - def get_extra_context(self): return { 'object': self.get_object(), 'title': _('Delete the source: %s?') % self.get_object(), } + def get_form_class(self): + return get_form_class(self.get_object().source_type) + + def get_object(self): + return get_object_or_404( + Source.on_organization.select_subclasses(), pk=self.kwargs['pk'] + ) + class SetupSourceEditView(SingleObjectEditView): post_action_redirect = reverse_lazy('sources:setup_source_list') view_permission = permission_sources_setup_edit - def get_object(self): - return get_object_or_404( - Source.objects.select_subclasses(), pk=self.kwargs['pk'] - ) - - def get_form_class(self): - return get_form_class(self.get_object().source_type) - def get_extra_context(self): return { 'object': self.get_object(), 'title': _('Edit source: %s') % self.get_object(), } + def get_form_class(self): + return get_form_class(self.get_object().source_type) + + def get_object(self): + return get_object_or_404( + Source.on_organization.select_subclasses(), pk=self.kwargs['pk'] + ) + class SetupSourceListView(SingleObjectListView): + queryset = Source.on_organization.select_subclasses() view_permission = permission_sources_setup_view - queryset = Source.objects.select_subclasses() extra_context = { 'extra_columns': ( diff --git a/mayan/apps/sources/wizards.py b/mayan/apps/sources/wizards.py index 9f790566f4..f6286ac5b0 100644 --- a/mayan/apps/sources/wizards.py +++ b/mayan/apps/sources/wizards.py @@ -42,7 +42,7 @@ class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView): template_name = 'appearance/generic_wizard.html' def dispatch(self, request, *args, **kwargs): - if not InteractiveSource.objects.filter(enabled=True).exists(): + if not InteractiveSource.on_organization.filter(enabled=True).exists(): messages.error( request, _(