Update source app

Sort arguments.

Add keyword arguments.

Update views regexes.

Update URL parameters to use the "_id" form.

Move setting literals to the literals.py module.

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2019-01-22 04:27:00 -04:00
parent c7bd2ee8f2
commit 108c54630f
12 changed files with 429 additions and 423 deletions
+33 -33
View File
@@ -22,13 +22,13 @@ from .handlers import (
handler_create_default_document_source, handler_initialize_periodic_tasks
)
from .links import (
link_document_create_multiple, link_setup_source_check_now,
link_setup_source_create_imap_email, link_setup_source_create_pop3_email,
link_setup_source_create_sane_scanner,
link_setup_source_create_staging_folder,
link_setup_source_create_watch_folder, link_setup_source_create_webform,
link_setup_source_delete, link_setup_source_edit, link_setup_source_logs,
link_setup_sources, link_staging_file_delete, link_upload_version
link_document_create_multiple, link_source_check_now,
link_source_create_imap_email, link_source_create_pop3_email,
link_source_create_sane_scanner,
link_source_create_staging_folder,
link_source_create_watch_folder, link_source_create_webform,
link_source_delete, link_source_edit, link_source_logs,
link_source_list, link_staging_file_delete, link_upload_version
)
from .queues import * # NOQA
from .widgets import StagingFileThumbnailWidget
@@ -45,24 +45,24 @@ class SourcesApp(MayanAppConfig):
def ready(self):
super(SourcesApp, self).ready()
POP3Email = self.get_model('POP3Email')
IMAPEmail = self.get_model('IMAPEmail')
Source = self.get_model('Source')
SourceLog = self.get_model('SourceLog')
SaneScanner = self.get_model('SaneScanner')
StagingFolderSource = self.get_model('StagingFolderSource')
WatchFolderSource = self.get_model('WatchFolderSource')
WebFormSource = self.get_model('WebFormSource')
POP3Email = self.get_model(model_name='POP3Email')
IMAPEmail = self.get_model(model_name='IMAPEmail')
Source = self.get_model(model_name='Source')
SourceLog = self.get_model(model_name='SourceLog')
SaneScanner = self.get_model(model_name='SaneScanner')
StagingFolderSource = self.get_model(model_name='StagingFolderSource')
WatchFolderSource = self.get_model(model_name='WatchFolderSource')
WebFormSource = self.get_model(model_name='WebFormSource')
MissingItem(
label=_('Create a document source'),
condition=lambda: not Source.objects.exists(),
description=_(
'Document sources are the way in which new documents are '
'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(),
view='sources:setup_source_list'
label=_('Create a document source'),
view='sources:source_list'
)
SourceColumn(
@@ -83,11 +83,11 @@ class SourcesApp(MayanAppConfig):
)
html_widget = StagingFileThumbnailWidget()
SourceColumn(
source=StagingFile,
label=_('Thumbnail'),
func=lambda context: html_widget.render(
instance=context['object'],
)
),
label=_('Thumbnail'),
source=StagingFile
)
SourceColumn(
@@ -134,7 +134,7 @@ class SourcesApp(MayanAppConfig):
menu_list_facet.bind_links(
links=(
link_setup_source_logs, link_transformation_list,
link_source_logs, link_transformation_list,
), sources=(
POP3Email, IMAPEmail, SaneScanner, StagingFolderSource,
WatchFolderSource, WebFormSource
@@ -143,7 +143,7 @@ class SourcesApp(MayanAppConfig):
menu_object.bind_links(
links=(
link_setup_source_edit, link_setup_source_delete,
link_source_edit, link_source_delete,
), sources=(
POP3Email, IMAPEmail, SaneScanner, StagingFolderSource,
WatchFolderSource, WebFormSource
@@ -153,24 +153,24 @@ class SourcesApp(MayanAppConfig):
links=(link_staging_file_delete,), sources=(StagingFile,)
)
menu_object.bind_links(
links=(link_setup_source_check_now,),
links=(link_source_check_now,),
sources=(IMAPEmail, POP3Email, WatchFolderSource,)
)
menu_secondary.bind_links(
links=(
link_setup_sources, link_setup_source_create_webform,
link_setup_source_create_sane_scanner,
link_setup_source_create_staging_folder,
link_setup_source_create_pop3_email,
link_setup_source_create_imap_email,
link_setup_source_create_watch_folder
link_source_list, link_source_create_webform,
link_source_create_sane_scanner,
link_source_create_staging_folder,
link_source_create_pop3_email,
link_source_create_imap_email,
link_source_create_watch_folder
), sources=(
POP3Email, IMAPEmail, StagingFolderSource, WatchFolderSource,
WebFormSource, 'sources:setup_source_list',
'sources:setup_source_create'
WebFormSource, 'sources:source_list',
'sources:source_create'
)
)
menu_setup.bind_links(links=(link_setup_sources,))
menu_setup.bind_links(links=(link_source_list,))
menu_sidebar.bind_links(
links=(link_upload_version,),
sources=(
+1 -1
View File
@@ -6,8 +6,8 @@ icon_document_create_multiple = Icon(
driver_name='fontawesome', symbol='upload'
)
icon_log = Icon(driver_name='fontawesome', symbol='exclamation-triangle')
icon_setup_sources = Icon(driver_name='fontawesome', symbol='upload')
icon_source_create = Icon(driver_name='fontawesome', symbol='plus')
icon_source_list = Icon(driver_name='fontawesome', symbol='upload')
icon_staging_folder = Icon(driver_name='fontawesome', symbol='folder')
icon_upload_view_link = Icon(driver_name='fontawesome', symbol='upload')
icon_wizard_submit = Icon(driver_name='fontawesome', symbol='arrow-right')
+65 -63
View File
@@ -9,7 +9,7 @@ from mayan.apps.documents.permissions import (
from mayan.apps.navigation import Link
from .icons import (
icon_document_create_multiple, icon_log, icon_setup_sources,
icon_document_create_multiple, icon_log, icon_source_list,
icon_source_create
)
from .literals import (
@@ -18,8 +18,8 @@ from .literals import (
SOURCE_CHOICE_WEB_FORM
)
from .permissions import (
permission_sources_setup_create, permission_sources_setup_delete,
permission_sources_setup_edit, permission_sources_setup_view
permission_sources_create, permission_sources_delete,
permission_sources_edit, permission_sources_view
)
@@ -31,13 +31,10 @@ def condition_check_document_creation_acls(context):
app_label='documents', model_name='DocumentType'
)
queryset = AccessControlList.objects.filter_by_access(
permission=permission_document_create, user=context['user'],
queryset=DocumentType.objects.all()
)
if queryset:
return True
return AccessControlList.objects.restrict_queryset(
permission=permission_document_create,
queryset=DocumentType.objects.all(), user=context['user']
).exists()
def document_new_version_not_blocked(context):
@@ -53,72 +50,77 @@ link_document_create_multiple = Link(
icon_class=icon_document_create_multiple, text=_('New document'),
view='sources:document_create_multiple'
)
link_setup_sources = Link(
icon_class=icon_setup_sources,
permissions=(permission_sources_setup_view,), text=_('Sources'),
view='sources:setup_source_list'
link_source_check_now = Link(
kwargs={'source_id': 'resolved_object.pk'},
permissions=(permission_sources_edit,), text=_('Check now'),
view='sources:source_check'
)
link_setup_source_create_imap_email = Link(
args='"%s"' % SOURCE_CHOICE_EMAIL_IMAP, icon_class=icon_source_create,
permissions=(permission_sources_setup_create,),
text=_('Add new IMAP email'), view='sources:setup_source_create',
link_source_create_imap_email = Link(
icon_class=icon_source_create,
kwargs={'source_type': '"%s"' % SOURCE_CHOICE_EMAIL_IMAP},
permissions=(permission_sources_create,),
text=_('Add new IMAP email'), view='sources:source_create'
)
link_setup_source_create_pop3_email = Link(
args='"%s"' % SOURCE_CHOICE_EMAIL_POP3, icon_class=icon_source_create,
permissions=(permission_sources_setup_create,),
text=_('Add new POP3 email'), view='sources:setup_source_create',
link_source_create_pop3_email = Link(
icon_class=icon_source_create,
kwargs={'source_type': '"%s"' % SOURCE_CHOICE_EMAIL_POP3},
permissions=(permission_sources_create,),
text=_('Add new POP3 email'), view='sources:source_create'
)
link_setup_source_create_staging_folder = Link(
args='"%s"' % SOURCE_CHOICE_STAGING, icon_class=icon_source_create,
permissions=(permission_sources_setup_create,),
text=_('Add new staging folder'), view='sources:setup_source_create',
link_source_create_staging_folder = Link(
icon_class=icon_source_create,
kwargs={'source_type': '"%s"' % SOURCE_CHOICE_STAGING},
permissions=(permission_sources_create,),
text=_('Add new staging folder'), view='sources:source_create'
)
link_setup_source_create_watch_folder = Link(
args='"%s"' % SOURCE_CHOICE_WATCH, icon_class=icon_source_create,
permissions=(permission_sources_setup_create,),
text=_('Add new watch folder'), view='sources:setup_source_create',
link_source_create_watch_folder = Link(
icon_class=icon_source_create,
kwargs={'source_type': '"%s"' % SOURCE_CHOICE_WATCH},
permissions=(permission_sources_create,),
text=_('Add new watch folder'), view='sources:source_create'
)
link_setup_source_create_webform = Link(
args='"%s"' % SOURCE_CHOICE_WEB_FORM, icon_class=icon_source_create,
permissions=(permission_sources_setup_create,),
text=_('Add new webform source'), view='sources:setup_source_create',
link_source_create_webform = Link(
icon_class=icon_source_create,
kwargs={'source_type': '"%s"' % SOURCE_CHOICE_WEB_FORM},
permissions=(permission_sources_create,),
text=_('Add new webform source'), view='sources:source_create'
)
link_setup_source_create_sane_scanner = Link(
args='"%s"' % SOURCE_CHOICE_SANE_SCANNER, icon_class=icon_source_create,
permissions=(permission_sources_setup_create,),
text=_('Add new SANE scanner'), view='sources:setup_source_create',
link_source_create_sane_scanner = Link(
icon_class=icon_source_create,
kwargs={'source_type': '"%s"' % SOURCE_CHOICE_SANE_SCANNER},
permissions=(permission_sources_create,),
text=_('Add new SANE scanner'), view='sources:source_create'
)
link_setup_source_delete = Link(
args=('resolved_object.pk',),
permissions=(permission_sources_setup_delete,), tags='dangerous',
text=_('Delete'), view='sources:setup_source_delete',
link_source_delete = Link(
kwargs={'source_id': 'resolved_object.pk'},
permissions=(permission_sources_delete,), tags='dangerous',
text=_('Delete'), view='sources:source_delete'
)
link_setup_source_edit = Link(
args=('resolved_object.pk',),
permissions=(permission_sources_setup_edit,), text=_('Edit'),
view='sources:setup_source_edit',
link_source_edit = Link(
kwargs={'source_id': 'resolved_object.pk'},
permissions=(permission_sources_edit,), text=_('Edit'),
view='sources:source_edit'
)
link_source_list = Link(
permissions=(permission_sources_setup_view,), text=_('Document sources'),
view='sources:setup_web_form_list'
icon_class=icon_source_list,
permissions=(permission_sources_view,), text=_('Sources'),
view='sources:source_list'
)
link_source_logs = Link(
icon_class=icon_log, kwargs={'source_id': 'resolved_object.pk'},
permissions=(permission_sources_view,), text=_('Logs'),
view='sources:source_logs'
)
link_staging_file_delete = Link(
args=('source.pk', 'object.encoded_filename',), keep_query=True,
permissions=(permission_document_new_version, permission_document_create),
tags='dangerous', text=_('Delete'), view='sources:staging_file_delete',
keep_query=True, kwargs={
'staging_file_pk': 'source.pk',
'encoded_filename': 'object.encoded_filename'
}, permissions=(permission_document_new_version, permission_document_create),
tags='dangerous', text=_('Delete'), view='sources:staging_file_delete'
)
link_upload_version = Link(
args='resolved_object.pk', condition=document_new_version_not_blocked,
condition=document_new_version_not_blocked,
kwargs={'document_pk': 'resolved_object.pk'},
permissions=(permission_document_new_version,),
text=_('Upload new version'), view='sources:upload_version',
)
link_setup_source_logs = Link(
args=('resolved_object.pk',), icon_class=icon_log,
permissions=(permission_sources_setup_view,), text=_('Logs'),
view='sources:setup_source_logs',
)
link_setup_source_check_now = Link(
args=('resolved_object.pk',),
permissions=(permission_sources_setup_view,), text=_('Check now'),
view='sources:setup_source_check',
text=_('Upload new version'), view='sources:upload_version'
)
+7
View File
@@ -1,7 +1,9 @@
from __future__ import unicode_literals
import os
import platform
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
if platform.system() == 'OpenBSD':
@@ -16,6 +18,11 @@ DEFAULT_POP3_TIMEOUT = 60
DEFAULT_SOURCE_LOCK_EXPIRE = 600
DEFAULT_SOURCE_TASK_RETRY_DELAY = 10
DEFAULT_STAGING_FILE_CACHE_STORAGE_BACKEND = 'SOURCES_STAGING_FILE_CACHE_STORAGE_BACKEND'
DEFAULT_STAGING_FILE_CACHE_STORAGE_BACKEND_ARGUMENTS = {
'location': os.path.join(settings.MEDIA_ROOT, 'staging_file_cache')
}
SCANNER_SOURCE_FLATBED = 'flatbed'
SCANNER_SOURCE_ADF = 'Automatic Document Feeder'
+9 -9
View File
@@ -6,18 +6,18 @@ from mayan.apps.permissions import PermissionNamespace
namespace = PermissionNamespace(label=_('Sources setup'), name='source_setup')
permission_sources_setup_create = namespace.add_permission(
name='sources_setup_create', label=_('Create new document sources')
permission_sources_create = namespace.add_permission(
label=_('Create new document sources'), name='sources_setup_create'
)
permission_sources_setup_delete = namespace.add_permission(
name='sources_setup_delete', label=_('Delete document sources')
permission_sources_delete = namespace.add_permission(
label=_('Delete document sources'), name='sources_setup_delete'
)
permission_sources_setup_edit = namespace.add_permission(
name='sources_setup_edit', label=_('Edit document sources')
permission_sources_edit = namespace.add_permission(
label=_('Edit document sources'), name='sources_setup_edit'
)
permission_sources_setup_view = namespace.add_permission(
name='sources_setup_view', label=_('View existing document sources')
permission_sources_view = namespace.add_permission(
label=_('View existing document sources'), name='sources_setup_view'
)
permission_staging_file_delete = namespace.add_permission(
name='sources_staging_file_delete', label=_('Delete staging files')
label=_('Delete staging files'), name='sources_staging_file_delete'
)
+11 -11
View File
@@ -5,28 +5,28 @@ from django.utils.translation import ugettext_lazy as _
from mayan.apps.task_manager.classes import CeleryQueue
queue_sources = CeleryQueue(
name='sources', label=_('Sources')
label=_('Sources'), name='sources'
)
queue_sources_periodic = CeleryQueue(
name='sources_periodic', label=_('Sources periodic'), transient=True
label=_('Sources periodic'), name='sources_periodic', transient=True
)
queue_sources_fast = CeleryQueue(
name='sources_fast', label=_('Sources fast'), transient=True
label=_('Sources fast'), name='sources_fast', transient=True
)
queue_sources_fast.add_task_type(
name='mayan.apps.sources.tasks.task_generate_staging_file_image',
label=_('Generate staging file image')
label=_('Generate staging file image'),
name='mayan.apps.sources.tasks.task_generate_staging_file_image'
)
queue_sources_periodic.add_task_type(
name='mayan.apps.sources.tasks.task_check_interval_source',
label=_('Check interval source')
label=_('Check interval source'),
name='mayan.apps.sources.tasks.task_check_interval_source'
)
queue_sources.add_task_type(
name='mayan.apps.sources.tasks.task_source_handle_upload',
label=_('Handle upload')
label=_('Handle upload'),
name='mayan.apps.sources.tasks.task_source_handle_upload'
)
queue_sources.add_task_type(
name='mayan.apps.sources.tasks.task_upload_document',
label=_('Upload document')
label=_('Upload document'),
name='mayan.apps.sources.tasks.task_upload_document'
)
+7 -9
View File
@@ -1,15 +1,15 @@
from __future__ import unicode_literals
import os
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from mayan.apps.smart_settings import Namespace
from .literals import DEFAULT_SCANIMAGE_PATH
from .literals import (
DEFAULT_SCANIMAGE_PATH, DEFAULT_STAGING_FILE_CACHE_STORAGE_BACKEND,
DEFAULT_STAGING_FILE_CACHE_STORAGE_BACKEND_ARGUMENTS
)
namespace = Namespace(name='sources', label=_('Sources'))
namespace = Namespace(label=_('Sources'), name='sources')
setting_scanimage_path = namespace.add_setting(
global_name='SOURCES_SCANIMAGE_PATH', default=DEFAULT_SCANIMAGE_PATH,
@@ -19,7 +19,7 @@ setting_scanimage_path = namespace.add_setting(
is_path=True
)
setting_staging_file_image_cache_storage = namespace.add_setting(
global_name='SOURCES_STAGING_FILE_CACHE_STORAGE_BACKEND',
global_name=DEFAULT_STAGING_FILE_CACHE_STORAGE_BACKEND,
default='django.core.files.storage.FileSystemStorage', help_text=_(
'Path to the Storage subclass to use when storing the cached '
'staging_file image files.'
@@ -27,9 +27,7 @@ setting_staging_file_image_cache_storage = namespace.add_setting(
)
setting_staging_file_image_cache_storage_arguments = namespace.add_setting(
global_name='SOURCES_STAGING_FILE_CACHE_STORAGE_BACKEND_ARGUMENTS',
default={
'location': os.path.join(settings.MEDIA_ROOT, 'staging_file_cache')
}, help_text=_(
default=DEFAULT_STAGING_FILE_CACHE_STORAGE_BACKEND_ARGUMENTS, help_text=_(
'Arguments to pass to the SOURCES_STAGING_FILE_CACHE_STORAGE_BACKEND.'
)
)
+32 -28
View File
@@ -18,8 +18,8 @@ from ..links import link_upload_version
from ..literals import SOURCE_CHOICE_WEB_FORM
from ..models import StagingFolderSource, WebFormSource
from ..permissions import (
permission_sources_setup_create, permission_sources_setup_delete,
permission_sources_setup_view, permission_staging_file_delete
permission_sources_create, permission_sources_delete,
permission_sources_view, permission_staging_file_delete
)
from .literals import (
@@ -33,7 +33,6 @@ class DocumentUploadTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(DocumentUploadTestCase, self).setUp()
self._create_source()
self.login_user()
def _create_source(self):
self.source = WebFormSource.objects.create(
@@ -55,7 +54,7 @@ class DocumentUploadTestCase(GenericDocumentViewTestCase):
def test_upload_wizard_without_permission(self):
response = self._request_upload_wizard_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Document.objects.count(), 0)
def test_upload_wizard_with_permission(self):
@@ -112,12 +111,12 @@ class DocumentUploadIssueTestCase(GenericDocumentViewTestCase):
auto_upload_document = False
def test_issue_25(self):
self.login_admin_user()
self.login_superuser()
# Create new webform source
self.post(
viewname='sources:setup_source_create',
args=(SOURCE_CHOICE_WEB_FORM,),
viewname='sources:source_create',
kwargs={'source_type': SOURCE_CHOICE_WEB_FORM},
data={'label': 'test', 'uncompress': 'n', 'enabled': True}
)
self.assertEqual(WebFormSource.objects.count(), 1)
@@ -145,7 +144,8 @@ class DocumentUploadIssueTestCase(GenericDocumentViewTestCase):
# Test for issue 25 during editing
self.post(
viewname='documents:document_edit', args=(document.pk,), data={
viewname='documents:document_edit',
kargs={'document_id': document.pk}, data={
'description': TEST_DOCUMENT_DESCRIPTION,
'language': document.language, 'label': document.label
}
@@ -171,7 +171,8 @@ class NewDocumentVersionViewTestCase(GenericDocumentViewTestCase):
NewVersionBlock.objects.block(self.document)
response = self.post(
viewname='sources:upload_version', args=(self.document.pk,),
viewname='sources:upload_version',
kwargs={'document_id': self.document.pk},
follow=True
)
@@ -181,7 +182,8 @@ class NewDocumentVersionViewTestCase(GenericDocumentViewTestCase):
)
response = self.get(
'documents:document_version_list', args=(self.document.pk,),
viewname='documents:document_version_list',
kwargs={'document_id': self.document.pk},
follow=True
)
@@ -204,13 +206,6 @@ class StagingFolderViewTestCase(GenericViewTestCase):
fs_cleanup(self.temporary_directory)
super(StagingFolderViewTestCase, self).tearDown()
def _request_staging_file_delete_view(self, staging_file):
return self.post(
viewname='sources:staging_file_delete', args=(
self.staging_folder.pk, staging_file.encoded_filename
)
)
def _create_staging_folder(self):
self.staging_folder = StagingFolderSource.objects.create(
label=TEST_SOURCE_LABEL,
@@ -219,6 +214,15 @@ class StagingFolderViewTestCase(GenericViewTestCase):
uncompress=TEST_SOURCE_UNCOMPRESS_N,
)
def _request_staging_file_delete_view(self, staging_file):
return self.post(
viewname='sources:staging_file_delete',
kwargs={
'staging_folder_id': self.staging_folder.pk,
'encoded_filename': staging_file.encoded_filename
},
)
def test_staging_folder_delete_no_permission(self):
self._create_staging_folder()
@@ -259,7 +263,7 @@ class SourcesViewsTestCase(GenericViewTestCase):
)
def _request_setup_source_list_view(self):
return self.get(viewname='sources:setup_source_list')
return self.get(viewname='sources:source_list')
def test_source_list_view_no_permission(self):
self._create_web_source()
@@ -270,7 +274,7 @@ class SourcesViewsTestCase(GenericViewTestCase):
def test_source_list_view_with_permission(self):
self._create_web_source()
self.grant_permission(permission=permission_sources_setup_view)
self.grant_permission(permission=permission_sources_view)
response = self._request_setup_source_list_view()
self.assertContains(
@@ -280,14 +284,14 @@ class SourcesViewsTestCase(GenericViewTestCase):
def _request_setup_source_create_view(self):
return self.post(
args=(SOURCE_CHOICE_WEB_FORM,),
viewname='sources:setup_source_create', data={
viewname='sources:source_create', data={
'enabled': True, 'label': TEST_SOURCE_LABEL,
'uncompress': TEST_SOURCE_UNCOMPRESS_N
}
)
def test_source_create_view_no_permission(self):
self.grant_permission(permission=permission_sources_setup_view)
self.grant_permission(permission=permission_sources_view)
response = self._request_setup_source_create_view()
self.assertEqual(response.status_code, 403)
@@ -295,8 +299,8 @@ class SourcesViewsTestCase(GenericViewTestCase):
self.assertEqual(WebFormSource.objects.count(), 0)
def test_source_create_view_with_permission(self):
self.grant_permission(permission=permission_sources_setup_create)
self.grant_permission(permission=permission_sources_setup_view)
self.grant_permission(permission=permission_sources_create)
self.grant_permission(permission=permission_sources_view)
response = self._request_setup_source_create_view()
self.assertEquals(response.status_code, 302)
@@ -307,15 +311,15 @@ class SourcesViewsTestCase(GenericViewTestCase):
def _request_setup_source_delete_view(self):
return self.post(
args=(self.source.pk,),
viewname='sources:setup_source_delete'
viewname='sources:source_delete',
kwargs={'source_id': self.source.pk}
)
def test_source_delete_view_with_permission(self):
self._create_web_source()
self.grant_permission(permission=permission_sources_setup_delete)
self.grant_permission(permission=permission_sources_setup_view)
self.grant_permission(permission=permission_sources_delete)
self.grant_permission(permission=permission_sources_view)
response = self._request_setup_source_delete_view()
self.assertEqual(response.status_code, 302)
@@ -324,7 +328,7 @@ class SourcesViewsTestCase(GenericViewTestCase):
def test_source_delete_view_no_permission(self):
self._create_web_source()
self.grant_permission(permission=permission_sources_setup_view)
self.grant_permission(permission=permission_sources_view)
response = self._request_setup_source_delete_view()
self.assertEqual(response.status_code, 403)
+45 -51
View File
@@ -7,87 +7,81 @@ from .api_views import (
APIStagingSourceListView, APIStagingSourceView
)
from .views import (
SetupSourceCheckView, SetupSourceCreateView, SetupSourceDeleteView,
SetupSourceEditView, SetupSourceListView, SourceLogListView,
SourceCheckView, SourceCreateView, SourceDeleteView,
SourceEditView, SourceListView, SourceLogView,
StagingFileDeleteView, UploadInteractiveVersionView, UploadInteractiveView
)
from .wizards import DocumentCreateWizard
urlpatterns = [
url(
r'^staging_file/(?P<pk>\d+)/(?P<encoded_filename>.+)/delete/$',
StagingFileDeleteView.as_view(), name='staging_file_delete'
regex=r'^sources/$', name='source_list',
view=SourceListView.as_view()
),
url(
regex=r'^sources/(?P<source_type>\w+)/create/$',
name='source_create', view=SourceCreateView.as_view()
),
url(
regex=r'^sources/(?P<source_id>\d+)/check/$', name='source_check',
view=SourceCheckView.as_view()
),
url(
regex=r'^sources/(?P<source_id>\d+)/delete/$',
name='source_delete', view=SourceDeleteView.as_view()
),
url(
regex=r'^sources/(?P<source_id>\d+)/edit/$', name='source_edit',
view=SourceEditView.as_view()
),
url(
regex=r'^sources/(?P<source_id>\d+)/logs/$', name='source_logs',
view=SourceLogView.as_view()
),
url(
r'^upload/document/new/interactive/(?P<source_id>\d+)/$',
UploadInteractiveView.as_view(), name='upload_interactive'
regex=r'^sources/(?P<source_id>\d+)/document/upload/$',
name='upload_interactive', view=UploadInteractiveView.as_view()
),
url(
r'^upload/document/new/interactive/$', UploadInteractiveView.as_view(),
name='upload_interactive'
regex=r'^sources/document/upload/$', name='upload_interactive',
view=UploadInteractiveView.as_view()
),
url(
r'^upload/document/(?P<document_pk>\d+)/version/interactive/(?P<source_id>\d+)/$',
UploadInteractiveVersionView.as_view(), name='upload_version'
regex=r'^sources/(?P<source_id>\d+)/documents/(?P<document_id>\d+)/versions/upload/$',
name='upload_version', view=UploadInteractiveVersionView.as_view()
),
url(
r'^upload/document/(?P<document_pk>\d+)/version/interactive/$',
UploadInteractiveVersionView.as_view(), name='upload_version'
),
# Setup views
url(
r'^setup/list/$', SetupSourceListView.as_view(),
name='setup_source_list'
regex=r'^sources/documents/(?P<document_id>\d+)/version/upload/$',
name='upload_version', view=UploadInteractiveVersionView.as_view()
),
url(
r'^setup/(?P<pk>\d+)/edit/$', SetupSourceEditView.as_view(),
name='setup_source_edit'
regex=r'^sources/wizard/$', name='document_create_multiple',
view=DocumentCreateWizard.as_view()
),
url(
r'^setup/(?P<pk>\d+)/logs/$', SourceLogListView.as_view(),
name='setup_source_logs'
),
url(
r'^setup/(?P<pk>\d+)/delete/$', SetupSourceDeleteView.as_view(),
name='setup_source_delete'
),
url(
r'^setup/(?P<source_type>\w+)/create/$',
SetupSourceCreateView.as_view(), name='setup_source_create'
),
url(
r'^setup/(?P<pk>\d+)/check/$', SetupSourceCheckView.as_view(),
name='setup_source_check'
),
# Document create views
url(
r'^create/from/local/multiple/$', DocumentCreateWizard.as_view(),
name='document_create_multiple'
regex=r'^staging_files/(?P<staging_folder_id>\d+)/(?P<encoded_filename>.+)/delete/$',
name='staging_file_delete', view=StagingFileDeleteView.as_view()
),
]
api_urls = [
url(
r'^staging_folders/file/(?P<staging_folder_pk>[0-9]+)/(?P<encoded_filename>.+)/image/$',
APIStagingSourceFileImageView.as_view(),
name='stagingfolderfile-image-view'
regex=r'^staging_folders/file/(?P<staging_folder_id>\d+)/(?P<encoded_filename>.+)/image/$',
name='stagingfolderfile-image-view',
view=APIStagingSourceFileImageView.as_view()
),
url(
r'^staging_folders/file/(?P<staging_folder_pk>[0-9]+)/(?P<encoded_filename>.+)/$',
APIStagingSourceFileView.as_view(), name='stagingfolderfile-detail'
regex=r'^staging_folders/file/(?P<staging_folder_id>\d+)/(?P<encoded_filename>.+)/$',
name='stagingfolderfile-detail', view=APIStagingSourceFileView.as_view()
),
url(
r'^staging_folders/$', APIStagingSourceListView.as_view(),
name='stagingfolder-list'
regex=r'^staging_folders/$', name='stagingfolder-list',
view=APIStagingSourceListView.as_view()
),
url(
r'^staging_folders/(?P<pk>[0-9]+)/$', APIStagingSourceView.as_view(),
name='stagingfolder-detail'
regex=r'^staging_folders/(?P<staging_folder_id>\d+)/$',
name='stagingfolder-detail', view=APIStagingSourceView.as_view()
)
]
+15 -15
View File
@@ -14,21 +14,6 @@ from .models import (
)
def get_class(source_type):
if source_type == SOURCE_CHOICE_WEB_FORM:
return WebFormSource
elif source_type == SOURCE_CHOICE_STAGING:
return StagingFolderSource
elif source_type == SOURCE_CHOICE_WATCH:
return WatchFolderSource
elif source_type == SOURCE_CHOICE_EMAIL_POP3:
return POP3Email
elif source_type == SOURCE_CHOICE_EMAIL_IMAP:
return IMAPEmail
elif source_type == SOURCE_CHOICE_SANE_SCANNER:
return SaneScanner
def get_form_class(source_type):
if source_type == SOURCE_CHOICE_WEB_FORM:
return WebFormSetupForm
@@ -44,6 +29,21 @@ def get_form_class(source_type):
return SaneScannerSetupForm
def get_model(source_type):
if source_type == SOURCE_CHOICE_WEB_FORM:
return WebFormSource
elif source_type == SOURCE_CHOICE_STAGING:
return StagingFolderSource
elif source_type == SOURCE_CHOICE_WATCH:
return WatchFolderSource
elif source_type == SOURCE_CHOICE_EMAIL_POP3:
return POP3Email
elif source_type == SOURCE_CHOICE_EMAIL_IMAP:
return IMAPEmail
elif source_type == SOURCE_CHOICE_SANE_SCANNER:
return SaneScanner
def get_upload_form_class(source_type):
if source_type == SOURCE_CHOICE_WEB_FORM:
return WebFormUploadForm
+190 -189
View File
@@ -15,13 +15,12 @@ from django.utils.translation import ugettext_lazy as _
from mayan.apps.acls.models import AccessControlList
from mayan.apps.checkouts.models import NewVersionBlock
from mayan.apps.common import menu_facet
from mayan.apps.common.mixins import ListModeMixin
from mayan.apps.common.mixins import ExternalObjectMixin, ListModeMixin
from mayan.apps.common.models import SharedUploadedFile
from mayan.apps.common.views import (
ConfirmView, MultiFormView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectEditView, SingleObjectListView
)
from mayan.apps.common.widgets import TwoStateWidget
from mayan.apps.documents.models import Document, DocumentType
from mayan.apps.documents.permissions import (
permission_document_create, permission_document_new_version
@@ -34,29 +33,160 @@ from .forms import (
NewDocumentForm, NewVersionForm, WebFormUploadForm, WebFormUploadFormHTML5
)
from .icons import (
icon_log, icon_setup_sources, icon_staging_folder, icon_upload_view_link
icon_log, icon_source_list, icon_staging_folder, icon_upload_view_link
)
from .links import (
link_setup_source_create_imap_email, link_setup_source_create_pop3_email,
link_setup_source_create_sane_scanner,
link_setup_source_create_staging_folder,
link_setup_source_create_watch_folder, link_setup_source_create_webform
link_source_create_imap_email, link_source_create_pop3_email,
link_source_create_sane_scanner, link_source_create_staging_folder,
link_source_create_watch_folder, link_source_create_webform
)
from .literals import SOURCE_UNCOMPRESS_CHOICE_ASK, SOURCE_UNCOMPRESS_CHOICE_Y
from .models import InteractiveSource, SaneScanner, Source, StagingFolderSource
from .permissions import (
permission_sources_setup_create, permission_sources_setup_delete,
permission_sources_setup_edit, permission_sources_setup_view,
permission_sources_create, permission_sources_delete,
permission_sources_edit, permission_sources_view,
permission_staging_file_delete
)
from .tasks import task_check_interval_source, task_source_handle_upload
from .utils import get_class, get_form_class, get_upload_form_class
from .utils import get_form_class, get_model, get_upload_form_class
logger = logging.getLogger(__name__)
class SourceLogListView(SingleObjectListView):
view_permission = permission_sources_setup_view
class SourceCheckView(ExternalObjectMixin, ConfirmView):
"""
Trigger the task_check_interval_source task for a given source to
test/debug their configuration irrespective of the schedule task setup.
"""
external_object_pk_url_kwarg = 'source_id'
external_object_queryset = Source.objects.select_subclasses()
external_object_permission = permission_sources_edit
def get_extra_context(self):
return {
'object': self.get_object(),
'subtitle': _(
'This will execute the source check code even if the source '
'is not enabled. Sources that delete content after '
'downloading will not do so while being tested. Check the '
'source\'s error log for information during testing. A '
'successful test will clear the error log.'
), 'title': _(
'Trigger check for source "%s"?'
) % self.get_object(),
}
def get_object(self):
return self.get_external_object()
def view_action(self):
task_check_interval_source.apply_async(
kwargs={
'source_id': self.get_object().pk, 'test': True
}
)
messages.success(
message=_('Source check queued.'), request=self.request
)
class SourceCreateView(SingleObjectCreateView):
post_action_redirect = reverse_lazy(viewname='sources:source_list')
view_permission = permission_sources_create
def get_form_class(self):
return get_form_class(self.kwargs['source_type'])
def get_extra_context(self):
return {
'object': get_model(self.kwargs['source_type']),
'title': _(
'Create new source of type: %s'
) % get_model(self.kwargs['source_type']).class_fullname(),
}
class SourceDeleteView(SingleObjectDeleteView):
post_action_redirect = reverse_lazy(viewname='sources:source_list')
view_permission = permission_sources_delete
def get_object(self):
return get_object_or_404(
klass=Source.objects.select_subclasses(), pk=self.kwargs['source_id']
)
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(),
}
class SourceEditView(SingleObjectEditView):
post_action_redirect = reverse_lazy(viewname='sources:source_list')
view_permission = permission_sources_edit
def get_object(self):
return get_object_or_404(
klass=Source.objects.select_subclasses(), pk=self.kwargs['source_id']
)
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(),
}
class SourceListView(SingleObjectListView):
queryset = Source.objects.select_subclasses()
view_permission = permission_sources_view
def get_extra_context(self):
return {
'hide_link': True,
'hide_object': True,
'no_results_icon': icon_source_list,
'no_results_secondary_links': [
link_source_create_webform.resolve(
context=RequestContext(request=self.request)
),
link_source_create_imap_email.resolve(
context=RequestContext(request=self.request)
),
link_source_create_pop3_email.resolve(
context=RequestContext(request=self.request)
),
link_source_create_sane_scanner.resolve(
context=RequestContext(request=self.request)
),
link_source_create_staging_folder.resolve(
context=RequestContext(request=self.request)
),
link_source_create_watch_folder.resolve(
context=RequestContext(request=self.request)
),
],
'no_results_text': _(
'Sources provide the means to upload documents. '
'Some sources like the webform, are interactive and require '
'user input to operate. Others like the email sources, are '
'automatic and run on the background without user intervention.'
),
'no_results_title': _('No sources available'),
'title': _('Sources'),
}
class SourceLogView(SingleObjectListView):
view_permission = permission_sources_view
def get_extra_context(self):
return {
@@ -76,7 +206,30 @@ class SourceLogListView(SingleObjectListView):
def get_source(self):
return get_object_or_404(
klass=Source.objects.select_subclasses(), pk=self.kwargs['pk']
klass=Source.objects.select_subclasses(), pk=self.kwargs['source_id']
)
class StagingFileDeleteView(SingleObjectDeleteView):
object_permission = permission_staging_file_delete
object_permission_related = 'staging_folder'
def get_extra_context(self):
return {
'object': self.get_object(),
'object_name': _('Staging file'),
'source': self.get_source(),
}
def get_object(self):
source = self.get_source()
return source.get_file(
encoded_filename=self.kwargs['encoded_filename']
)
def get_source(self):
return get_object_or_404(
klass=StagingFolderSource, pk=self.kwargs['staging_folder_id']
)
@@ -122,13 +275,14 @@ class UploadBaseView(ListModeMixin, MultiFormView):
if not InteractiveSource.objects.filter(enabled=True).exists():
messages.error(
request,
_(
message=_(
'No interactive document sources have been defined or '
'none have been enabled, create one before proceeding.'
)
), request=request
)
return HttpResponseRedirect(
redirect_to=reverse(viewname='sources:source_list')
)
return HttpResponseRedirect(reverse('sources:setup_source_list'))
return super(UploadBaseView, self).dispatch(request, *args, **kwargs)
@@ -142,7 +296,7 @@ class UploadBaseView(ListModeMixin, MultiFormView):
try:
staging_filelist = list(self.source.get_files())
except Exception as exception:
messages.error(self.request, exception)
messages.error(message=exception, request=self.request)
staging_filelist = []
finally:
subtemplates_list = [
@@ -243,7 +397,7 @@ class UploadInteractiveView(UploadBaseView):
forms['source_form'].cleaned_data
)
except SourceException as exception:
messages.error(self.request, exception)
messages.error(message=exception, request=self.request)
else:
shared_uploaded_file = SharedUploadedFile.objects.create(
file=uploaded_file.file
@@ -257,7 +411,7 @@ class UploadInteractiveView(UploadBaseView):
try:
self.source.clean_up_upload_file(uploaded_file)
except Exception as exception:
messages.error(self.request, exception)
messages.error(message=exception, request=self.request)
querystring = furl()
querystring.args.update(self.request.GET)
@@ -293,15 +447,14 @@ class UploadInteractiveView(UploadBaseView):
raise type(exception)(message)
else:
messages.success(
self.request,
_(
message=_(
'New document queued for upload and will be available '
'shortly.'
)
), request=self.request
)
return HttpResponseRedirect(
'{}?{}'.format(
redirect_to='{}?{}'.format(
reverse(
self.request.resolver_match.view_name,
kwargs=self.request.resolver_match.kwargs
@@ -372,19 +525,19 @@ class UploadInteractiveVersionView(UploadBaseView):
self.subtemplates_list = []
self.document = get_object_or_404(klass=Document, pk=kwargs['document_pk'])
self.document = get_object_or_404(klass=Document, pk=kwargs['document_id'])
# TODO: Try to remove this new version block check from here
if NewVersionBlock.objects.is_blocked(self.document):
messages.error(
self.request,
_(
message=_(
'Document "%s" is blocked from uploading new versions.'
) % self.document
) % self.document, request=self.request
)
return HttpResponseRedirect(
reverse(
'documents:document_version_list', args=(self.document.pk,)
redirect_to=reverse(
viewname='documents:document_version_list',
kwargs={'document_version_id': self.document.pk}
)
)
@@ -405,7 +558,7 @@ class UploadInteractiveVersionView(UploadBaseView):
forms['source_form'].cleaned_data
)
except SourceException as exception:
messages.error(self.request, exception)
messages.error(message=exception, request=self.request)
else:
shared_uploaded_file = SharedUploadedFile.objects.create(
file=uploaded_file.file
@@ -414,7 +567,7 @@ class UploadInteractiveVersionView(UploadBaseView):
try:
self.source.clean_up_upload_file(uploaded_file)
except Exception as exception:
messages.error(self.request, exception)
messages.error(message=exception, request=self.request)
if not self.request.user.is_anonymous:
user_id = self.request.user.pk
@@ -429,16 +582,16 @@ class UploadInteractiveVersionView(UploadBaseView):
))
messages.success(
self.request,
_(
message=_(
'New document version queued for upload and will be '
'available shortly.'
)
), request=self.request
)
return HttpResponseRedirect(
reverse(
'documents:document_version_list', args=(self.document.pk,)
redirect_to=reverse(
viewname='documents:document_version_list',
kwargs={'document_id': self.document.pk}
)
)
@@ -474,155 +627,3 @@ class UploadInteractiveVersionView(UploadBaseView):
) % self.source.label
return context
class StagingFileDeleteView(SingleObjectDeleteView):
object_permission = permission_staging_file_delete
object_permission_related = 'staging_folder'
def get_extra_context(self):
return {
'object': self.get_object(),
'object_name': _('Staging file'),
'source': self.get_source(),
}
def get_object(self):
source = self.get_source()
return source.get_file(
encoded_filename=self.kwargs['encoded_filename']
)
def get_source(self):
return get_object_or_404(
klass=StagingFolderSource, pk=self.kwargs['pk']
)
# Setup views
class SetupSourceCheckView(ConfirmView):
"""
Trigger the task_check_interval_source task for a given source to
test/debug their configuration irrespective of the schedule task setup.
"""
view_permission = permission_sources_setup_create
def get_extra_context(self):
return {
'object': self.get_object(),
'subtitle': _(
'This will execute the source check code even if the source '
'is not enabled. Sources that delete content after '
'downloading will not do so while being tested. Check the '
'source\'s error log for information during testing. A '
'successful test will clear the error log.'
), 'title': _(
'Trigger check for source "%s"?'
) % self.get_object(),
}
def get_object(self):
return get_object_or_404(klass=Source.objects.select_subclasses(), pk=self.kwargs['pk'])
def view_action(self):
task_check_interval_source.apply_async(
kwargs={
'source_id': self.get_object().pk, 'test': True
}
)
messages.success(self.request, _('Source check queued.'))
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'],
'title': _(
'Create new source of type: %s'
) % get_class(self.kwargs['source_type']).class_fullname(),
}
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(
klass=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(),
}
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(
klass=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(),
}
class SetupSourceListView(SingleObjectListView):
queryset = Source.objects.select_subclasses()
view_permission = permission_sources_setup_view
def get_extra_context(self):
return {
'hide_link': True,
'hide_object': True,
'no_results_icon': icon_setup_sources,
'no_results_secondary_links': [
link_setup_source_create_webform.resolve(
context=RequestContext(request=self.request)
),
link_setup_source_create_imap_email.resolve(
context=RequestContext(request=self.request)
),
link_setup_source_create_pop3_email.resolve(
context=RequestContext(request=self.request)
),
link_setup_source_create_sane_scanner.resolve(
context=RequestContext(request=self.request)
),
link_setup_source_create_staging_folder.resolve(
context=RequestContext(request=self.request)
),
link_setup_source_create_watch_folder.resolve(
context=RequestContext(request=self.request)
),
],
'no_results_text': _(
'Sources provide the means to upload documents. '
'Some sources like the webform, are interactive and require '
'user input to operate. Others like the email sources, are '
'automatic and run on the background without user intervention.'
),
'no_results_title': _('No sources available'),
'title': _('Sources'),
}
+14 -14
View File
@@ -150,12 +150,25 @@ class DocumentCreateWizard(SessionWizardView):
'none have been enabled, create one before proceeding.'
)
)
return HttpResponseRedirect(reverse('sources:setup_source_list'))
return HttpResponseRedirect(reverse(viewname='sources:setup_source_list'))
return super(
DocumentCreateWizard, self
).dispatch(request, *args, **kwargs)
def done(self, form_list, **kwargs):
query_dict = {}
for step in WizardStep.get_all():
query_dict.update(step.done(wizard=self) or {})
url = furl(reverse(viewname='sources:upload_interactive'))
# Use equal and not .update() to get the same result as using
# urlencode(doseq=True)
url.args = query_dict
return HttpResponseRedirect(url)
def get_context_data(self, form, **kwargs):
context = super(
DocumentCreateWizard, self
@@ -184,16 +197,3 @@ class DocumentCreateWizard(SessionWizardView):
def get_form_kwargs(self, step):
return WizardStep.get(name=step).get_form_kwargs(wizard=self) or {}
def done(self, form_list, **kwargs):
query_dict = {}
for step in WizardStep.get_all():
query_dict.update(step.done(wizard=self) or {})
url = furl(reverse('sources:upload_interactive'))
# Use equal and not .update() to get the same result as using
# urlencode(doseq=True)
url.args = query_dict
return HttpResponseRedirect(url)