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']