From 3e53ce0c4300d4dd80fc7001c85d95b7968bff44 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 2 Jan 2019 13:54:58 -0400 Subject: [PATCH] Add keyword arguments to the cabinet app Modernize tests. Use the FilteredSelectionForm in the view to add new cabinets to documents. Add missing icons. Rename some view names to be more consistent. Signed-off-by: Roberto Rosario --- mayan/apps/cabinets/api_views.py | 6 +- mayan/apps/cabinets/apps.py | 27 +++---- mayan/apps/cabinets/events.py | 2 +- mayan/apps/cabinets/forms.py | 33 ++------ mayan/apps/cabinets/icons.py | 20 ++++- mayan/apps/cabinets/links.py | 35 ++++---- mayan/apps/cabinets/models.py | 19 +++-- mayan/apps/cabinets/permissions.py | 12 +-- mayan/apps/cabinets/serializers.py | 9 ++- mayan/apps/cabinets/tests/test_api.py | 79 +++++++++--------- mayan/apps/cabinets/tests/test_views.py | 69 +++++++++++----- .../apps/cabinets/tests/test_wizard_steps.py | 2 +- mayan/apps/cabinets/urls.py | 81 +++++++++++-------- mayan/apps/cabinets/views.py | 51 +++++++----- mayan/apps/cabinets/wizard_steps.py | 2 +- 15 files changed, 254 insertions(+), 193 deletions(-) diff --git a/mayan/apps/cabinets/api_views.py b/mayan/apps/cabinets/api_views.py index caf1849678..8811607090 100644 --- a/mayan/apps/cabinets/api_views.py +++ b/mayan/apps/cabinets/api_views.py @@ -33,7 +33,7 @@ class APIDocumentCabinetListView(generics.ListAPIView): mayan_object_permissions = {'GET': (permission_cabinet_view,)} def get_queryset(self): - document = get_object_or_404(Document, pk=self.kwargs['pk']) + document = get_object_or_404(Document, pk=self.kwargs['document_pk']) AccessControlList.objects.check_access( permissions=permission_document_view, user=self.request.user, obj=document @@ -135,7 +135,7 @@ class APICabinetDocumentListView(generics.ListCreateAPIView): return context def get_cabinet(self): - return get_object_or_404(klass=Cabinet, pk=self.kwargs['pk']) + return get_object_or_404(klass=Cabinet, pk=self.kwargs['cabinet_pk']) def get_queryset(self): cabinet = self.get_cabinet() @@ -163,7 +163,7 @@ class APICabinetDocumentView(generics.RetrieveDestroyAPIView): serializer_class = CabinetDocumentSerializer def get_cabinet(self): - return get_object_or_404(klass=Cabinet, pk=self.kwargs['pk']) + return get_object_or_404(klass=Cabinet, pk=self.kwargs['cabinet_pk']) def get_queryset(self): return self.get_cabinet().documents.all() diff --git a/mayan/apps/cabinets/apps.py b/mayan/apps/cabinets/apps.py index ed77edfd4f..4f1d6c4514 100644 --- a/mayan/apps/cabinets/apps.py +++ b/mayan/apps/cabinets/apps.py @@ -16,11 +16,11 @@ from mayan.apps.documents.search import document_page_search, document_search from mayan.apps.navigation import SourceColumn from .links import ( - link_cabinet_add_document, link_cabinet_add_multiple_documents, link_cabinet_child_add, link_cabinet_create, link_cabinet_delete, link_cabinet_edit, link_cabinet_list, link_cabinet_view, - link_custom_acl_list, link_document_cabinet_list, - link_document_cabinet_remove, link_multiple_document_cabinet_remove + link_custom_acl_list, link_document_cabinet_add, + link_document_cabinet_list, link_document_cabinet_remove, + link_document_multiple_cabinet_add, link_document_multiple_cabinet_remove ) from .menus import menu_cabinets from .methods import method_get_document_cabinets @@ -49,8 +49,8 @@ class CabinetsApp(MayanAppConfig): app_label='documents', model_name='Document' ) - DocumentCabinet = self.get_model('DocumentCabinet') - Cabinet = self.get_model('Cabinet') + DocumentCabinet = self.get_model(model_name='DocumentCabinet') + Cabinet = self.get_model(model_name='Cabinet') # Add explicit order_by as DocumentCabinet ordering Meta option has no # effect. @@ -80,18 +80,17 @@ class CabinetsApp(MayanAppConfig): ) SourceColumn( - source=Document, label=_('Cabinets'), func=lambda context: widget_document_cabinets( document=context['object'], user=context['request'].user - ), order=1 + ), order=1, label=_('Cabinets'), source=Document ) document_page_search.add_model_field( - field='document_version__document__cabinets__label', - label=_('Cabinets') + label=_('Cabinets'), + field='document_version__document__cabinets__label' ) document_search.add_model_field( - field='cabinets__label', label=_('Cabinets') + label=_('Cabinets'), field='cabinets__label' ) menu_facet.bind_links( @@ -108,8 +107,8 @@ class CabinetsApp(MayanAppConfig): menu_multi_item.bind_links( links=( - link_cabinet_add_multiple_documents, - link_multiple_document_cabinet_remove + link_document_multiple_cabinet_add, + link_document_multiple_cabinet_remove ), sources=(Document,) ) menu_object.bind_links( @@ -125,10 +124,10 @@ class CabinetsApp(MayanAppConfig): ), sources=(Cabinet,) ) menu_sidebar.bind_links( - links=(link_cabinet_add_document, link_document_cabinet_remove), + links=(link_document_cabinet_add, link_document_cabinet_remove), sources=( 'cabinets:document_cabinet_list', - 'cabinets:cabinet_add_document', + 'cabinets:document_cabinet_add', 'cabinets:document_cabinet_remove' ) ) diff --git a/mayan/apps/cabinets/events.py b/mayan/apps/cabinets/events.py index bca867bd2a..998ceddabd 100644 --- a/mayan/apps/cabinets/events.py +++ b/mayan/apps/cabinets/events.py @@ -4,7 +4,7 @@ from django.utils.translation import ugettext_lazy as _ from mayan.apps.events import EventTypeNamespace -namespace = EventTypeNamespace(name='cabinets', label=_('Cabinets')) +namespace = EventTypeNamespace(label=_('Cabinets'), name='cabinets') event_cabinets_add_document = namespace.add_event_type( label=_('Document added to cabinet'), name='add_document' diff --git a/mayan/apps/cabinets/forms.py b/mayan/apps/cabinets/forms.py index 5876fefcc6..82626055c9 100644 --- a/mayan/apps/cabinets/forms.py +++ b/mayan/apps/cabinets/forms.py @@ -1,33 +1,12 @@ from __future__ import absolute_import, unicode_literals -import logging - -from django import forms from django.utils.translation import ugettext_lazy as _ -from mayan.apps.acls.models import AccessControlList - -from .models import Cabinet - -logger = logging.getLogger(__name__) +from mayan.apps.common.forms import FilteredSelectionForm -class CabinetListForm(forms.Form): - def __init__(self, *args, **kwargs): - help_text = kwargs.pop('help_text', None) - permission = kwargs.pop('permission', None) - queryset = kwargs.pop('queryset', Cabinet.objects.all()) - user = kwargs.pop('user', None) - - logger.debug('user: %s', user) - super(CabinetListForm, self).__init__(*args, **kwargs) - - queryset = AccessControlList.objects.filter_by_access( - permission=permission, user=user, queryset=queryset - ) - - self.fields['cabinets'] = forms.ModelMultipleChoiceField( - label=_('Cabinets'), help_text=help_text, - queryset=queryset, required=False, - widget=forms.SelectMultiple(attrs={'class': 'select2'}) - ) +class CabinetListForm(FilteredSelectionForm): + _field_name = 'cabinets' + _label = _('Cabinets') + _widget_attributes = {'class': 'select2'} + _allow_multiple = True diff --git a/mayan/apps/cabinets/icons.py b/mayan/apps/cabinets/icons.py index 879186abf0..f3f28fa879 100644 --- a/mayan/apps/cabinets/icons.py +++ b/mayan/apps/cabinets/icons.py @@ -3,7 +3,25 @@ from __future__ import absolute_import, unicode_literals from mayan.apps.appearance.classes import Icon icon_cabinet = Icon(driver_name='fontawesome', symbol='columns') -icon_cabinet_add = Icon(driver_name='fontawesome', symbol='plus') icon_cabinet_child_add = Icon(driver_name='fontawesome', symbol='plus') icon_cabinet_create = Icon(driver_name='fontawesome', symbol='plus') +icon_cabinet_delete = Icon(driver_name='fontawesome', symbol='times') +icon_cabinet_edit = Icon(driver_name='fontawesome', symbol='pencil-alt') icon_cabinet_list = Icon(driver_name='fontawesome', symbol='columns') +icon_cabinet_view = Icon(driver_name='fontawesome', symbol='columns') +icon_document_cabinet_add = Icon( + driver_name='fontawesome-dual', primary_symbol='columns', + secondary_symbol='arrow-right' +) +icon_document_multiple_cabinet_add = Icon( + driver_name='fontawesome-dual', primary_symbol='columns', + secondary_symbol='arrow-right' +) +icon_document_cabinet_remove = Icon( + driver_name='fontawesome-dual', primary_symbol='columns', + secondary_symbol='minus' +) +icon_document_multiple_cabinet_remove = Icon( + driver_name='fontawesome-dual', primary_symbol='columns', + secondary_symbol='minus' +) diff --git a/mayan/apps/cabinets/links.py b/mayan/apps/cabinets/links.py index 7a19505cec..bdf0a25294 100644 --- a/mayan/apps/cabinets/links.py +++ b/mayan/apps/cabinets/links.py @@ -9,8 +9,10 @@ from mayan.apps.documents.permissions import permission_document_view from mayan.apps.navigation import Link, get_cascade_condition from .icons import ( - icon_cabinet_add, icon_cabinet_child_add, icon_cabinet_create, - icon_cabinet_list + icon_cabinet_child_add, icon_cabinet_create, icon_cabinet_delete, + icon_cabinet_edit, icon_cabinet_list, icon_cabinet_view, + icon_document_cabinet_add, icon_document_cabinet_remove, + icon_document_multiple_cabinet_add, icon_document_multiple_cabinet_remove ) from .permissions import ( permission_cabinet_add_document, permission_cabinet_create, @@ -26,21 +28,23 @@ link_document_cabinet_list = Link( text=_('Cabinets'), view='cabinets:document_cabinet_list', ) link_document_cabinet_remove = Link( - args='resolved_object.pk', + args='resolved_object.pk', icon_class=icon_document_cabinet_remove, permissions=(permission_cabinet_remove_document,), text=_('Remove from cabinets'), view='cabinets:document_cabinet_remove' ) -link_cabinet_add_document = Link( - args='object.pk', icon_class=icon_cabinet_add, +link_document_cabinet_add = Link( + args='object.pk', icon_class=icon_document_cabinet_add, permissions=(permission_cabinet_add_document,), text=_('Add to cabinets'), - view='cabinets:cabinet_add_document', + view='cabinets:document_cabinet_add', ) -link_cabinet_add_multiple_documents = Link( - text=_('Add to cabinets'), view='cabinets:cabinet_add_multiple_documents' +link_document_multiple_cabinet_add = Link( + icon_class=icon_document_multiple_cabinet_add, text=_('Add to cabinets'), + view='cabinets:document_multiple_cabinet_add' ) -link_multiple_document_cabinet_remove = Link( +link_document_multiple_cabinet_remove = Link( + icon_class=icon_document_multiple_cabinet_remove, text=_('Remove from cabinets'), - view='cabinets:multiple_document_cabinet_remove' + view='cabinets:document_multiple_cabinet_remove' ) # Cabinet links @@ -65,11 +69,13 @@ link_cabinet_create = Link( text=_('Create cabinet'), view='cabinets:cabinet_create' ) link_cabinet_delete = Link( - args='object.pk', permissions=(permission_cabinet_delete,), - tags='dangerous', text=_('Delete'), view='cabinets:cabinet_delete' + args='object.pk', icon_class=icon_cabinet_delete, + permissions=(permission_cabinet_delete,), tags='dangerous', + text=_('Delete'), view='cabinets:cabinet_delete' ) link_cabinet_edit = Link( - args='object.pk', permissions=(permission_cabinet_edit,), text=_('Edit'), + args='object.pk', icon_class=icon_cabinet_edit, + permissions=(permission_cabinet_edit,), text=_('Edit'), view='cabinets:cabinet_edit' ) link_cabinet_list = Link( @@ -80,6 +86,7 @@ link_cabinet_list = Link( view='cabinets:cabinet_list' ) link_cabinet_view = Link( - args='object.pk', permissions=(permission_cabinet_view,), text=_('Details'), + args='object.pk', icon_class=icon_cabinet_view, + permissions=(permission_cabinet_view,), text=_('Details'), view='cabinets:cabinet_view' ) diff --git a/mayan/apps/cabinets/models.py b/mayan/apps/cabinets/models.py index 988d1c63f1..7129e63b8a 100644 --- a/mayan/apps/cabinets/models.py +++ b/mayan/apps/cabinets/models.py @@ -53,11 +53,13 @@ class Cabinet(MPTTModel): """ self.documents.add(document) event_cabinets_add_document.commit( - action_object=self, actor=user, target=document + actor=user, action_object=self, target=document ) def get_absolute_url(self): - return reverse('cabinets:cabinet_view', args=(self.pk,)) + return reverse( + viewname='cabinets:cabinet_view', kwargs={'cabinet_pk': self.pk} + ) def get_document_count(self, user): """ @@ -72,7 +74,8 @@ class Cabinet(MPTTModel): filtered by access. """ return AccessControlList.objects.filter_by_access( - permission_document_view, user, queryset=self.documents + permission=permission_document_view, queryset=self.documents, + user=user ) def get_full_path(self): @@ -93,7 +96,7 @@ class Cabinet(MPTTModel): """ self.documents.remove(document) event_cabinets_remove_document.commit( - action_object=self, actor=user, target=document + actor=user, action_object=self, target=document ) def validate_unique(self, exclude=None): @@ -105,9 +108,13 @@ class Cabinet(MPTTModel): """ with transaction.atomic(): if connection.vendor == 'oracle': - queryset = Cabinet.objects.filter(parent=self.parent, label=self.label) + queryset = Cabinet.objects.filter( + parent=self.parent, label=self.label + ) else: - queryset = Cabinet.objects.select_for_update().filter(parent=self.parent, label=self.label) + queryset = Cabinet.objects.select_for_update().filter( + parent=self.parent, label=self.label + ) if queryset.exists(): params = { diff --git a/mayan/apps/cabinets/permissions.py b/mayan/apps/cabinets/permissions.py index 6d3031dbde..e712a63da5 100644 --- a/mayan/apps/cabinets/permissions.py +++ b/mayan/apps/cabinets/permissions.py @@ -9,20 +9,20 @@ namespace = PermissionNamespace(label=_('Cabinets'), name='cabinets') # Translators: this refers to the permission that will allow users to add # documents to cabinets. permission_cabinet_add_document = namespace.add_permission( - name='cabinet_add_document', label=_('Add documents to cabinets') + label=_('Add documents to cabinets'), name='cabinet_add_document' ) permission_cabinet_create = namespace.add_permission( - name='cabinet_create', label=_('Create cabinets') + label=_('Create cabinets'), name='cabinet_create' ) permission_cabinet_delete = namespace.add_permission( - name='cabinet_delete', label=_('Delete cabinets') + label=_('Delete cabinets'), name='cabinet_delete' ) permission_cabinet_edit = namespace.add_permission( - name='cabinet_edit', label=_('Edit cabinets') + label=_('Edit cabinets'), name='cabinet_edit' ) permission_cabinet_remove_document = namespace.add_permission( - name='cabinet_remove_document', label=_('Remove documents from cabinets') + label=_('Remove documents from cabinets'), name='cabinet_remove_document' ) permission_cabinet_view = namespace.add_permission( - name='cabinet_view', label=_('View cabinets') + label=_('View cabinets'), name='cabinet_view' ) diff --git a/mayan/apps/cabinets/serializers.py b/mayan/apps/cabinets/serializers.py index e3d6867123..1b505919e2 100644 --- a/mayan/apps/cabinets/serializers.py +++ b/mayan/apps/cabinets/serializers.py @@ -54,7 +54,7 @@ class CabinetSerializer(serializers.ModelSerializer): def get_parent_url(self, obj): if obj.parent: return reverse( - 'rest_api:cabinet-detail', args=(obj.parent.pk,), + viewname='rest_api:cabinet-detail', kwargs={'cabinet_pk': obj.parent.pk}, format=self.context['format'], request=self.context.get('request') ) @@ -167,9 +167,10 @@ class CabinetDocumentSerializer(DocumentSerializer): def get_cabinet_document_url(self, instance): return reverse( - 'rest_api:cabinet-document', args=( - self.context['cabinet'].pk, instance.pk - ), request=self.context['request'], format=self.context['format'] + viewname='rest_api:cabinet-document', kwargs={ + 'cabinet_pk': self.context['cabinet'].pk, + 'document_pk': instance.pk + }, request=self.context['request'], format=self.context['format'] ) diff --git a/mayan/apps/cabinets/tests/test_api.py b/mayan/apps/cabinets/tests/test_api.py index 8a26d0fb12..929c4166a3 100644 --- a/mayan/apps/cabinets/tests/test_api.py +++ b/mayan/apps/cabinets/tests/test_api.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals from django.contrib.auth import get_user_model -from django.urls import reverse from django.utils.encoding import force_text from rest_framework import status @@ -39,8 +38,9 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): self.document_2 = self.upload_document() def test_cabinet_create(self): - response = self.client.post( - reverse('rest_api:cabinet-list'), {'label': TEST_CABINET_LABEL} + response = self.post( + viewname='rest_api:cabinet-list', + data={'label': TEST_CABINET_LABEL} ) self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -53,8 +53,8 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): self.assertEqual(cabinet.label, TEST_CABINET_LABEL) def test_cabinet_create_with_single_document(self): - response = self.client.post( - reverse('rest_api:cabinet-list'), { + response = self.post( + viewname='rest_api:cabinet-list', data={ 'label': TEST_CABINET_LABEL, 'documents_pk_list': '{}'.format( self.document.pk ) @@ -73,8 +73,8 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): self.assertEqual(cabinet.label, TEST_CABINET_LABEL) def test_cabinet_create_with_multiple_documents(self): - response = self.client.post( - reverse('rest_api:cabinet-list'), { + response = self.post( + viewname='rest_api:cabinet-list', data={ 'label': TEST_CABINET_LABEL, 'documents_pk_list': '{},{}'.format( self.document.pk, self.document_2.pk @@ -102,11 +102,9 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): cabinet = Cabinet.objects.create(label=TEST_CABINET_LABEL) cabinet.documents.add(self.document) - response = self.client.delete( - reverse( - 'rest_api:cabinet-document', - args=(cabinet.pk, self.document.pk) - ) + response = self.delete( + viewname='rest_api:cabinet-document', + kwargs={'cabinet_pk': cabinet.pk, 'document_pk': self.document.pk} ) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) @@ -116,11 +114,9 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): cabinet = Cabinet.objects.create(label=TEST_CABINET_LABEL) cabinet.documents.add(self.document) - response = self.client.get( - reverse( - 'rest_api:cabinet-document', - args=(cabinet.pk, self.document.pk) - ) + response = self.get( + viewname='rest_api:cabinet-document', + kwargs={'cabinet_pk': cabinet.pk, 'document_pk': self.document.pk} ) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -132,8 +128,9 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): cabinet = Cabinet.objects.create(label=TEST_CABINET_LABEL) cabinet.documents.add(self.document) - response = self.client.get( - reverse('rest_api:cabinet-document-list', args=(cabinet.pk,)) + response = self.get( + viewname='rest_api:cabinet-document-list', + kwargs={'cabinet_pk': cabinet.pk} ) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -144,8 +141,9 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): def test_cabinet_delete(self): cabinet = Cabinet.objects.create(label=TEST_CABINET_LABEL) - response = self.client.delete( - reverse('rest_api:cabinet-detail', args=(cabinet.pk,)) + response = self.delete( + viewname='rest_api:cabinet-detail', + kwargs={'cabinet_pk': cabinet.pk} ) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) @@ -154,9 +152,10 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): def test_cabinet_edit_via_patch(self): cabinet = Cabinet.objects.create(label=TEST_CABINET_LABEL) - response = self.client.patch( - reverse('rest_api:cabinet-detail', args=(cabinet.pk,)), - {'label': TEST_CABINET_EDITED_LABEL} + response = self.patch( + viewname='rest_api:cabinet-detail', + kwargs={'cabinet_pk': cabinet.pk}, + data={'label': TEST_CABINET_EDITED_LABEL} ) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -167,9 +166,10 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): def test_cabinet_edit_via_put(self): cabinet = Cabinet.objects.create(label=TEST_CABINET_LABEL) - response = self.client.put( - reverse('rest_api:cabinet-detail', args=(cabinet.pk,)), - {'label': TEST_CABINET_EDITED_LABEL} + response = self.put( + viewname='rest_api:cabinet-detail', + kwargs={'cabinet_pk': cabinet.pk}, + data={'label': TEST_CABINET_EDITED_LABEL} ) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -180,8 +180,9 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): def test_cabinet_add_document(self): cabinet = Cabinet.objects.create(label=TEST_CABINET_LABEL) - response = self.client.post( - reverse('rest_api:cabinet-document-list', args=(cabinet.pk,)), { + response = self.post( + viewname='rest_api:cabinet-document-list', + kwargs={'cabinet_pk': cabinet.pk}, data={ 'documents_pk_list': '{}'.format(self.document.pk) } ) @@ -194,8 +195,10 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): def test_cabinet_add_multiple_documents(self): cabinet = Cabinet.objects.create(label=TEST_CABINET_LABEL) - response = self.client.post( - reverse('rest_api:cabinet-document-list', args=(cabinet.pk,)), { + response = self.post( + viewname='rest_api:cabinet-document-list', + kwargs={'cabinet_pk': cabinet.pk}, + data={ 'documents_pk_list': '{},{}'.format( self.document.pk, self.document_2.pk ) @@ -215,8 +218,8 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): label=TEST_CABINET_LABEL, parent=cabinet ) - response = self.client.get( - reverse('rest_api:cabinet-list') + response = self.get( + viewname='rest_api:cabinet-list' ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['results'][0]['label'], cabinet.label) @@ -226,12 +229,10 @@ class CabinetAPITestCase(DocumentTestMixin, APITestCase): cabinet.documents.add(self.document) - response = self.client.delete( - reverse( - 'rest_api:cabinet-document', args=( - cabinet.pk, self.document.pk - ) - ), + response = self.delete( + viewname='rest_api:cabinet-document', kwargs={ + 'cabinet_pk': cabinet.pk, 'document_pk': self.document.pk + } ) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertEqual(cabinet.documents.count(), 0) diff --git a/mayan/apps/cabinets/tests/test_views.py b/mayan/apps/cabinets/tests/test_views.py index 34f05ec861..9743bdbb56 100644 --- a/mayan/apps/cabinets/tests/test_views.py +++ b/mayan/apps/cabinets/tests/test_views.py @@ -53,14 +53,15 @@ class CabinetViewTestCase(CabinetTestMixin, GenericDocumentViewTestCase): def _request_delete_cabinet(self): return self.post( - viewname='cabinets:cabinet_delete', args=(self.cabinet.pk,) + viewname='cabinets:cabinet_delete', + kwargs={'cabinet_pk': self.cabinet.pk} ) def test_cabinet_delete_view_no_permission(self): self._create_cabinet() response = self._request_delete_cabinet() - self.assertEqual(response.status_code, 403) + self.assertEqual(response.status_code, 404) self.assertEqual(Cabinet.objects.count(), 1) def test_cabinet_delete_view_with_access(self): @@ -74,7 +75,7 @@ class CabinetViewTestCase(CabinetTestMixin, GenericDocumentViewTestCase): def _request_edit_cabinet(self): return self.post( - viewname='cabinets:cabinet_edit', args=(self.cabinet.pk,), data={ + viewname='cabinets:cabinet_edit', kwargs={'cabinet_pk': self.cabinet.pk}, data={ 'label': TEST_CABINET_EDITED_LABEL } ) @@ -83,7 +84,7 @@ class CabinetViewTestCase(CabinetTestMixin, GenericDocumentViewTestCase): self._create_cabinet() response = self._request_edit_cabinet() - self.assertEqual(response.status_code, 403) + self.assertEqual(response.status_code, 404) self.cabinet.refresh_from_db() self.assertEqual(self.cabinet.label, TEST_CABINET_LABEL) @@ -125,16 +126,14 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): def _add_document_to_cabinet(self): return self.post( - viewname='cabinets:cabinet_add_document', args=( - self.document.pk, - ), data={'cabinets': self.cabinet.pk} + viewname='cabinets:document_cabinet_add', kwargs={ + 'document_pk': self.document.pk + }, data={'cabinets': self.cabinet.pk} ) def test_cabinet_add_document_view_no_permission(self): self._create_cabinet() - self.grant_permission(permission=permission_cabinet_view) - response = self._add_document_to_cabinet() self.assertContains( @@ -143,10 +142,37 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): self.cabinet.refresh_from_db() self.assertEqual(self.cabinet.documents.count(), 0) - def test_cabinet_add_document_view_with_access(self): + def test_cabinet_add_document_view_with_cabinet_access(self): + self._create_cabinet() + + self.grant_access( + obj=self.cabinet, permission=permission_cabinet_add_document + ) + response = self._add_document_to_cabinet() + + self.assertContains( + response, text='Select a valid choice.', status_code=404 + ) + self.cabinet.refresh_from_db() + self.assertEqual(self.cabinet.documents.count(), 0) + + def test_cabinet_add_document_view_with_document_access(self): + self._create_cabinet() + + self.grant_access( + obj=self.cabinet, permission=permission_cabinet_add_document + ) + response = self._add_document_to_cabinet() + + self.assertContains( + response, text='Select a valid choice.', status_code=404 + ) + self.cabinet.refresh_from_db() + self.assertEqual(self.cabinet.documents.count(), 0) + + def test_cabinet_add_document_view_with_full_access(self): self._create_cabinet() - self.grant_access(obj=self.cabinet, permission=permission_cabinet_view) self.grant_access( obj=self.cabinet, permission=permission_cabinet_add_document ) @@ -166,7 +192,7 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): def _request_add_multiple_documents_to_cabinet(self): return self.post( - viewname='cabinets:cabinet_add_multiple_documents', data={ + viewname='cabinets:document_multiple_cabinet_add', data={ 'id_list': (self.document.pk,), 'cabinets': self.cabinet.pk } ) @@ -174,8 +200,6 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): def test_cabinet_add_multiple_documents_view_no_permission(self): self._create_cabinet() - self.grant_permission(permission=permission_cabinet_view) - response = self._request_add_multiple_documents_to_cabinet() self.assertContains( @@ -184,7 +208,7 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): self.cabinet.refresh_from_db() self.assertEqual(self.cabinet.documents.count(), 0) - def test_cabinet_add_multiple_documents_view_with_access(self): + def test_cabinet_add_multiple_documents_view_with_full_access(self): self._create_cabinet() self.grant_access( @@ -206,7 +230,7 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): def _request_remove_document_from_cabinet(self): return self.post( viewname='cabinets:document_cabinet_remove', - args=(self.document.pk,), data={ + kwargs={'document_pk': self.document.pk}, data={ 'cabinets': (self.cabinet.pk,), } ) @@ -225,7 +249,7 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): self.cabinet.refresh_from_db() self.assertEqual(self.cabinet.documents.count(), 1) - def test_cabinet_remove_document_view_with_access(self): + def test_cabinet_remove_document_view_with_full_access(self): self._create_cabinet() self.cabinet.documents.add(self.document) @@ -245,7 +269,8 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): def _request_document_cabinet_list(self): return self.get( - viewname='cabinets:document_cabinet_list', args=(self.document.pk,) + viewname='cabinets:document_cabinet_list', + kwargs={'document_pk': self.document.pk} ) def test_document_cabinet_list_view_no_permission(self): @@ -253,10 +278,10 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): self.cabinet.documents.add(self.document) response = self._request_document_cabinet_list() self.assertNotContains( - response=response, text=self.document.label, status_code=403 + response=response, text=self.document.label, status_code=404 ) self.assertNotContains( - response=response, text=self.cabinet.label, status_code=403 + response=response, text=self.cabinet.label, status_code=404 ) def test_document_cabinet_list_view_with_cabinet_access(self): @@ -265,10 +290,10 @@ class DocumentViewsTestCase(CabinetTestMixin, GenericDocumentViewTestCase): self.grant_access(obj=self.cabinet, permission=permission_cabinet_view) response = self._request_document_cabinet_list() self.assertNotContains( - response=response, text=self.document.label, status_code=403 + response=response, text=self.document.label, status_code=404 ) self.assertNotContains( - response=response, text=self.cabinet.label, status_code=403 + response=response, text=self.cabinet.label, status_code=404 ) def test_document_cabinet_list_view_with_document_access(self): diff --git a/mayan/apps/cabinets/tests/test_wizard_steps.py b/mayan/apps/cabinets/tests/test_wizard_steps.py index bd79dd5c8d..61455ec4c5 100644 --- a/mayan/apps/cabinets/tests/test_wizard_steps.py +++ b/mayan/apps/cabinets/tests/test_wizard_steps.py @@ -35,7 +35,7 @@ class CabinetDocumentUploadTestCase(GenericDocumentViewTestCase): def _request_upload_interactive_document_create_view(self): with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object: return self.post( - viewname='sources:upload_interactive', args=(self.source.pk,), + viewname='sources:upload_interactive', kwargs={'source_pk': self.source.pk}, data={ 'document_type_id': self.document_type.pk, 'source-file': file_object, diff --git a/mayan/apps/cabinets/urls.py b/mayan/apps/cabinets/urls.py index 06739ad800..e72e890823 100644 --- a/mayan/apps/cabinets/urls.py +++ b/mayan/apps/cabinets/urls.py @@ -14,61 +14,74 @@ from .views import ( ) urlpatterns = [ - url(r'^list/$', CabinetListView.as_view(), name='cabinet_list'), url( - r'^(?P\d+)/child/add/$', CabinetChildAddView.as_view(), - name='cabinet_child_add' - ), - url(r'^create/$', CabinetCreateView.as_view(), name='cabinet_create'), - url( - r'^(?P\d+)/edit/$', CabinetEditView.as_view(), name='cabinet_edit' + regex=r'^cabinets/$', name='cabinet_list', + view=CabinetListView.as_view() ), url( - r'^(?P\d+)/delete/$', CabinetDeleteView.as_view(), - name='cabinet_delete' - ), - url(r'^(?P\d+)/$', CabinetDetailView.as_view(), name='cabinet_view'), - - url( - r'^document/(?P\d+)/cabinet/add/$', - DocumentAddToCabinetView.as_view(), name='cabinet_add_document' + regex=r'^cabinets/create/$', name='cabinet_create', + view=CabinetCreateView.as_view() ), url( - r'^document/multiple/cabinet/add/$', - DocumentAddToCabinetView.as_view(), - name='cabinet_add_multiple_documents' + regex=r'^cabinets/(?P\d+)/$', name='cabinet_view', + view=CabinetDetailView.as_view() ), url( - r'^document/(?P\d+)/cabinet/remove/$', - DocumentRemoveFromCabinetView.as_view(), name='document_cabinet_remove' + regex=r'^cabinets/(?P\d+)/delete/$', name='cabinet_delete', + view=CabinetDeleteView.as_view() ), url( - r'^document/multiple/cabinet/remove/$', - DocumentRemoveFromCabinetView.as_view(), - name='multiple_document_cabinet_remove' + regex=r'^cabinets/(?P\d+)/edit/$', name='cabinet_edit', + view=CabinetEditView.as_view() ), url( - r'^document/(?P\d+)/cabinet/list/$', - DocumentCabinetListView.as_view(), name='document_cabinet_list' + regex=r'^cabinets/(?P\d+)/child/add/$', + name='cabinet_child_add', view=CabinetChildAddView.as_view() + ), + url( + regex=r'^documents/(?P\d+)/cabinets/add/$', + name='document_cabinet_add', view=DocumentAddToCabinetView.as_view() + ), + url( + regex=r'^documents/multiple/cabinets/add/$', + name='document_multiple_cabinet_add', + view=DocumentAddToCabinetView.as_view() + ), + url( + regex=r'^documents/(?P\d+)/cabinets/remove/$', + name='document_cabinet_remove', + view=DocumentRemoveFromCabinetView.as_view() + ), + url( + regex=r'^documents/multiple/cabinets/remove/$', + name='document_multiple_cabinet_remove', + view=DocumentRemoveFromCabinetView.as_view() + ), + url( + regex=r'^documents/(?P\d+)/cabinets/list/$', + name='document_cabinet_list', view=DocumentCabinetListView.as_view() ), ] api_urls = [ url( - r'^cabinets/(?P[0-9]+)/documents/(?P[0-9]+)/$', - APICabinetDocumentView.as_view(), name='cabinet-document' + regex=r'^cabinets/(?P\d+)/documents/(?P\d+)/$', + name='cabinet-document', view=APICabinetDocumentView.as_view() ), url( - r'^cabinets/(?P[0-9]+)/documents/$', - APICabinetDocumentListView.as_view(), name='cabinet-document-list' + regex=r'^cabinets/(?P\d+)/documents/$', + name='cabinet-document-list', view=APICabinetDocumentListView.as_view() ), url( - r'^cabinets/(?P[0-9]+)/$', APICabinetView.as_view(), - name='cabinet-detail' + regex=r'^cabinets/(?P\d+)/$', name='cabinet-detail', + view=APICabinetView.as_view() ), - url(r'^cabinets/$', APICabinetListView.as_view(), name='cabinet-list'), url( - r'^documents/(?P[0-9]+)/cabinets/$', - APIDocumentCabinetListView.as_view(), name='document-cabinet-list' + regex=r'^cabinets/$', name='cabinet-list', + view=APICabinetListView.as_view() + ), + url( + regex=r'^documents/(?P\d+)/cabinets/$', + name='document-cabinet-list', view=APIDocumentCabinetListView.as_view() ), ] diff --git a/mayan/apps/cabinets/views.py b/mayan/apps/cabinets/views.py index 8d28ad32d8..1b4e1a559a 100644 --- a/mayan/apps/cabinets/views.py +++ b/mayan/apps/cabinets/views.py @@ -21,7 +21,7 @@ from mayan.apps.documents.views import DocumentListView from .forms import CabinetListForm from .icons import icon_cabinet from .links import ( - link_cabinet_add_document, link_cabinet_child_add, link_cabinet_create + link_cabinet_child_add, link_cabinet_create, link_document_cabinet_add ) from .models import Cabinet from .permissions import ( @@ -37,7 +37,7 @@ logger = logging.getLogger(__name__) class CabinetCreateView(SingleObjectCreateView): fields = ('label',) model = Cabinet - post_action_redirect = reverse_lazy('cabinets:cabinet_list') + post_action_redirect = reverse_lazy(viewname='cabinets:cabinet_list') view_permission = permission_cabinet_create def get_extra_context(self): @@ -64,8 +64,8 @@ class CabinetChildAddView(SingleObjectCreateView): cabinet = super(CabinetChildAddView, self).get_object(*args, **kwargs) AccessControlList.objects.check_access( - permissions=permission_cabinet_edit, user=self.request.user, - obj=cabinet.get_root() + permissions=permission_cabinet_edit, obj=cabinet.get_root(), + user=self.request.user, raise_404=True ) return cabinet @@ -81,7 +81,9 @@ class CabinetChildAddView(SingleObjectCreateView): class CabinetDeleteView(SingleObjectDeleteView): model = Cabinet object_permission = permission_cabinet_delete - post_action_redirect = reverse_lazy('cabinets:cabinet_list') + object_permission_raise_404 = True + pk_url_kwarg = 'cabinet_pk' + post_action_redirect = reverse_lazy(viewname='cabinets:cabinet_list') def get_extra_context(self): return { @@ -95,8 +97,9 @@ class CabinetDetailView(DocumentListView): def get_document_queryset(self): queryset = AccessControlList.objects.filter_by_access( - permission=permission_document_view, user=self.request.user, - queryset=self.get_object().documents.all() + permission=permission_document_view, + queryset=self.get_object().documents.all(), + user=self.request.user ) return queryset @@ -133,7 +136,9 @@ class CabinetDetailView(DocumentListView): return context def get_object(self): - cabinet = get_object_or_404(klass=Cabinet, pk=self.kwargs['pk']) + cabinet = get_object_or_404( + klass=Cabinet, pk=self.kwargs['cabinet_pk'] + ) if cabinet.is_root_node(): permission_object = cabinet @@ -141,8 +146,8 @@ class CabinetDetailView(DocumentListView): permission_object = cabinet.get_root() AccessControlList.objects.check_access( - permissions=permission_cabinet_view, user=self.request.user, - obj=permission_object + permissions=permission_cabinet_view, obj=permission_object, + user=self.request.user, raise_404=True ) return cabinet @@ -152,7 +157,9 @@ class CabinetEditView(SingleObjectEditView): fields = ('label',) model = Cabinet object_permission = permission_cabinet_edit - post_action_redirect = reverse_lazy('cabinets:cabinet_list') + object_permission_raise_404 = True + pk_url_kwarg = 'cabinet_pk' + post_action_redirect = reverse_lazy(viewname='cabinets:cabinet_list') def get_extra_context(self): return { @@ -188,11 +195,13 @@ class CabinetListView(SingleObjectListView): class DocumentCabinetListView(CabinetListView): def dispatch(self, request, *args, **kwargs): - self.document = get_object_or_404(klass=Document, pk=self.kwargs['pk']) + self.document = get_object_or_404( + klass=Document, pk=self.kwargs['document_pk'] + ) AccessControlList.objects.check_access( permissions=permission_document_view, user=request.user, - obj=self.document + obj=self.document, raise_404=True ) return super(DocumentCabinetListView, self).dispatch( @@ -203,7 +212,7 @@ class DocumentCabinetListView(CabinetListView): return { 'hide_link': True, 'no_results_icon': icon_cabinet, - 'no_results_main_link': link_cabinet_add_document.resolve( + 'no_results_main_link': link_document_cabinet_add.resolve( context=RequestContext( request=self.request, dict_={'object': self.document} ) @@ -226,6 +235,7 @@ class DocumentAddToCabinetView(MultipleObjectFormActionView): form_class = CabinetListForm model = Document object_permission = permission_cabinet_add_document + pk_url_kwarg = 'document_pk' success_message = _( 'Add to cabinet request performed on %(count)d document' ) @@ -286,11 +296,11 @@ class DocumentAddToCabinetView(MultipleObjectFormActionView): for cabinet in form.cleaned_data['cabinets']: AccessControlList.objects.check_access( obj=cabinet, permissions=permission_cabinet_add_document, - user=self.request.user + user=self.request.user, raise_404=True ) if cabinet in cabinet_membership: messages.warning( - self.request, _( + request=self.request, message=_( 'Document: %(document)s is already in ' 'cabinet: %(cabinet)s.' ) % { @@ -302,7 +312,7 @@ class DocumentAddToCabinetView(MultipleObjectFormActionView): document=instance, user=self.request.user ) messages.success( - self.request, _( + request=self.request, message=_( 'Document: %(document)s added to cabinet: ' '%(cabinet)s successfully.' ) % { @@ -315,6 +325,7 @@ class DocumentRemoveFromCabinetView(MultipleObjectFormActionView): form_class = CabinetListForm model = Document object_permission = permission_cabinet_remove_document + pk_url_kwarg = 'document_pk' success_message = _( 'Remove from cabinet request performed on %(count)d document' ) @@ -373,12 +384,12 @@ class DocumentRemoveFromCabinetView(MultipleObjectFormActionView): for cabinet in form.cleaned_data['cabinets']: AccessControlList.objects.check_access( obj=cabinet, permissions=permission_cabinet_remove_document, - user=self.request.user + user=self.request.user, raise_404=True ) if cabinet not in cabinet_membership: messages.warning( - self.request, _( + request=self.request, message=_( 'Document: %(document)s is not in cabinet: ' '%(cabinet)s.' ) % { @@ -390,7 +401,7 @@ class DocumentRemoveFromCabinetView(MultipleObjectFormActionView): document=instance, user=self.request.user ) messages.success( - self.request, _( + request=self.request, message=_( 'Document: %(document)s removed from cabinet: ' '%(cabinet)s.' ) % { diff --git a/mayan/apps/cabinets/wizard_steps.py b/mayan/apps/cabinets/wizard_steps.py index b211661ff1..5f409480b4 100644 --- a/mayan/apps/cabinets/wizard_steps.py +++ b/mayan/apps/cabinets/wizard_steps.py @@ -28,7 +28,7 @@ class WizardStepCabinets(WizardStep): @classmethod def done(cls, wizard): result = {} - cleaned_data = wizard.get_cleaned_data_for_step(cls.name) + cleaned_data = wizard.get_cleaned_data_for_step(step=cls.name) if cleaned_data: result['cabinets'] = [ force_text(cabinet.pk) for cabinet in cleaned_data['cabinets']