diff --git a/mayan/apps/sources/permissions.py b/mayan/apps/sources/permissions.py index 9ca6d8dc79..0575b8561f 100644 --- a/mayan/apps/sources/permissions.py +++ b/mayan/apps/sources/permissions.py @@ -17,3 +17,6 @@ permission_sources_setup_edit = namespace.add_permission( permission_sources_setup_view = namespace.add_permission( name='sources_setup_view', label=_('View existing document sources') ) +permission_staging_file_delete = namespace.add_permission( + name='sources_staging_file_delete', label=_('Delete staging files') +) diff --git a/mayan/apps/sources/tests/test_views.py b/mayan/apps/sources/tests/test_views.py index be0d2fed47..038ccd0882 100644 --- a/mayan/apps/sources/tests/test_views.py +++ b/mayan/apps/sources/tests/test_views.py @@ -1,11 +1,16 @@ from __future__ import unicode_literals +import os +import shutil +import tempfile + from django.contrib.auth import get_user_model from django.core.urlresolvers import reverse from django.test.client import Client from django.test import TestCase, override_settings from acls.models import AccessControlList +from common.tests.test_views import GenericViewTestCase from documents.models import Document, DocumentType, NewVersionBlock from documents.permissions import permission_document_create from documents.tests import ( @@ -19,10 +24,12 @@ from user_management.tests import ( ) from ..links import link_upload_version from ..literals import SOURCE_CHOICE_WEB_FORM -from ..models import WebFormSource +from ..models import StagingFolderSource, WebFormSource +from ..permissions import permission_staging_file_delete TEST_SOURCE_LABEL = 'test' -TEST_SOURCE_UNCOMPRESS = 'n' +TEST_SOURCE_UNCOMPRESS_N = 'n' +TEST_STAGING_PREVIEW_WIDTH = 640 class DocumentUploadTestCase(GenericDocumentViewTestCase): @@ -30,7 +37,7 @@ class DocumentUploadTestCase(GenericDocumentViewTestCase): super(DocumentUploadTestCase, self).setUp() self.source = WebFormSource.objects.create( enabled=True, label=TEST_SOURCE_LABEL, - uncompress=TEST_SOURCE_UNCOMPRESS + uncompress=TEST_SOURCE_UNCOMPRESS_N ) self.document.delete() @@ -210,3 +217,71 @@ class NewDocumentVersionViewTestCase(GenericDocumentViewTestCase): resolved_link = link_upload_version.resolve(context=response.context) self.assertEqual(resolved_link, None) + + +class StagingFolderTestCase(GenericViewTestCase): + def setUp(self): + super(StagingFolderTestCase, self).setUp() + self.temporary_directory = tempfile.mkdtemp() + # TODO: remove temp directory after test + shutil.copy(TEST_SMALL_DOCUMENT_PATH, self.temporary_directory) + + self.filename = os.path.basename(TEST_SMALL_DOCUMENT_PATH) + + def tearDown(self): + super(StagingFolderTestCase, self).tearDown() + shutil.rmtree(self.temporary_directory) + + def test_staging_folder_delete_no_permission(self): + self.login( + username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD + ) + + staging_folder = StagingFolderSource.objects.create( + label=TEST_SOURCE_LABEL, + folder_path=self.temporary_directory, + preview_width=TEST_STAGING_PREVIEW_WIDTH, + uncompress=TEST_SOURCE_UNCOMPRESS_N, + ) + + self.assertEqual(len(list(staging_folder.get_files())), 1) + + staging_file = list(staging_folder.get_files())[0] + + response = self.post( + 'sources:staging_file_delete', args=( + staging_folder.pk, staging_file.encoded_filename + ), follow=True + ) + + self.assertEqual(response.status_code, 403) + self.assertEqual(len(list(staging_folder.get_files())), 1) + + def test_staging_folder_delete_with_permission(self): + self.login( + username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD + ) + + self.role.permissions.add( + permission_staging_file_delete.stored_permission + ) + + staging_folder = StagingFolderSource.objects.create( + label=TEST_SOURCE_LABEL, + folder_path=self.temporary_directory, + preview_width=TEST_STAGING_PREVIEW_WIDTH, + uncompress=TEST_SOURCE_UNCOMPRESS_N, + ) + + self.assertEqual(len(list(staging_folder.get_files())), 1) + + staging_file = list(staging_folder.get_files())[0] + + response = self.post( + 'sources:staging_file_delete', args=( + staging_folder.pk, staging_file.encoded_filename + ), follow=True + ) + + self.assertContains(response, 'deleted', status_code=200) + self.assertEqual(len(list(staging_folder.get_files())), 0) diff --git a/mayan/apps/sources/urls.py b/mayan/apps/sources/urls.py index b52e01f902..15eb41df1b 100644 --- a/mayan/apps/sources/urls.py +++ b/mayan/apps/sources/urls.py @@ -8,16 +8,16 @@ from .api_views import ( ) from .views import ( SetupSourceCreateView, SetupSourceDeleteView, SetupSourceEditView, - SetupSourceListView, SourceLogListView, UploadInteractiveVersionView, - UploadInteractiveView + SetupSourceListView, SourceLogListView, StagingFileDeleteView, + UploadInteractiveVersionView, UploadInteractiveView ) from .wizards import DocumentCreateWizard urlpatterns = patterns( - 'sources.views', + '', url( - r'^staging_file/(?P\d+)/(?P.+)/delete/$', - 'staging_file_delete', name='staging_file_delete' + r'^staging_file/(?P\d+)/(?P.+)/delete/$', + StagingFileDeleteView.as_view(), name='staging_file_delete' ), url( diff --git a/mayan/apps/sources/views.py b/mayan/apps/sources/views.py index a0d02acefa..288cfcd40d 100644 --- a/mayan/apps/sources/views.py +++ b/mayan/apps/sources/views.py @@ -1,12 +1,10 @@ from __future__ import absolute_import, unicode_literals -from django.conf import settings from django.contrib import messages from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse, reverse_lazy from django.http import HttpResponseRedirect -from django.shortcuts import render_to_response, get_object_or_404 -from django.template import RequestContext +from django.shortcuts import get_object_or_404 from django.utils.translation import ugettext_lazy as _ from acls.models import AccessControlList @@ -41,7 +39,8 @@ from .models import ( ) from .permissions import ( permission_sources_setup_create, permission_sources_setup_delete, - permission_sources_setup_edit, permission_sources_setup_view + permission_sources_setup_edit, permission_sources_setup_view, + permission_staging_file_delete ) from .tasks import task_source_handle_upload from .utils import get_class, get_form_class, get_upload_form_class @@ -423,48 +422,27 @@ class UploadInteractiveVersionView(UploadBaseView): return context -def staging_file_delete(request, staging_folder_pk, encoded_filename): - Permission.check_permissions( - request.user, ( - permission_document_create, permission_document_new_version +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'] ) - ) - staging_folder = get_object_or_404( - StagingFolderSource, pk=staging_folder_pk - ) - staging_file = staging_folder.get_file(encoded_filename=encoded_filename) - next = request.POST.get( - 'next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))) - ) - previous = request.POST.get( - 'previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))) - ) - - if request.method == 'POST': - try: - staging_file.delete() - messages.success(request, _('Staging file delete successfully.')) - except Exception as exception: - messages.error( - request, _('Staging file delete error; %s.') % exception - ) - return HttpResponseRedirect(next) - - results = UploadBaseView.get_active_tab_links() - - return render_to_response('appearance/generic_confirm.html', { - 'source': staging_folder, - 'delete_view': True, - 'object': staging_file, - 'next': next, - 'previous': previous, - 'extra_navigation_links': { - 'form_header': { - 'staging_file_delete': {'links': results['tab_links']} - } - }, - }, context_instance=RequestContext(request)) + def get_source(self): + return get_object_or_404( + StagingFolderSource, pk=self.kwargs['pk'] + ) # Setup views