Backport common mixin and generics improvements

* Rename get_object_list to get_source_queryset.
* Add uniqueness validation to SingleObjectCreateView.
* Remove MultipleInstanceActionMixin.
* Backport MultipleObjectMixin improvements.
* Remove ObjectListPermissionFilterMixin.
* Add and improve tests.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2019-05-06 02:07:35 -04:00
parent 7181852c2d
commit 95a1df8072
72 changed files with 1330 additions and 1092 deletions

View File

@@ -235,6 +235,11 @@
workflow proxy instance menu list.
* Fix translation of the source upload forms
using dropzone.js
* Rename get_object_list to get_source_queryset.
* Add uniqueness validation to SingleObjectCreateView.
* Remove MultipleInstanceActionMixin.
* Backport MultipleObjectMixin improvements.
* Remove ObjectListPermissionFilterMixin.
3.1.11 (2019-04-XX)
===================

View File

@@ -268,6 +268,11 @@ Other changes
workflow proxy instance menu list.
* Fix translation of the source upload forms
using dropzone.js
* Rename get_object_list to get_source_queryset.
* Add uniqueness validation to SingleObjectCreateView.
* Remove MultipleInstanceActionMixin.
* Backport MultipleObjectMixin improvements.
* Remove ObjectListPermissionFilterMixin.
Removals
--------

View File

@@ -9,7 +9,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.db import models
from django.db.models import CharField, Value as V, Q
from django.db.models import CharField, Value, Q
from django.db.models.functions import Concat
from django.utils.encoding import force_text
from django.utils.translation import ugettext
@@ -60,14 +60,15 @@ class AccessControlListManager(models.Manager):
# id combinations
content_type_object_id_queryset = queryset.annotate(
ct_fk_combination=Concat(
related_field.ct_field, V('-'), related_field.fk_field,
output_field=CharField()
related_field.ct_field, Value('-'),
related_field.fk_field, output_field=CharField()
)
).values('ct_fk_combination')
acl_filter = self.annotate(
ct_fk_combination=Concat(
'content_type', V('-'), 'object_id', output_field=CharField()
'content_type', Value('-'), 'object_id',
output_field=CharField()
)
).filter(
permissions=stored_permission, role__groups__user=user,

View File

@@ -154,7 +154,7 @@ class ACLListView(SingleObjectListView):
'title': _('Access control lists for: %s' % self.content_object),
}
def get_object_list(self):
def get_source_queryset(self):
return AccessControlList.objects.filter(
content_type=self.object_content_type,
object_id=self.content_object.pk

View File

@@ -1,6 +1,7 @@
from __future__ import absolute_import, unicode_literals
from mayan.apps.common.tests import GenericViewTestCase
from mayan.apps.documents.permissions import permission_document_view
from mayan.apps.documents.tests import GenericDocumentViewTestCase
from ..models import Cabinet
@@ -47,7 +48,7 @@ class CabinetViewTestCase(CabinetTestMixin, CabinetViewTestMixin, GenericViewTes
self._create_test_cabinet()
response = self._request_test_cabinet_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Cabinet.objects.count(), 1)
@@ -66,7 +67,7 @@ class CabinetViewTestCase(CabinetTestMixin, CabinetViewTestMixin, GenericViewTes
self._create_test_cabinet()
response = self._request_test_cabinet_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_cabinet.refresh_from_db()
self.assertEqual(self.test_cabinet.label, TEST_CABINET_LABEL)
@@ -84,6 +85,25 @@ class CabinetViewTestCase(CabinetTestMixin, CabinetViewTestMixin, GenericViewTes
self.test_cabinet.refresh_from_db()
self.assertEqual(self.test_cabinet.label, TEST_CABINET_LABEL_EDITED)
def test_cabinet_list_view_no_permission(self):
self._create_test_cabinet()
response = self._request_test_cabinet_list_view()
self.assertNotContains(
response, text=self.test_cabinet.label, status_code=200
)
def test_cabinet_list_view_with_access(self):
self._create_test_cabinet()
self.grant_access(
obj=self.test_cabinet, permission=permission_cabinet_view
)
response = self._request_test_cabinet_list_view()
self.assertContains(
response, text=self.test_cabinet.label, status_code=200
)
class CabinetChildViewTestCase(CabinetTestMixin, CabinetViewTestMixin, GenericViewTestCase):
def setUp(self):
@@ -94,7 +114,7 @@ class CabinetChildViewTestCase(CabinetTestMixin, CabinetViewTestMixin, GenericVi
cabinet_count = Cabinet.objects.count()
response = self._request_test_cabinet_child_create_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Cabinet.objects.count(), cabinet_count)
@@ -115,7 +135,7 @@ class CabinetChildViewTestCase(CabinetTestMixin, CabinetViewTestMixin, GenericVi
cabinet_count = Cabinet.objects.count()
response = self._request_test_cabinet_child_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Cabinet.objects.count(), cabinet_count)
@@ -149,9 +169,7 @@ class CabinetDocumentViewTestCase(CabinetTestMixin, CabinetViewTestMixin, Generi
self.grant_permission(permission=permission_cabinet_view)
response = self._add_document_to_cabinet()
self.assertContains(
response=response, text='Select a valid choice.', status_code=200
)
self.assertEqual(response.status_code, 404)
self.test_cabinet.refresh_from_db()
self.assertEqual(self.test_cabinet.documents.count(), 0)
@@ -184,9 +202,7 @@ class CabinetDocumentViewTestCase(CabinetTestMixin, CabinetViewTestMixin, Generi
self.grant_permission(permission=permission_cabinet_view)
response = self._request_test_document_multiple_cabinet_multiple_add_view_cabinet()
self.assertContains(
response=response, text='Select a valid choice', status_code=200
)
self.assertEqual(response.status_code, 404)
self.test_cabinet.refresh_from_db()
self.assertEqual(self.test_cabinet.documents.count(), 0)
@@ -216,9 +232,7 @@ class CabinetDocumentViewTestCase(CabinetTestMixin, CabinetViewTestMixin, Generi
self.test_cabinet.documents.add(self.test_document)
response = self._request_test_document_cabinet_multiple_remove_view()
self.assertContains(
response=response, text='Select a valid choice', status_code=200
)
self.assertEqual(response.status_code, 404)
self.test_cabinet.refresh_from_db()
self.assertEqual(self.test_cabinet.documents.count(), 1)
@@ -243,21 +257,72 @@ class CabinetDocumentViewTestCase(CabinetTestMixin, CabinetViewTestMixin, Generi
self.test_cabinet.refresh_from_db()
self.assertEqual(self.test_cabinet.documents.count(), 0)
def test_cabinet_list_view_no_permission(self):
self._create_test_cabinet()
response = self._request_test_cabinet_list_view()
self.assertNotContains(
response, text=self.test_cabinet.label, status_code=200
def _request_test_cabinet_document_list_view(self):
return self.get(
viewname='cabinets:cabinet_view', kwargs={
'pk': self.test_cabinet.pk
}
)
def test_cabinet_list_view_with_access(self):
def test_cabinet_document_list_view_no_permission(self):
self._create_test_cabinet()
self.test_cabinet.documents.add(self.test_document)
response = self._request_test_cabinet_document_list_view()
self.assertNotContains(
response, text=self.test_cabinet.label, status_code=404
)
self.assertNotContains(
response, text=self.test_document.label, status_code=404
)
def test_cabinet_document_list_view_with_cabinet_access(self):
self._create_test_cabinet()
self.test_cabinet.documents.add(self.test_document)
self.grant_access(
obj=self.test_cabinet, permission=permission_cabinet_view
)
response = self._request_test_cabinet_list_view()
response = self._request_test_cabinet_document_list_view()
self.assertContains(
response, text=self.test_cabinet.label, status_code=200
)
self.assertNotContains(
response, text=self.test_document.label, status_code=200
)
def test_cabinet_document_list_view_with_document_access(self):
self._create_test_cabinet()
self.test_cabinet.documents.add(self.test_document)
self.grant_access(
obj=self.test_document, permission=permission_document_view
)
response = self._request_test_cabinet_document_list_view()
self.assertNotContains(
response, text=self.test_cabinet.label, status_code=404
)
self.assertNotContains(
response, text=self.test_document.label, status_code=404
)
def test_cabinet_document_list_view_with_full_access(self):
self._create_test_cabinet()
self.test_cabinet.documents.add(self.test_document)
self.grant_access(
obj=self.test_cabinet, permission=permission_cabinet_view
)
self.grant_access(
obj=self.test_document, permission=permission_document_view
)
response = self._request_test_cabinet_document_list_view()
self.assertContains(
response, text=self.test_cabinet.label, status_code=200
)
self.assertContains(
response, text=self.test_document.label, status_code=200
)

View File

@@ -13,6 +13,7 @@ from mayan.apps.common.generics import (
MultipleObjectFormActionView, SingleObjectCreateView,
SingleObjectDeleteView, SingleObjectEditView, SingleObjectListView
)
from mayan.apps.common.mixins import ExternalObjectMixin
from mayan.apps.documents.permissions import permission_document_view
from mayan.apps.documents.models import Document
from mayan.apps.documents.views import DocumentListView
@@ -45,38 +46,25 @@ class CabinetCreateView(SingleObjectCreateView):
}
class CabinetChildAddView(SingleObjectCreateView):
class CabinetChildAddView(ExternalObjectMixin, SingleObjectCreateView):
fields = ('label',)
model = Cabinet
def form_valid(self, form):
"""
If the form is valid, save the associated model.
"""
self.object = form.save(commit=False)
self.object.parent = self.get_object()
self.object.save()
return super(CabinetChildAddView, self).form_valid(form=form)
def get_object(self, *args, **kwargs):
cabinet = super(CabinetChildAddView, self).get_object(*args, **kwargs)
AccessControlList.objects.check_access(
obj=cabinet.get_root(), permissions=(permission_cabinet_edit,),
user=self.request.user
)
return cabinet
external_object_class = Cabinet
external_object_permission = permission_cabinet_edit
def get_extra_context(self):
return {
'title': _(
'Add new level to: %s'
) % self.get_object().get_full_path(),
'object': self.get_object()
) % self.external_object.get_full_path(),
'object': self.external_object
}
def get_queryset(self):
return self.external_object.get_descendants()
def get_save_extra_data(self):
return {'parent': self.external_object}
class CabinetDeleteView(SingleObjectDeleteView):
model = Cabinet
@@ -90,34 +78,34 @@ class CabinetDeleteView(SingleObjectDeleteView):
}
class CabinetDetailView(DocumentListView):
class CabinetDetailView(ExternalObjectMixin, DocumentListView):
external_object_class = Cabinet
external_object_permission = permission_cabinet_view
template_name = 'cabinets/cabinet_details.html'
def get_document_queryset(self):
queryset = AccessControlList.objects.filter_by_access(
permission=permission_document_view,
queryset=self.get_object().documents.all(), user=self.request.user
)
return queryset
return self.external_object.documents.all()
def get_context_data(self, **kwargs):
context = super(CabinetDetailView, self).get_context_data(**kwargs)
cabinet = self.get_object()
context.update(
{
'column_class': 'col-xs-12 col-sm-6 col-md-4 col-lg-3',
'hide_links': True,
'jstree_data': '\n'.join(
jstree_data(node=cabinet.get_root(), selected_node=cabinet)
jstree_data(
node=self.external_object.get_root(),
selected_node=self.external_object
)
),
'list_as_items': True,
'no_results_icon': icon_cabinet,
'no_results_main_link': link_cabinet_child_add.resolve(
context=RequestContext(
request=self.request, dict_={'object': cabinet}
request=self.request, dict_={
'object': self.external_object
}
)
),
'no_results_text': _(
@@ -126,28 +114,15 @@ class CabinetDetailView(DocumentListView):
'select the cabinet view of a document view.'
),
'no_results_title': _('This cabinet level is empty'),
'object': cabinet,
'title': _('Details of cabinet: %s') % cabinet.get_full_path(),
'object': self.external_object,
'title': _(
'Details of cabinet: %s'
) % self.external_object.get_full_path(),
}
)
return context
def get_object(self):
cabinet = get_object_or_404(klass=Cabinet, pk=self.kwargs['pk'])
if cabinet.is_root_node():
permission_object = cabinet
else:
permission_object = cabinet.get_root()
AccessControlList.objects.check_access(
obj=permission_object, permissions=(permission_cabinet_view,),
user=self.request.user
)
return cabinet
class CabinetEditView(SingleObjectEditView):
fields = ('label',)
@@ -182,7 +157,7 @@ class CabinetListView(SingleObjectListView):
'no_results_title': _('No cabinets available'),
}
def get_object_list(self):
def get_source_queryset(self):
# Add explicit ordering of root nodes since the queryset returned
# is not affected by the model's order Meta option.
return Cabinet.objects.root_nodes().order_by('label')
@@ -220,7 +195,7 @@ class DocumentCabinetListView(CabinetListView):
'title': _('Cabinets containing document: %s') % self.document,
}
def get_object_list(self):
def get_source_queryset(self):
return self.document.document_cabinets()

View File

@@ -119,14 +119,11 @@ class DocumentCheckoutViewTestCase(DocumentCheckoutTestMixin, GenericDocumentVie
def test_checkout_detail_view_no_permission(self):
self._check_out_test_document()
self.grant_access(
obj=self.test_document,
permission=permission_document_check_out
)
response = self._request_check_out_detail_view()
self.assertNotContains(
response, text=STATE_LABELS[STATE_CHECKED_OUT], status_code=403
response, text=STATE_LABELS[STATE_CHECKED_OUT], status_code=404
)
def test_checkout_detail_view_with_access(self):

View File

@@ -24,6 +24,64 @@ from .permissions import (
)
class DocumentCheckinView(ConfirmView):
def get_extra_context(self):
document = self.get_object()
context = {
'object': document,
}
if document.get_check_out_info().user != self.request.user:
context['title'] = _(
'You didn\'t originally checked out this document. '
'Forcefully check in the document: %s?'
) % document
else:
context['title'] = _('Check in the document: %s?') % document
return context
def get_object(self):
return get_object_or_404(klass=Document, pk=self.kwargs['pk'])
def get_post_action_redirect(self):
return reverse(
viewname='checkouts:check_out_info', kwargs={
'pk': self.get_object().pk
}
)
def view_action(self):
document = self.get_object()
if document.get_check_out_info().user == self.request.user:
AccessControlList.objects.check_access(
obj=document, permissions=(permission_document_check_in,),
user=self.request.user
)
else:
AccessControlList.objects.check_access(
obj=document,
permissions=(permission_document_check_in_override,),
user=self.request.user
)
try:
document.check_in(user=self.request.user)
except DocumentNotCheckedOut:
messages.error(
message=_('Document has not been checked out.'),
request=self.request
)
else:
messages.success(
message=_(
'Document "%s" checked in successfully.'
) % document, request=self.request
)
class CheckoutDocumentView(SingleObjectCreateView):
form_class = DocumentCheckoutForm
@@ -125,69 +183,8 @@ class CheckoutDetailView(SingleObjectDetailView):
def get_extra_context(self):
return {
'object': self.get_object(),
'object': self.object,
'title': _(
'Check out details for document: %s'
) % self.get_object()
) % self.object
}
def get_object(self):
return get_object_or_404(klass=Document, pk=self.kwargs['pk'])
class DocumentCheckinView(ConfirmView):
def get_extra_context(self):
document = self.get_object()
context = {
'object': document,
}
if document.get_check_out_info().user != self.request.user:
context['title'] = _(
'You didn\'t originally checked out this document. '
'Forcefully check in the document: %s?'
) % document
else:
context['title'] = _('Check in the document: %s?') % document
return context
def get_object(self):
return get_object_or_404(klass=Document, pk=self.kwargs['pk'])
def get_post_action_redirect(self):
return reverse(
viewname='checkouts:check_out_info', kwargs={
'pk': self.get_object().pk
}
)
def view_action(self):
document = self.get_object()
if document.get_check_out_info().user == self.request.user:
AccessControlList.objects.check_access(
obj=document, permissions=(permission_document_check_in,),
user=self.request.user
)
else:
AccessControlList.objects.check_access(
obj=document,
permissions=(permission_document_check_in_override,),
user=self.request.user
)
try:
document.check_in(user=self.request.user)
except DocumentNotCheckedOut:
messages.error(
message=_('Document has not been checked out.'),
request=self.request
)
else:
messages.success(
message=_(
'Document "%s" checked in successfully.'
) % document, request=self.request
)

View File

@@ -1,7 +1,7 @@
from __future__ import absolute_import, unicode_literals
from django.contrib import messages
from django.core.exceptions import ImproperlyConfigured
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.db import transaction
from django.http import HttpResponseRedirect
from django.urls import reverse
@@ -36,7 +36,7 @@ from .literals import (
from .mixins import (
DeleteExtraDataMixin, DynamicFormViewMixin, ExternalObjectMixin,
ExtraContextMixin, FormExtraKwargsMixin, MultipleObjectMixin,
ObjectActionMixin, ObjectListPermissionFilterMixin, ObjectNameMixin,
ObjectActionMixin, ObjectNameMixin,
ObjectPermissionCheckMixin, RedirectionMixin, RestrictedQuerysetMixin,
ViewPermissionCheckMixin
)
@@ -138,7 +138,10 @@ class MultiFormView(DjangoFormView):
return self.forms_invalid(forms=self.forms)
class AddRemoveView(ExternalObjectMixin, ExtraContextMixin, ViewPermissionCheckMixin, RestrictedQuerysetMixin, MultiFormView):
class AddRemoveView(
ExternalObjectMixin, ExtraContextMixin, ViewPermissionCheckMixin,
RestrictedQuerysetMixin, MultiFormView
):
form_classes = {'form_available': ChoiceForm, 'form_added': ChoiceForm}
list_added_help_text = _(
'Select entries to be removed. Hold Control to select multiple '
@@ -384,15 +387,21 @@ class AddRemoveView(ExternalObjectMixin, ExtraContextMixin, ViewPermissionCheckM
)
class ConfirmView(ObjectListPermissionFilterMixin, ObjectPermissionCheckMixin, ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, TemplateView):
class ConfirmView(
RestrictedQuerysetMixin, ViewPermissionCheckMixin, ExtraContextMixin,
RedirectionMixin, TemplateView
):
template_name = 'appearance/generic_confirm.html'
def post(self, request, *args, **kwargs):
self.view_action()
return HttpResponseRedirect(self.get_success_url())
return HttpResponseRedirect(redirect_to=self.get_success_url())
class FormView(ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, FormExtraKwargsMixin, DjangoFormView):
class FormView(
ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin,
FormExtraKwargsMixin, DjangoFormView
):
template_name = 'appearance/generic_form.html'
@@ -400,7 +409,11 @@ class DynamicFormView(DynamicFormViewMixin, FormView):
pass
class MultipleObjectFormActionView(ObjectActionMixin, MultipleObjectMixin, FormExtraKwargsMixin, ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, DjangoFormView):
class MultipleObjectFormActionView(
ExtraContextMixin, ObjectActionMixin, ViewPermissionCheckMixin,
RestrictedQuerysetMixin, MultipleObjectMixin, FormExtraKwargsMixin,
RedirectionMixin, DjangoFormView
):
"""
This view will present a form and upon receiving a POST request will
perform an action on an object or queryset
@@ -413,7 +426,7 @@ class MultipleObjectFormActionView(ObjectActionMixin, MultipleObjectMixin, FormE
if self.__class__.mro()[0].get_queryset != MultipleObjectFormActionView.get_queryset:
raise ImproperlyConfigured(
'%(cls)s is overloading the get_queryset method. Subclasses '
'should implement the get_object_list method instead. ' % {
'should implement the get_source_queryset method instead. ' % {
'cls': self.__class__.__name__
}
)
@@ -428,23 +441,50 @@ class MultipleObjectFormActionView(ObjectActionMixin, MultipleObjectMixin, FormE
try:
return super(MultipleObjectFormActionView, self).get_queryset()
except ImproperlyConfigured:
self.queryset = self.get_object_list()
self.queryset = self.get_source_queryset()
return super(MultipleObjectFormActionView, self).get_queryset()
class MultipleObjectConfirmActionView(ObjectActionMixin, MultipleObjectMixin, ObjectListPermissionFilterMixin, ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, TemplateView):
class MultipleObjectConfirmActionView(
ExtraContextMixin, ObjectActionMixin, ViewPermissionCheckMixin,
RestrictedQuerysetMixin, MultipleObjectMixin, RedirectionMixin, TemplateView
):
template_name = 'appearance/generic_confirm.html'
def __init__(self, *args, **kwargs):
result = super(MultipleObjectConfirmActionView, self).__init__(*args, **kwargs)
if self.__class__.mro()[0].get_queryset != MultipleObjectConfirmActionView.get_queryset:
raise ImproperlyConfigured(
'%(cls)s is overloading the get_queryset method. Subclasses '
'should implement the get_source_queryset method instead. ' % {
'cls': self.__class__.__name__
}
)
return result
def get_queryset(self):
try:
return super(MultipleObjectConfirmActionView, self).get_queryset()
except ImproperlyConfigured:
self.queryset = self.get_source_queryset()
return super(MultipleObjectConfirmActionView, self).get_queryset()
def post(self, request, *args, **kwargs):
self.view_action()
return HttpResponseRedirect(self.get_success_url())
return HttpResponseRedirect(redirect_to=self.get_success_url())
class SimpleView(ViewPermissionCheckMixin, ExtraContextMixin, TemplateView):
pass
class SingleObjectCreateView(ObjectNameMixin, ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, FormExtraKwargsMixin, CreateView):
class SingleObjectCreateView(
ObjectNameMixin, ViewPermissionCheckMixin, ExtraContextMixin,
RedirectionMixin, FormExtraKwargsMixin, CreateView
):
error_message_duplicate = None
template_name = 'appearance/generic_form.html'
def form_valid(self, form):
@@ -461,42 +501,78 @@ class SingleObjectCreateView(ObjectNameMixin, ViewPermissionCheckMixin, ExtraCon
else:
save_extra_data = {}
try:
self.object.validate_unique()
except ValidationError as exception:
context = self.get_context_data()
error_message = self.get_error_message_duplicate() or _(
'Duplicate data error: %(error)s'
) % {
'error': '\n'.join(exception.messages)
}
messages.error(
message=error_message, request=self.request
)
return super(
SingleObjectCreateView, self
).form_invalid(form=form)
try:
self.object.save(**save_extra_data)
except Exception as exception:
context = self.get_context_data()
messages.error(
self.request,
_('%(object)s not created, error: %(error)s') % {
message=_('%(object)s not created, error: %(error)s') % {
'object': self.get_object_name(context=context),
'error': exception
}
}, request=self.request
)
return super(
SingleObjectCreateView, self
).form_invalid(form=form)
else:
context = self.get_context_data()
messages.success(
self.request,
_(
message=_(
'%(object)s created successfully.'
) % {'object': self.get_object_name(context=context)}
) % {'object': self.get_object_name(context=context)},
request=self.request
)
return HttpResponseRedirect(self.get_success_url())
return HttpResponseRedirect(redirect_to=self.get_success_url())
def get_error_message_duplicate(self):
return self.error_message_duplicate
class SingleObjectDynamicFormCreateView(DynamicFormViewMixin, SingleObjectCreateView):
class SingleObjectDynamicFormCreateView(
DynamicFormViewMixin, SingleObjectCreateView
):
pass
class SingleObjectDeleteView(ObjectNameMixin, DeleteExtraDataMixin, ViewPermissionCheckMixin, ObjectPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, DeleteView):
class SingleObjectDeleteView(
ObjectNameMixin, DeleteExtraDataMixin, ViewPermissionCheckMixin,
RestrictedQuerysetMixin, ExtraContextMixin, RedirectionMixin, DeleteView
):
template_name = 'appearance/generic_confirm.html'
def get_context_data(self, **kwargs):
context = super(SingleObjectDeleteView, self).get_context_data(**kwargs)
context.update({'delete_view': True})
return context
def __init__(self, *args, **kwargs):
result = super(SingleObjectDeleteView, self).__init__(*args, **kwargs)
if self.__class__.mro()[0].get_queryset != SingleObjectDeleteView.get_queryset:
raise ImproperlyConfigured(
'%(cls)s is overloading the get_queryset method. Subclasses '
'should implement the get_source_queryset method instead. ' % {
'cls': self.__class__.__name__
}
)
return result
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
@@ -507,40 +583,77 @@ class SingleObjectDeleteView(ObjectNameMixin, DeleteExtraDataMixin, ViewPermissi
result = super(SingleObjectDeleteView, self).delete(request, *args, **kwargs)
except Exception as exception:
messages.error(
self.request,
_('%(object)s not deleted, error: %(error)s.') % {
message=_('%(object)s not deleted, error: %(error)s.') % {
'object': object_name,
'error': exception
}
}, request=self.request
)
raise exception
else:
messages.success(
self.request,
_(
message=_(
'%(object)s deleted successfully.'
) % {'object': object_name}
) % {'object': object_name},
request=self.request
)
return result
def get_context_data(self, **kwargs):
context = super(SingleObjectDeleteView, self).get_context_data(**kwargs)
context.update({'delete_view': True})
return context
class SingleObjectDetailView(ViewPermissionCheckMixin, ObjectPermissionCheckMixin, FormExtraKwargsMixin, ExtraContextMixin, ModelFormMixin, DetailView):
def get_queryset(self):
try:
return super(SingleObjectDeleteView, self).get_queryset()
except ImproperlyConfigured:
self.queryset = self.get_source_queryset()
return super(SingleObjectDeleteView, self).get_queryset()
class SingleObjectDetailView(
ViewPermissionCheckMixin, RestrictedQuerysetMixin, FormExtraKwargsMixin,
ExtraContextMixin, ModelFormMixin, DetailView
):
template_name = 'appearance/generic_form.html'
def __init__(self, *args, **kwargs):
result = super(SingleObjectDetailView, self).__init__(*args, **kwargs)
if self.__class__.mro()[0].get_queryset != SingleObjectDetailView.get_queryset:
raise ImproperlyConfigured(
'%(cls)s is overloading the get_queryset method. Subclasses '
'should implement the get_source_queryset method instead. ' % {
'cls': self.__class__.__name__
}
)
return result
def get_context_data(self, **kwargs):
context = super(SingleObjectDetailView, self).get_context_data(**kwargs)
context.update({'read_only': True, 'form': self.get_form()})
return context
def get_queryset(self):
try:
return super(SingleObjectDetailView, self).get_queryset()
except ImproperlyConfigured:
self.queryset = self.get_source_queryset()
return super(SingleObjectDetailView, self).get_queryset()
class SingleObjectDownloadView(ViewPermissionCheckMixin, ObjectPermissionCheckMixin, VirtualDownloadView, SingleObjectMixin):
TextIteratorIO = TextIteratorIO
VirtualFile = VirtualFile
class SingleObjectEditView(ObjectNameMixin, ViewPermissionCheckMixin, ObjectPermissionCheckMixin, ExtraContextMixin, FormExtraKwargsMixin, RedirectionMixin, UpdateView):
class SingleObjectEditView(
ObjectNameMixin, ViewPermissionCheckMixin, RestrictedQuerysetMixin,
ExtraContextMixin, FormExtraKwargsMixin, RedirectionMixin, UpdateView
):
template_name = 'appearance/generic_form.html'
def form_valid(self, form):
@@ -564,23 +677,22 @@ class SingleObjectEditView(ObjectNameMixin, ViewPermissionCheckMixin, ObjectPerm
self.object.save(**save_extra_data)
except Exception as exception:
messages.error(
self.request,
_('%(object)s not updated, error: %(error)s.') % {
message=_('%(object)s not updated, error: %(error)s.') % {
'object': object_name,
'error': exception
}
}, request=self.request
)
raise exception
return super(
SingleObjectEditView, self
).form_invalid(form=form)
else:
messages.success(
self.request,
_(
message=_(
'%(object)s updated successfully.'
) % {'object': object_name}
) % {'object': object_name}, request=self.request
)
return HttpResponseRedirect(self.get_success_url())
return HttpResponseRedirect(redirect_to=self.get_success_url())
def get_object(self, queryset=None):
obj = super(SingleObjectEditView, self).get_object(queryset=queryset)
@@ -592,11 +704,16 @@ class SingleObjectEditView(ObjectNameMixin, ViewPermissionCheckMixin, ObjectPerm
return obj
class SingleObjectDynamicFormEditView(DynamicFormViewMixin, SingleObjectEditView):
class SingleObjectDynamicFormEditView(
DynamicFormViewMixin, SingleObjectEditView
):
pass
class SingleObjectListView(PaginationMixin, ViewPermissionCheckMixin, ObjectListPermissionFilterMixin, ExtraContextMixin, RedirectionMixin, ListView):
class SingleObjectListView(
PaginationMixin, ViewPermissionCheckMixin, RestrictedQuerysetMixin,
ExtraContextMixin, RedirectionMixin, ListView
):
template_name = 'appearance/generic_list.html'
def __init__(self, *args, **kwargs):
@@ -605,7 +722,7 @@ class SingleObjectListView(PaginationMixin, ViewPermissionCheckMixin, ObjectList
if self.__class__.mro()[0].get_queryset != SingleObjectListView.get_queryset:
raise ImproperlyConfigured(
'%(cls)s is overloading the get_queryset method. Subclasses '
'should implement the get_object_list method instead. ' % {
'should implement the get_source_queryset method instead. ' % {
'cls': self.__class__.__name__
}
)
@@ -631,7 +748,7 @@ class SingleObjectListView(PaginationMixin, ViewPermissionCheckMixin, ObjectList
try:
queryset = super(SingleObjectListView, self).get_queryset()
except ImproperlyConfigured:
self.queryset = self.get_object_list()
self.queryset = self.get_source_queryset()
queryset = super(SingleObjectListView, self).get_queryset()
self.field_name = self.get_sort_field()

View File

@@ -5,11 +5,14 @@ from django.utils.translation import ugettext_lazy as _
DEFAULT_COMMON_HOME_VIEW = 'common:home'
DELETE_STALE_UPLOADS_INTERVAL = 60 * 10 # 10 minutes
DJANGO_SQLITE_BACKEND = 'django.db.backends.sqlite3'
MESSAGE_SQLITE_WARNING = _(
'Your database backend is set to use SQLite. SQLite should only be used '
'for development and testing, not for production.'
)
PK_LIST_SEPARATOR = ','
TEXT_SORT_FIELD_PARAMETER = '_sort_field'
TEXT_SORT_FIELD_VARIABLE_NAME = 'sort_field'
TEXT_SORT_ORDER_CHOICE_ASCENDING = 'asc'

View File

@@ -3,27 +3,23 @@ from __future__ import unicode_literals
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.db.models.query import QuerySet
from django.http import HttpResponseRedirect
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, resolve_url
from django.utils.translation import ungettext, ugettext_lazy as _
from django.views.generic.detail import SingleObjectMixin
from mayan.apps.acls.models import AccessControlList
from mayan.apps.permissions import Permission
from .exceptions import ActionError
from .forms import DynamicForm
__all__ = (
'DeleteExtraDataMixin', 'DynamicFormViewMixin', 'ExtraContextMixin',
'FormExtraKwargsMixin', 'MultipleObjectMixin', 'ObjectActionMixin',
'ObjectListPermissionFilterMixin', 'ObjectNameMixin',
'ObjectPermissionCheckMixin', 'RedirectionMixin',
'ViewPermissionCheckMixin'
)
from .literals import PK_LIST_SEPARATOR
class DeleteExtraDataMixin(object):
"""
Mixin to populate the extra data needed for delete views
"""
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
success_url = self.get_success_url()
@@ -44,7 +40,28 @@ class DynamicFormViewMixin(object):
return data
class ExtraContextMixin(object):
"""
Mixin that allows views to pass extra context to the template much easier
than overloading .get_context_data().
"""
extra_context = {}
def get_extra_context(self):
return self.extra_context
def get_context_data(self, **kwargs):
context = super(ExtraContextMixin, self).get_context_data(**kwargs)
context.update(self.get_extra_context())
return context
class ExternalObjectMixin(object):
"""
Mixin to allow views to load an object with minimal code but with all
the filtering and configurability possible. This object is often use as
the main or master object in multi object views.
"""
external_object_class = None
external_object_permission = None
external_object_pk_url_kwarg = 'pk'
@@ -100,21 +117,6 @@ class ExternalObjectMixin(object):
return queryset
class ExtraContextMixin(object):
"""
Mixin that allows views to pass extra context to the template
"""
extra_context = {}
def get_extra_context(self):
return self.extra_context
def get_context_data(self, **kwargs):
context = super(ExtraContextMixin, self).get_context_data(**kwargs)
context.update(self.get_extra_context())
return context
class FormExtraKwargsMixin(object):
"""
Mixin that allows a view to pass extra keyword arguments to forms
@@ -130,62 +132,103 @@ class FormExtraKwargsMixin(object):
return result
class MultipleInstanceActionMixin(object):
# TODO: Deprecated, replace views using this with
# MultipleObjectFormActionView or MultipleObjectConfirmActionView
class MultipleObjectMixin(SingleObjectMixin):
"""
Mixin that allows a view to work on a single or multiple objects. It can
receive a pk, a slug or a list of IDs via an id_list query.
The pk, slug, and ID list parameter name can be changed using the
attributes: pk_url_kwargs, slug_url_kwarg, and pk_list_key.
"""
pk_list_key = 'id_list'
pk_list_separator = PK_LIST_SEPARATOR
model = None
success_message = _('Operation performed on %(count)d object')
success_message_plural = _('Operation performed on %(count)d objects')
def dispatch(self, request, *args, **kwargs):
self.object_list = self.get_object_list()
if self.view_mode_single:
self.object = self.object_list.first()
def get_pk_list(self):
return self.request.GET.get(
'id_list', self.request.POST.get('id_list', '')
).split(',')
return super(MultipleObjectMixin, self).dispatch(request=request, *args, **kwargs)
def get_queryset(self):
return self.model.objects.filter(pk__in=self.get_pk_list())
def get(self, request, *args, **kwargs):
"""
Override BaseDetailView.get()
"""
return super(SingleObjectMixin, self).get(request, *args, **kwargs)
def get_success_message(self, count):
return ungettext(
self.success_message,
self.success_message_plural,
count
) % {
'count': count,
}
def get_context_data(self, **kwargs):
"""
Override SingleObjectMixin.get_context_data()
"""
return super(SingleObjectMixin, self).get_context_data(**kwargs)
def post(self, request, *args, **kwargs):
count = 0
for instance in self.get_queryset():
try:
self.object_action(instance=instance)
except PermissionDenied:
pass
else:
count += 1
def get_object(self):
"""
Remove this method from the subclass
"""
raise AttributeError
messages.success(
self.request,
self.get_success_message(count=count)
def get_object_list(self, queryset=None):
"""
Returns the list of objects the view is displaying.
By default this requires `self.queryset` and a `pk`, `slug` ro
`pk_list' argument in the URLconf, but subclasses can override this
to return any object.
"""
self.view_mode_single = False
self.view_mode_multiple = False
# Use a custom queryset if provided; this is required for subclasses
# like DateDetailView
if queryset is None:
queryset = self.get_queryset()
# Next, try looking up by primary key.
pk = self.kwargs.get(self.pk_url_kwarg)
slug = self.kwargs.get(self.slug_url_kwarg)
pk_list = self.get_pk_list()
if pk is not None:
queryset = queryset.filter(pk=pk)
self.view_mode_single = True
# Next, try looking up by slug.
if slug is not None and (pk is None or self.query_pk_and_slug):
slug_field = self.get_slug_field()
queryset = queryset.filter(**{slug_field: slug})
self.view_mode_single = True
if pk_list is not None:
queryset = queryset.filter(pk__in=self.get_pk_list())
self.view_mode_multiple = True
# If none of those are defined, it's an error.
if pk is None and slug is None and pk_list is None:
raise AttributeError(
'View %s must be called with '
'either an object pk, a slug or an pk list.'
% self.__class__.__name__
)
return HttpResponseRedirect(self.get_success_url())
class MultipleObjectMixin(object):
"""
Mixin that allows a view to work on a single or multiple objects
"""
model = None
object_permission = None
pk_list_key = 'id_list'
pk_list_separator = ','
pk_url_kwarg = 'pk'
queryset = None
slug_url_kwarg = 'slug'
try:
# Get the single item from the filtered queryset
queryset.get()
except queryset.model.MultipleObjectsReturned:
# Queryset has more than one item, this is good.
return queryset
except queryset.model.DoesNotExist:
raise Http404(
_('No %(verbose_name)s found matching the query') %
{'verbose_name': queryset.model._meta.verbose_name}
)
else:
# Queryset has one item, this is good.
return queryset
def get_pk_list(self):
# Accept pk_list even on POST request to allowing direct requests
# to the view bypassing the initial GET request to submit the form.
# Example: when the view is called from a test or a custom UI
result = self.request.GET.get(
self.pk_list_key, self.request.POST.get(self.pk_list_key)
)
@@ -195,43 +238,6 @@ class MultipleObjectMixin(object):
else:
return None
def get_queryset(self):
if self.queryset is not None:
queryset = self.queryset
if isinstance(queryset, QuerySet):
queryset = queryset.all()
elif self.model is not None:
queryset = self.model._default_manager.all()
pk = self.kwargs.get(self.pk_url_kwarg)
slug = self.kwargs.get(self.slug_url_kwarg)
pk_list = self.get_pk_list()
if pk is not None:
queryset = queryset.filter(pk=pk)
# Next, try looking up by slug.
if slug is not None and (pk is None or self.query_pk_and_slug):
slug_field = self.get_slug_field()
queryset = queryset.filter(**{slug_field: slug})
if pk_list is not None:
queryset = queryset.filter(pk__in=self.get_pk_list())
if pk is None and slug is None and pk_list is None:
raise AttributeError(
'Generic detail view %s must be called with '
'either an object pk, a slug or an id list.'
% self.__class__.__name__
)
if self.object_permission:
return AccessControlList.objects.filter_by_access(
self.object_permission, self.request.user, queryset=queryset
)
else:
return queryset
class ObjectActionMixin(object):
"""
@@ -275,34 +281,6 @@ class ObjectActionMixin(object):
)
class ObjectListPermissionFilterMixin(object):
"""
access_object_retrieve_method is have the entire view check against
an object permission and not the individual secondary items.
"""
access_object_retrieve_method = None
object_permission = None
def dispatch(self, request, *args, **kwargs):
if self.access_object_retrieve_method and self.object_permission:
AccessControlList.objects.check_access(
obj=getattr(self, self.access_object_retrieve_method)(),
permissions=(self.object_permission,), user=request.user
)
return super(ObjectListPermissionFilterMixin, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
queryset = super(ObjectListPermissionFilterMixin, self).get_queryset()
if not self.access_object_retrieve_method and self.object_permission:
return AccessControlList.objects.filter_by_access(
queryset=queryset, permission=self.object_permission,
user=self.request.user
)
else:
return queryset
class ObjectNameMixin(object):
def get_object_name(self, context=None):
if not context:
@@ -319,6 +297,7 @@ class ObjectNameMixin(object):
return object_name
# TODO: Remove this mixin and replace with restricted queryset
class ObjectPermissionCheckMixin(object):
object_permission = None
@@ -425,6 +404,12 @@ class RestrictedQuerysetMixin(object):
class ViewPermissionCheckMixin(object):
"""
Restrict access to the view based on the user's direct permissions from
roles. This mixing is used for views whose objects don't support ACLs or
for views that perform actions that are not related to a specify object or
object's permission like maintenance views.
"""
view_permission = None
def dispatch(self, request, *args, **kwargs):

View File

@@ -174,7 +174,7 @@ class ObjectErrorLogEntryListView(SingleObjectListView):
klass=content_type.model_class(), pk=self.kwargs['object_id']
)
def get_object_list(self):
def get_source_queryset(self):
return self.get_object().error_logs.all()

View File

@@ -232,5 +232,5 @@ class TransformationListView(SingleObjectListView):
'title': _('Transformations for: %s') % self.content_object,
}
def get_object_list(self):
def get_source_queryset(self):
return Transformation.objects.get_for_object(obj=self.content_object)

View File

@@ -49,7 +49,7 @@ class DependencyGroupEntryListView(SingleObjectListView):
'title': _('Entries for dependency group: %s') % self.get_object(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_object().get_entries()
def get_object(self):
@@ -75,7 +75,7 @@ class DependencyGroupListView(SingleObjectListView):
'title': _('Dependency groups'),
}
def get_object_list(self):
def get_source_queryset(self):
return DependencyGroup.get_all()
@@ -121,7 +121,7 @@ class DependencyGroupEntryDetailView(SingleObjectListView):
]
)
def get_object_list(self):
def get_source_queryset(self):
return self.get_dependency_group_entry().get_dependencies()

View File

@@ -112,7 +112,7 @@ class KeyQueryResultView(SingleObjectListView):
'title': _('Key query results'),
}
def get_object_list(self):
def get_source_queryset(self):
term = self.request.GET.get('term')
if term:
return Key.objects.search(query=term)
@@ -156,7 +156,7 @@ class KeyUploadView(SingleObjectCreateView):
class PrivateKeyListView(SingleObjectListView):
object_permission = permission_key_view
queryset = Key.objects.private_keys()
source_queryset = Key.objects.private_keys()
def get_extra_context(self):
return {
@@ -179,7 +179,7 @@ class PrivateKeyListView(SingleObjectListView):
class PublicKeyListView(SingleObjectListView):
object_permission = permission_key_view
queryset = Key.objects.public_keys()
source_queryset = Key.objects.public_keys()
def get_extra_context(self):
return {

View File

@@ -118,7 +118,7 @@ class DocumentCommentListView(SingleObjectListView):
'title': _('Comments for document: %s') % self.get_document(),
}
def get_object_list(self):
def get_source_queryset(self):
AccessControlList.objects.check_access(
obj=self.get_document(), permissions=(permission_comment_view,),
user=self.request.user

View File

@@ -96,6 +96,13 @@ class DocumentIndexingApp(MayanAppConfig):
permission_document_indexing_view,
)
)
ModelPermission.register_inheritance(
model=IndexTemplateNode, related='index'
)
ModelPermission.register_inheritance(
model=IndexInstanceNode, related='index_template_node__index'
)
SourceColumn(
attribute='label', is_identifier=True, is_sortable=True,

View File

@@ -36,7 +36,7 @@ class IndexViewTestCase(IndexTestMixin, IndexViewTestMixin, GenericDocumentViewT
self._create_test_index()
response = self._request_test_index_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Index.objects.count(), 1)
@@ -54,7 +54,7 @@ class IndexViewTestCase(IndexTestMixin, IndexViewTestMixin, GenericDocumentViewT
self._create_test_index()
response = self._request_test_index_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_index.refresh_from_db()
self.assertEqual(self.test_index.label, TEST_INDEX_LABEL)

View File

@@ -191,7 +191,7 @@ class SetupIndexTreeTemplateListView(SingleObjectListView):
def get_index(self):
return get_object_or_404(klass=Index, pk=self.kwargs['pk'])
def get_object_list(self):
def get_source_queryset(self):
return self.get_index().template_root.get_descendants(
include_self=True
)
@@ -231,7 +231,6 @@ class TemplateNodeCreateView(SingleObjectCreateView):
class TemplateNodeDeleteView(SingleObjectDeleteView):
model = IndexTemplateNode
object_permission = permission_document_indexing_edit
object_permission_related = 'index'
def get_extra_context(self):
return {
@@ -255,7 +254,6 @@ class TemplateNodeEditView(SingleObjectEditView):
form_class = IndexTemplateNodeForm
model = IndexTemplateNode
object_permission = permission_document_indexing_edit
object_permission_related = 'index'
def get_extra_context(self):
return {
@@ -294,7 +292,7 @@ class IndexListView(SingleObjectListView):
'title': _('Indexes'),
}
def get_object_list(self):
def get_source_queryset(self):
queryset = IndexInstance.objects.filter(enabled=True)
return queryset.filter(
node_templates__index_instance_nodes__isnull=False
@@ -355,10 +353,10 @@ class IndexInstanceNodeView(DocumentListView):
return context
def get_object_list(self):
def get_source_queryset(self):
if self.index_instance_node:
if self.index_instance_node.index_template_node.link_documents:
return super(IndexInstanceNodeView, self).get_object_list()
return super(IndexInstanceNodeView, self).get_source_queryset()
else:
self.object_permission = None
return self.index_instance_node.get_children().order_by(
@@ -374,7 +372,6 @@ class DocumentIndexNodeListView(SingleObjectListView):
Show a list of indexes where the current document can be found
"""
object_permission = permission_document_indexing_instance_view
object_permission_related = 'index'
def dispatch(self, request, *args, **kwargs):
AccessControlList.objects.check_access(
@@ -407,7 +404,7 @@ class DocumentIndexNodeListView(SingleObjectListView):
) % self.get_document(),
}
def get_object_list(self):
def get_source_queryset(self):
return DocumentIndexInstanceNode.objects.get_for(
document=self.get_document()
)

View File

@@ -30,7 +30,7 @@ class DocumentContentViewsTestCase(GenericDocumentViewTestCase):
def test_document_content_view_no_permissions(self):
response = self._request_document_content_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_content_view_with_access(self):
self.grant_access(
@@ -51,7 +51,7 @@ class DocumentContentViewsTestCase(GenericDocumentViewTestCase):
def test_document_page_content_view_no_permissions(self):
response = self._request_document_page_content_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_page_content_view_with_access(self):
self.grant_access(
@@ -96,7 +96,7 @@ class DocumentContentViewsTestCase(GenericDocumentViewTestCase):
def test_document_type_parsing_settings_view_no_permission(self):
response = self._request_test_document_type_parsing_settings()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_type_parsing_settings_view_with_access(self):
self.grant_access(

View File

@@ -10,6 +10,7 @@ from mayan.apps.common.generics import (
FormView, MultipleObjectConfirmActionView, SingleObjectDetailView,
SingleObjectDownloadView, SingleObjectEditView, SingleObjectListView
)
from mayan.apps.common.mixins import ExternalObjectMixin
from mayan.apps.documents.forms import DocumentTypeFilteredSelectForm
from mayan.apps.documents.models import Document, DocumentPage, DocumentType
@@ -93,7 +94,7 @@ class DocumentParsingErrorsListView(SingleObjectListView):
) % self.get_document(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_document().latest_version.parsing_errors.all()
@@ -136,19 +137,21 @@ class DocumentSubmitView(MultipleObjectConfirmActionView):
instance.submit_for_parsing()
class DocumentTypeSettingsEditView(SingleObjectEditView):
class DocumentTypeSettingsEditView(ExternalObjectMixin, SingleObjectEditView):
external_object_class = DocumentType
external_object_permission = permission_document_type_parsing_setup
external_object_pk_url_kwarg = 'pk'
fields = ('auto_parsing',)
object_permission = permission_document_type_parsing_setup
post_action_redirect = reverse_lazy('documents:document_type_list')
post_action_redirect = reverse_lazy(viewname='documents:document_type_list')
def get_document_type(self):
return get_object_or_404(klass=DocumentType, pk=self.kwargs['pk'])
return self.external_object
def get_extra_context(self):
return {
'object': self.get_document_type(),
'title': _(
'Edit parsing settings for document type: %s'
'Edit parsing settings for document type: %s.'
) % self.get_document_type()
}
@@ -195,5 +198,5 @@ class ParseErrorListView(SingleObjectListView):
}
view_permission = permission_document_type_parsing_setup
def get_object_list(self):
def get_source_queryset(self):
return DocumentVersionParseError.objects.all()

View File

@@ -79,7 +79,7 @@ class SignaturesViewTestCase(SignaturesTestMixin, GenericDocumentViewTestCase):
self._create_test_detached_signature()
response = self._request_document_version_signature_details_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_signature_detail_view_with_access(self):
self._create_test_key()
@@ -186,7 +186,7 @@ class SignaturesViewTestCase(SignaturesTestMixin, GenericDocumentViewTestCase):
)
response = self._request_document_version_signature_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(DetachedSignature.objects.count(), 1)
def test_signature_delete_view_with_access(self):

View File

@@ -232,7 +232,6 @@ class DocumentVersionEmbeddedSignatureCreateView(FormView):
class DocumentVersionSignatureDeleteView(SingleObjectDeleteView):
model = DetachedSignature
object_permission = permission_document_version_signature_delete
object_permission_related = 'document_version.document'
def get_extra_context(self):
return {
@@ -251,7 +250,6 @@ class DocumentVersionSignatureDeleteView(SingleObjectDeleteView):
class DocumentVersionSignatureDetailView(SingleObjectDetailView):
form_class = DocumentVersionSignatureDetailForm
object_permission = permission_document_version_signature_view
object_permission_related = 'document_version.document'
def get_extra_context(self):
return {
@@ -263,14 +261,13 @@ class DocumentVersionSignatureDetailView(SingleObjectDetailView):
) % self.get_object(),
}
def get_queryset(self):
def get_source_queryset(self):
return SignatureBaseModel.objects.select_subclasses()
class DocumentVersionSignatureDownloadView(SingleObjectDownloadView):
model = DetachedSignature
object_permission = permission_document_version_signature_download
object_permission_related = 'document_version.document'
def get_file(self):
signature = self.get_object()
@@ -335,7 +332,7 @@ class DocumentVersionSignatureListView(SingleObjectListView):
) % self.get_document_version(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_document_version().signatures.all()

View File

@@ -54,7 +54,7 @@ class WorkflowViewTestCase(WorkflowTestMixin, GenericViewTestCase):
self._create_test_workflow()
response = self._request_workflow_delete_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.assertTrue(self.test_workflow in Workflow.objects.all())
@@ -84,7 +84,7 @@ class WorkflowViewTestCase(WorkflowTestMixin, GenericViewTestCase):
self._create_test_workflow()
response = self._request_workflow_edit_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.test_workflow.refresh_from_db()
self.assertEqual(self.test_workflow.label, TEST_WORKFLOW_LABEL)
@@ -137,7 +137,7 @@ class WorkflowViewTestCase(WorkflowTestMixin, GenericViewTestCase):
self._create_test_workflow()
response = self._request_workflow_preview_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.assertTrue(self.test_workflow in Workflow.objects.all())
@@ -169,7 +169,7 @@ class WorkflowStateViewTestCase(WorkflowTestMixin, GenericViewTestCase):
self._create_test_workflow()
response = self._request_workflow_state_create_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.assertEquals(WorkflowState.objects.count(), 0)
@@ -223,7 +223,7 @@ class WorkflowStateViewTestCase(WorkflowTestMixin, GenericViewTestCase):
self._create_test_workflow_states()
response = self._request_workflow_state_delete_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.assertEquals(WorkflowState.objects.count(), 2)
@@ -254,7 +254,7 @@ class WorkflowStateViewTestCase(WorkflowTestMixin, GenericViewTestCase):
workflow_state_label = self.test_workflow_state_1.label
response = self._request_workflow_state_edit_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.test_workflow_state_1.refresh_from_db()
self.assertEquals(
@@ -290,7 +290,7 @@ class WorkflowStateViewTestCase(WorkflowTestMixin, GenericViewTestCase):
self._create_test_workflow_states()
response = self._request_workflow_state_list_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
def test_workflow_state_list_with_access(self):
self._create_test_workflow()
@@ -357,7 +357,7 @@ class WorkflowTransitionViewTestCase(WorkflowTestMixin, GenericDocumentViewTestC
self._create_test_workflow_states()
response = self._request_workflow_transition_create_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.assertEquals(WorkflowTransition.objects.count(), 0)
@@ -392,13 +392,13 @@ class WorkflowTransitionViewTestCase(WorkflowTestMixin, GenericDocumentViewTestC
kwargs={'pk': self.test_workflow_transition.pk}
)
def test_delete_workflow_transition_no_access(self):
def test_delete_workflow_transition_no_permissions(self):
self._create_test_workflow()
self._create_test_workflow_states()
self._create_test_workflow_transition()
response = self._request_workflow_transition_delete_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.assertTrue(
self.test_workflow_transition in WorkflowTransition.objects.all()
@@ -434,7 +434,7 @@ class WorkflowTransitionViewTestCase(WorkflowTestMixin, GenericDocumentViewTestC
self._create_test_workflow_transition()
response = self._request_workflow_transition_edit_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
self.test_workflow_transition.refresh_from_db()
self.assertEqual(
@@ -471,9 +471,10 @@ class WorkflowTransitionViewTestCase(WorkflowTestMixin, GenericDocumentViewTestC
self._create_test_workflow_transition()
response = self._request_workflow_transition_list_view()
self.assertEquals(response.status_code, 200)
self.assertNotContains(response, text=self.test_workflow_transition.label)
self.assertNotContains(
response=response, text=self.test_workflow_transition.label,
status_code=404
)
def test_workflow_transition_list_with_access(self):
self._create_test_workflow()
@@ -485,8 +486,10 @@ class WorkflowTransitionViewTestCase(WorkflowTestMixin, GenericDocumentViewTestC
)
response = self._request_workflow_transition_list_view()
self.assertEquals(response.status_code, 200)
self.assertContains(response, text=self.test_workflow_transition.label)
self.assertContains(
response=response, text=self.test_workflow_transition.label,
status_code=200
)
def _request_workflow_transition(self):
return self.post(
@@ -510,6 +513,7 @@ class WorkflowTransitionViewTestCase(WorkflowTestMixin, GenericDocumentViewTestC
response = self._request_workflow_transition()
self.assertEqual(response.status_code, 200)
# Workflow should remain in the same initial state
self.assertEqual(
self.test_workflow_instance.get_current_state(),
@@ -574,7 +578,7 @@ class WorkflowTransitionEventViewTestCase(WorkflowTestMixin, GenericDocumentView
self._create_test_workflow_transition()
response = self._request_workflow_transition_event_list_view()
self.assertEquals(response.status_code, 403)
self.assertEquals(response.status_code, 404)
def test_workflow_transition_event_list_with_access(self):
self._create_test_workflow()

View File

@@ -51,7 +51,7 @@ class DocumentWorkflowInstanceListView(SingleObjectListView):
) % self.get_document(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_document().workflows.all()
@@ -77,7 +77,7 @@ class WorkflowInstanceDetailView(SingleObjectListView):
'workflow_instance': self.get_workflow_instance(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_workflow_instance().log_entries.order_by('-datetime')
def get_workflow_instance(self):

View File

@@ -75,7 +75,7 @@ class WorkflowListView(SingleObjectListView):
'title': _('Workflows'),
}
def get_object_list(self):
def get_source_queryset(self):
return WorkflowRuntimeProxy.objects.all()
@@ -148,7 +148,7 @@ class WorkflowStateListView(SingleObjectListView):
'title': _('States of workflow: %s') % self.get_workflow()
}
def get_object_list(self):
def get_source_queryset(self):
return WorkflowStateRuntimeProxy.objects.filter(
workflow=self.get_workflow()
)

View File

@@ -3,20 +3,19 @@ from __future__ import absolute_import, unicode_literals
from django.contrib import messages
from django.core.files.base import ContentFile
from django.db import transaction
from django.db.utils import IntegrityError
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.template import RequestContext
from django.urls import reverse, reverse_lazy
from django.utils.translation import ugettext_lazy as _
from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.generics import (
AddRemoveView, ConfirmView, FormView, SingleObjectCreateView,
SingleObjectDeleteView, SingleObjectDetailView,
SingleObjectDynamicFormCreateView, SingleObjectDynamicFormEditView,
SingleObjectDownloadView, SingleObjectEditView, SingleObjectListView
)
from mayan.apps.common.mixins import ExternalObjectMixin
from mayan.apps.documents.events import event_document_type_edited
from mayan.apps.documents.models import DocumentType
from mayan.apps.documents.permissions import permission_document_type_edit
@@ -366,7 +365,7 @@ class SetupWorkflowStateActionListView(SingleObjectListView):
def get_form_schema(self):
return {'fields': self.get_class().fields}
def get_object_list(self):
def get_source_queryset(self):
return self.get_workflow_state().actions.all()
def get_workflow_state(self):
@@ -403,7 +402,10 @@ class SetupWorkflowStateActionSelectionView(FormView):
# Workflow states
class SetupWorkflowStateCreateView(SingleObjectCreateView):
class SetupWorkflowStateCreateView(ExternalObjectMixin, SingleObjectCreateView):
external_object_class = Workflow
external_object_permission = permission_workflow_edit
external_object_pk_url_kwarg = 'pk'
form_class = WorkflowStateForm
def get_extra_context(self):
@@ -414,34 +416,26 @@ class SetupWorkflowStateCreateView(SingleObjectCreateView):
) % self.get_workflow()
}
def get_object_list(self):
def get_instance_extra_data(self):
return {'workflow': self.get_workflow()}
def get_source_queryset(self):
return self.get_workflow().states.all()
def get_success_url(self):
return reverse(
viewname='document_states:setup_workflow_state_list', kwargs={
'pk': self.kwargs['pk']
}
viewname='document_states:setup_workflow_state_list',
kwargs={'pk': self.kwargs['pk']}
)
def get_workflow(self):
workflow = get_object_or_404(klass=Workflow, pk=self.kwargs['pk'])
AccessControlList.objects.check_access(
obj=workflow, permissions=(permission_workflow_edit,),
user=self.request.user
)
return workflow
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.workflow = self.get_workflow()
self.object.save()
return super(SetupWorkflowStateCreateView, self).form_valid(form)
return self.get_external_object()
class SetupWorkflowStateDeleteView(SingleObjectDeleteView):
model = WorkflowState
object_permission = permission_workflow_edit
pk_url_kwarg = 'pk'
def get_extra_context(self):
return {
@@ -450,28 +444,18 @@ class SetupWorkflowStateDeleteView(SingleObjectDeleteView):
'workflow_instance': self.get_object().workflow,
}
def get_object_list(self):
return self.get_workflow().states.all()
def get_success_url(self):
return reverse(
viewname='document_states:setup_workflow_state_list',
kwargs={'pk': self.get_object().workflow.pk}
)
def get_workflow(self):
workflow = get_object_or_404(klass=Workflow, pk=self.kwargs['pk'])
AccessControlList.objects.check_access(
obj=workflow, permissions=(permission_workflow_edit,),
user=self.request.user
)
return workflow
class SetupWorkflowStateEditView(SingleObjectEditView):
form_class = WorkflowStateForm
model = WorkflowState
object_permission = permission_workflow_edit
pk_url_kwarg = 'pk'
def get_extra_context(self):
return {
@@ -487,27 +471,19 @@ class SetupWorkflowStateEditView(SingleObjectEditView):
)
class SetupWorkflowStateListView(SingleObjectListView):
class SetupWorkflowStateListView(ExternalObjectMixin, SingleObjectListView):
external_object_class = Workflow
external_object_permission = permission_workflow_view
external_object_pk_url_kwarg = 'pk'
object_permission = permission_workflow_view
def dispatch(self, request, *args, **kwargs):
AccessControlList.objects.check_access(
obj=self.get_workflow(), permissions=(permission_workflow_view,),
user=request.user
)
return super(
SetupWorkflowStateListView, self
).dispatch(request, *args, **kwargs)
def get_extra_context(self):
return {
'hide_link': True,
'hide_object': True,
'no_results_icon': icon_workflow_state,
'no_results_main_link': link_setup_workflow_state_create.resolve(
context=RequestContext(
request=self.request, dict_={'object': self.get_workflow()}
self.request, {'object': self.get_workflow()}
)
),
'no_results_text': _(
@@ -520,35 +496,22 @@ class SetupWorkflowStateListView(SingleObjectListView):
'title': _('States of workflow: %s') % self.get_workflow()
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_workflow().states.all()
def get_workflow(self):
return get_object_or_404(klass=Workflow, pk=self.kwargs['pk'])
return self.get_external_object()
# Transitions
class SetupWorkflowTransitionCreateView(SingleObjectCreateView):
class SetupWorkflowTransitionCreateView(ExternalObjectMixin, SingleObjectCreateView):
external_object_class = Workflow
external_object_permission = permission_workflow_edit
external_object_pk_url_kwarg = 'pk'
form_class = WorkflowTransitionForm
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.workflow = self.get_workflow()
try:
self.object.save()
except IntegrityError:
messages.error(
message=_('Unable to save transition; integrity error.'),
request=self.request
)
return super(
SetupWorkflowTransitionCreateView, self
).form_invalid(form)
else:
return HttpResponseRedirect(self.get_success_url())
def get_extra_context(self):
return {
'object': self.get_workflow(),
@@ -564,7 +527,10 @@ class SetupWorkflowTransitionCreateView(SingleObjectCreateView):
kwargs['workflow'] = self.get_workflow()
return kwargs
def get_object_list(self):
def get_instance_extra_data(self):
return {'workflow': self.get_workflow()}
def get_source_queryset(self):
return self.get_workflow().transitions.all()
def get_success_url(self):
@@ -574,17 +540,13 @@ class SetupWorkflowTransitionCreateView(SingleObjectCreateView):
)
def get_workflow(self):
workflow = get_object_or_404(klass=Workflow, pk=self.kwargs['pk'])
AccessControlList.objects.check_access(
obj=workflow, permissions=(permission_workflow_edit,),
user=self.request.user
)
return workflow
return self.get_external_object()
class SetupWorkflowTransitionDeleteView(SingleObjectDeleteView):
model = WorkflowTransition
object_permission = permission_workflow_edit
pk_url_kwarg = 'pk'
def get_extra_context(self):
return {
@@ -604,6 +566,7 @@ class SetupWorkflowTransitionEditView(SingleObjectEditView):
form_class = WorkflowTransitionForm
model = WorkflowTransition
object_permission = permission_workflow_edit
pk_url_kwarg = 'pk'
def get_extra_context(self):
return {
@@ -626,17 +589,19 @@ class SetupWorkflowTransitionEditView(SingleObjectEditView):
)
class SetupWorkflowTransitionListView(SingleObjectListView):
class SetupWorkflowTransitionListView(ExternalObjectMixin, SingleObjectListView):
external_object_class = Workflow
external_object_permission = permission_workflow_view
external_object_pk_url_kwarg = 'pk'
object_permission = permission_workflow_view
def get_extra_context(self):
return {
'hide_link': True,
'hide_object': True,
'no_results_icon': icon_workflow_transition,
'no_results_main_link': link_setup_workflow_transition_create.resolve(
context=RequestContext(
request=self.request, dict_={'object': self.get_workflow()}
self.request, {'object': self.get_workflow()}
)
),
'no_results_text': _(
@@ -652,24 +617,20 @@ class SetupWorkflowTransitionListView(SingleObjectListView):
) % self.get_workflow()
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_workflow().transitions.all()
def get_workflow(self):
return get_object_or_404(klass=Workflow, pk=self.kwargs['pk'])
return self.get_external_object()
class SetupWorkflowTransitionTriggerEventListView(FormView):
class SetupWorkflowTransitionTriggerEventListView(ExternalObjectMixin, FormView):
external_object_class = WorkflowTransition
external_object_permission = permission_workflow_edit
external_object_pk_url_kwarg = 'pk'
form_class = WorkflowTransitionTriggerEventRelationshipFormSet
submodel = StoredEventType
def dispatch(self, *args, **kwargs):
AccessControlList.objects.check_access(
obj=self.get_object().workflow,
permissions=(permission_workflow_edit,),
user=self.request.user
)
EventType.refresh()
return super(
SetupWorkflowTransitionTriggerEventListView, self
@@ -684,6 +645,7 @@ class SetupWorkflowTransitionTriggerEventListView(FormView):
message=_(
'Error updating workflow transition trigger events; %s'
) % exception, request=self.request
)
else:
messages.success(
@@ -697,7 +659,7 @@ class SetupWorkflowTransitionTriggerEventListView(FormView):
).form_valid(form=form)
def get_object(self):
return get_object_or_404(klass=WorkflowTransition, pk=self.kwargs['pk'])
return self.get_external_object()
def get_extra_context(self):
return {

View File

@@ -56,7 +56,7 @@ class DocumentTypeViewsTestCase(GenericDocumentViewTestCase):
def test_document_type_delete_view_no_permission(self):
response = self._request_document_type_delete()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(DocumentType.objects.count(), 1)
@@ -84,7 +84,7 @@ class DocumentTypeViewsTestCase(GenericDocumentViewTestCase):
def test_document_type_edit_view_no_permission(self):
response = self._request_document_type_edit()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_document_type.refresh_from_db()
self.assertEqual(
@@ -123,7 +123,7 @@ class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, Gener
)
response = self._request_quick_label_create()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(self.test_document_type.filenames.count(), 0)
@@ -146,7 +146,7 @@ class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, Gener
def test_document_type_quick_label_delete_no_access(self):
self._create_test_quick_label()
response = self._request_quick_label_delete()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(
self.test_document_type.filenames.count(), 1
@@ -178,7 +178,7 @@ class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, Gener
self._create_test_quick_label()
response = self._request_quick_label_edit()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_document_type_filename.refresh_from_db()
self.assertEqual(
@@ -212,7 +212,7 @@ class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, Gener
self._create_test_quick_label()
response = self._request_quick_label_list_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_type_quick_label_list_with_access(self):
self._create_test_quick_label()

View File

@@ -20,7 +20,7 @@ class DocumentVersionTestCase(DocumentVersionTestMixin, GenericDocumentViewTestC
self._upload_new_version()
response = self._request_document_version_list_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_version_list_with_access(self):
self._upload_new_version()
@@ -46,7 +46,7 @@ class DocumentVersionTestCase(DocumentVersionTestMixin, GenericDocumentViewTestC
response = self._request_document_version_revert_view(
document_version=first_version
)
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(self.document.versions.count(), 2)

View File

@@ -34,7 +34,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
def test_document_view_no_permissions(self):
response = self._request_document_properties_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_view_with_permissions(self):
self.grant_access(
@@ -84,7 +84,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
response = self._request_document_type_edit(
document_type=document_type_2
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(
Document.objects.get(pk=self.test_document.pk).document_type,
@@ -138,7 +138,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
response = self._request_multiple_document_type_edit(
document_type=document_type_2
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(
Document.objects.first().document_type, self.test_document_type
@@ -327,7 +327,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
self.assertEqual(self.test_document.pages.count(), 0)
response = self._request_document_update_page_count_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(self.test_document.pages.count(), 0)
@@ -356,7 +356,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
self.assertEqual(self.test_document.pages.count(), 0)
response = self._request_document_multiple_update_page_count_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(self.test_document.pages.count(), 0)
@@ -397,7 +397,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
)
response = self._request_document_clear_transformations_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertQuerysetEqual(
Transformation.objects.get_for_object(obj=document_page),
@@ -454,7 +454,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
self.grant_permission(permission=permission_document_view)
response = self._request_document_multiple_clear_transformations()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertQuerysetEqual(
Transformation.objects.get_for_object(obj=document_page),
(repr(transformation),)
@@ -578,7 +578,7 @@ class DocumentsQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericD
self._create_test_quick_label()
response = self._request_document_quick_label_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_quick_label_with_access(self):
self._create_test_quick_label()

View File

@@ -66,7 +66,7 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase):
Action.objects.all().delete()
response = self._request_test_document_preview_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(list(Action.objects.any(obj=self.test_document)), [])

View File

@@ -15,7 +15,7 @@ class FavoriteDocumentsTestCase(GenericDocumentViewTestCase):
def test_document_add_to_favorites_view_no_permission(self):
response = self._request_document_add_to_favorites_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(FavoriteDocument.objects.count(), 0)
def test_document_add_to_favorites_view_with_access(self):
@@ -62,7 +62,7 @@ class FavoriteDocumentsTestCase(GenericDocumentViewTestCase):
def test_document_remove_from_favorites_view_no_permission(self):
self._document_add_to_favorites()
response = self._request_document_remove_from_favorites()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(FavoriteDocument.objects.count(), 1)
def test_document_remove_from_favorites_view_with_access(self):

View File

@@ -10,24 +10,25 @@ from .base import GenericDocumentViewTestCase
class TrashedDocumentTestCase(GenericDocumentViewTestCase):
def _request_document_restore_view(self):
return self.post(
def _request_document_restore_get_view(self):
return self.get(
viewname='documents:document_restore', kwargs={
'pk': self.test_document.pk
}
)
def test_document_restore_view_no_permission(self):
def test_document_restore_get_view_no_permission(self):
self.test_document.delete()
self.assertEqual(Document.objects.count(), 0)
response = self._request_document_restore_view()
self.assertEqual(response.status_code, 302)
document_count = Document.objects.count()
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0)
response = self._request_document_restore_get_view()
self.assertEqual(response.status_code, 404)
def test_document_restore_view_with_access(self):
self.assertEqual(Document.objects.count(), document_count)
def test_document_restore_get_view_with_access(self):
self.test_document.delete()
self.assertEqual(Document.objects.count(), 0)
@@ -35,56 +36,118 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
obj=self.test_document, permission=permission_document_restore
)
response = self._request_document_restore_view()
document_count = Document.objects.count()
response = self._request_document_restore_get_view()
self.assertEqual(response.status_code, 200)
self.assertEqual(Document.objects.count(), document_count)
def _request_document_restore_post_view(self):
return self.post(
viewname='documents:document_restore', kwargs={
'pk': self.test_document.pk
}
)
def test_document_restore_post_view_no_permission(self):
self.test_document.delete()
self.assertEqual(Document.objects.count(), 0)
response = self._request_document_restore_post_view()
self.assertEqual(response.status_code, 404)
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0)
def test_document_restore_post_view_with_access(self):
self.test_document.delete()
self.assertEqual(Document.objects.count(), 0)
self.grant_access(
obj=self.test_document, permission=permission_document_restore
)
response = self._request_document_restore_post_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 1)
def _request_document_trash_view(self):
def _request_document_trash_get_view(self):
return self.get(
viewname='documents:document_trash', kwargs={
'pk': self.test_document.pk
}
)
def test_document_trash_get_view_no_permissions(self):
document_count = Document.objects.count()
response = self._request_document_trash_get_view()
self.assertEqual(response.status_code, 404)
self.assertEqual(Document.objects.count(), document_count)
def test_document_trash_get_view_with_access(self):
self.grant_access(
obj=self.test_document, permission=permission_document_trash
)
document_count = Document.objects.count()
response = self._request_document_trash_get_view()
self.assertEqual(response.status_code, 200)
self.assertEqual(Document.objects.count(), document_count)
def _request_document_trash_post_view(self):
return self.post(
viewname='documents:document_trash', kwargs={
'pk': self.test_document.pk
}
)
def test_document_trash_no_permissions(self):
response = self._request_document_trash_view()
self.assertEqual(response.status_code, 302)
def test_document_trash_post_view_no_permissions(self):
response = self._request_document_trash_post_view()
self.assertEqual(response.status_code, 404)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 1)
def test_document_trash_with_access(self):
def test_document_trash_post_view_with_access(self):
self.grant_access(
obj=self.test_document, permission=permission_document_trash
)
response = self._request_document_trash_view()
response = self._request_document_trash_post_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0)
def _request_document_delete_view(self):
return self.post(
def _request_document_delete_get_view(self):
return self.get(
viewname='documents:document_delete', kwargs={
'pk': self.test_document.pk
}
)
def test_document_delete_no_permissions(self):
def test_document_delete_get_view_no_permissions(self):
self.test_document.delete()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
response = self._request_document_delete_view()
self.assertEqual(response.status_code, 302)
trashed_document_count = DeletedDocument.objects.count()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
response = self._request_document_delete_get_view()
self.assertEqual(response.status_code, 404)
def test_document_delete_with_access(self):
self.assertEqual(
DeletedDocument.objects.count(), trashed_document_count
)
def test_document_delete_get_view_with_access(self):
self.test_document.delete()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
@@ -93,7 +156,43 @@ class TrashedDocumentTestCase(GenericDocumentViewTestCase):
obj=self.test_document, permission=permission_document_delete
)
response = self._request_document_delete_view()
trashed_document_count = DeletedDocument.objects.count()
response = self._request_document_delete_get_view()
self.assertEqual(response.status_code, 200)
self.assertEqual(
DeletedDocument.objects.count(), trashed_document_count
)
def _request_document_delete_post_view(self):
return self.post(
viewname='documents:document_delete', kwargs={
'pk': self.test_document.pk
}
)
def test_document_delete_post_view_no_permissions(self):
self.test_document.delete()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
response = self._request_document_delete_post_view()
self.assertEqual(response.status_code, 404)
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
def test_document_delete_post_view_with_access(self):
self.test_document.delete()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
self.grant_access(
obj=self.test_document, permission=permission_document_delete
)
response = self._request_document_delete_post_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(DeletedDocument.objects.count(), 0)

View File

@@ -56,7 +56,7 @@ class DocumentPageListView(SingleObjectListView):
'title': _('Pages for document: %s') % self.get_document(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_document().pages.all()

View File

@@ -7,11 +7,11 @@ from django.template import RequestContext
from django.urls import reverse, reverse_lazy
from django.utils.translation import ugettext_lazy as _
from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.generics import (
SingleObjectCreateView, SingleObjectDeleteView, SingleObjectEditView,
SingleObjectListView
)
from mayan.apps.common.mixins import ExternalObjectMixin
from ..forms import DocumentTypeFilenameForm_create
from ..icons import (
@@ -133,22 +133,14 @@ class DocumentTypeEditView(SingleObjectEditView):
}
class DocumentTypeFilenameCreateView(SingleObjectCreateView):
class DocumentTypeFilenameCreateView(ExternalObjectMixin, SingleObjectCreateView):
external_object_class = DocumentType
external_object_permission = permission_document_type_edit
external_object_pk_url_kwarg = 'pk'
form_class = DocumentTypeFilenameForm_create
def dispatch(self, request, *args, **kwargs):
AccessControlList.objects.check_access(
obj=self.get_document_type(),
permissions=(permission_document_type_edit,),
user=request.user
)
return super(DocumentTypeFilenameCreateView, self).dispatch(
request, *args, **kwargs
)
def get_document_type(self):
return get_object_or_404(klass=DocumentType, pk=self.kwargs['pk'])
return self.get_external_object()
def get_extra_context(self):
return {
@@ -163,10 +155,37 @@ class DocumentTypeFilenameCreateView(SingleObjectCreateView):
return {'document_type': self.get_document_type()}
class DocumentTypeFilenameDeleteView(SingleObjectDeleteView):
model = DocumentTypeFilename
object_permission = permission_document_type_edit
pk_url_kwarg = 'pk'
def get_extra_context(self):
return {
'document_type': self.get_object().document_type,
'filename': self.get_object(),
'navigation_object_list': ('document_type', 'filename',),
'title': _(
'Delete the quick label: %(label)s, from document type '
'"%(document_type)s"?'
) % {
'document_type': self.get_object().document_type,
'label': self.get_object()
},
}
def get_post_action_redirect(self):
return reverse(
viewname='documents:document_type_filename_list',
kwargs={'pk': self.get_object().document_type.pk}
)
class DocumentTypeFilenameEditView(SingleObjectEditView):
fields = ('enabled', 'filename',)
model = DocumentTypeFilename
object_permission = permission_document_type_edit
pk_url_kwarg = 'pk'
def get_extra_context(self):
document_type_filename = self.get_object()
@@ -186,42 +205,18 @@ class DocumentTypeFilenameEditView(SingleObjectEditView):
def get_post_action_redirect(self):
return reverse(
'documents:document_type_filename_list',
args=(self.get_object().document_type.pk,)
viewname='documents:document_type_filename_list',
kwargs={'pk': self.get_object().document_type.pk}
)
class DocumentTypeFilenameDeleteView(SingleObjectDeleteView):
model = DocumentTypeFilename
object_permission = permission_document_type_edit
def get_extra_context(self):
return {
'document_type': self.get_object().document_type,
'filename': self.get_object(),
'navigation_object_list': ('document_type', 'filename',),
'title': _(
'Delete the quick label: %(label)s, from document type '
'"%(document_type)s"?'
) % {
'document_type': self.get_object().document_type,
'label': self.get_object()
},
}
def get_post_action_redirect(self):
return reverse(
'documents:document_type_filename_list',
args=(self.get_object().document_type.pk,)
)
class DocumentTypeFilenameListView(SingleObjectListView):
access_object_retrieve_method = 'get_document_type'
object_permission = permission_document_type_view
class DocumentTypeFilenameListView(ExternalObjectMixin, SingleObjectListView):
external_object_class = DocumentType
external_object_permission = permission_document_type_view
external_object_pk_url_kwarg = 'pk'
def get_document_type(self):
return get_object_or_404(klass=DocumentType, pk=self.kwargs['pk'])
return self.get_external_object()
def get_extra_context(self):
return {
@@ -251,5 +246,5 @@ class DocumentTypeFilenameListView(SingleObjectListView):
) % self.get_document_type(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_document_type().filenames.all()

View File

@@ -10,6 +10,7 @@ from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.generics import (
ConfirmView, SingleObjectDetailView, SingleObjectListView
)
from mayan.apps.common.mixins import ExternalObjectMixin
from ..events import event_document_view
from ..forms import DocumentVersionDownloadForm, DocumentVersionPreviewForm
@@ -22,71 +23,13 @@ from ..permissions import (
from .document_views import DocumentDownloadFormView, DocumentDownloadView
__all__ = (
'DocumentVersionListView', 'DocumentVersionRevertView',
'DocumentVersionDownloadFormView', 'DocumentVersionDownloadView',
'DocumentVersionListView', 'DocumentVersionRevertView',
'DocumentVersionView'
)
logger = logging.getLogger(__name__)
class DocumentVersionListView(SingleObjectListView):
def dispatch(self, request, *args, **kwargs):
AccessControlList.objects.check_access(
obj=self.get_document(),
permissions=(permission_document_version_view,),
user=request.user
)
self.get_document().add_as_recent_document_for_user(request.user)
return super(
DocumentVersionListView, self
).dispatch(request, *args, **kwargs)
def get_document(self):
return get_object_or_404(klass=Document, pk=self.kwargs['pk'])
def get_extra_context(self):
return {
'hide_object': True,
'list_as_items': True,
'object': self.get_document(),
'title': _('Versions of document: %s') % self.get_document(),
}
def get_object_list(self):
return self.get_document().versions.order_by('-timestamp')
class DocumentVersionRevertView(ConfirmView):
object_permission = permission_document_version_revert
object_permission_related = 'document'
def get_extra_context(self):
return {
'message': _(
'All later version after this one will be deleted too.'
),
'object': self.get_object().document,
'title': _('Revert to this version?'),
}
def get_object(self):
return get_object_or_404(klass=DocumentVersion, pk=self.kwargs['pk'])
def view_action(self):
try:
self.get_object().revert(_user=self.request.user)
messages.success(
self.request, _('Document version reverted successfully')
)
except Exception as exception:
messages.error(
self.request,
_('Error reverting document version; %s') % exception
)
class DocumentVersionDownloadFormView(DocumentDownloadFormView):
form_class = DocumentVersionDownloadForm
model = DocumentVersion
@@ -146,6 +89,61 @@ class DocumentVersionDownloadView(DocumentDownloadView):
return self.get_object().mimetype
class DocumentVersionListView(ExternalObjectMixin, SingleObjectListView):
external_object_class = Document
external_object_permission = permission_document_version_view
external_object_pk_url_kwarg = 'pk'
def get_document(self):
document = self.get_external_object()
document.add_as_recent_document_for_user(user=self.request.user)
return document
def get_extra_context(self):
return {
'hide_object': True,
'list_as_items': True,
'object': self.get_document(),
'table_cell_container_classes': 'td-container-thumbnail',
'title': _('Versions of document: %s') % self.get_document(),
}
def get_source_queryset(self):
return self.get_document().versions.order_by('-timestamp')
class DocumentVersionRevertView(ExternalObjectMixin, ConfirmView):
external_object_class = DocumentVersion
external_object_permission = permission_document_version_revert
external_object_pk_url_kwarg = 'pk'
def get_extra_context(self):
return {
'message': _(
'All later version after this one will be deleted too.'
),
'object': self.get_object().document,
'title': _('Revert to this version?'),
}
def get_object(self):
return self.get_external_object()
def view_action(self):
try:
self.get_object().revert(_user=self.request.user)
messages.success(
message=_(
'Document version reverted successfully'
), request=self.request
)
except Exception as exception:
messages.error(
message=_('Error reverting document version; %s') % exception,
request=self.request
)
class DocumentVersionView(SingleObjectDetailView):
form_class = DocumentVersionPreviewForm
model = DocumentVersion

View File

@@ -95,7 +95,7 @@ class DocumentListView(SingleObjectListView):
'title': _('All documents'),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_document_queryset()
@@ -347,7 +347,7 @@ class DocumentDuplicatesListView(DocumentListView):
)
return context
def get_object_list(self):
def get_source_queryset(self):
try:
return DuplicatedDocument.objects.get(
document=self.get_document()

View File

@@ -41,11 +41,11 @@ class DocumentTrashView(MultipleObjectConfirmActionView):
)
def get_extra_context(self):
queryset = self.get_object_list()
queryset = self.get_queryset()
result = {
'title': ungettext(
single='Move the selected document to the trash?',
singular='Move the selected document to the trash?',
plural='Move the selected documents to the trash?',
number=queryset.count()
)
@@ -72,7 +72,9 @@ class EmptyTrashCanView(ConfirmView):
kwargs={'trashed_document_id': deleted_document.pk}
)
messages.success(self.request, _('Trash emptied successfully'))
messages.success(
message=_('Trash emptied successfully'), request=self.request
)
class TrashedDocumentDeleteView(MultipleObjectConfirmActionView):
@@ -87,11 +89,11 @@ class TrashedDocumentDeleteView(MultipleObjectConfirmActionView):
)
def get_extra_context(self):
queryset = self.get_object_list()
queryset = self.get_queryset()
result = {
'title': ungettext(
single='Delete the selected trashed document?',
singular='Delete the selected trashed document?',
plural='Delete the selected trashed documents?',
number=queryset.count()
)
@@ -147,11 +149,11 @@ class TrashedDocumentRestoreView(MultipleObjectConfirmActionView):
)
def get_extra_context(self):
queryset = self.get_object_list()
queryset = self.get_queryset()
result = {
'title': ungettext(
single='Restore the selected trashed document?',
singular='Restore the selected trashed document?',
plural='Restore the selected trashed documents?',
number=queryset.count()
)

View File

@@ -31,7 +31,7 @@ class ResultsView(SearchModelMixin, SingleObjectListView):
return context
def get_object_list(self):
def get_source_queryset(self):
self.search_model = self.get_search_model()
if self.request.GET:

View File

@@ -36,7 +36,7 @@ class EventListView(SingleObjectListView):
'title': _('Events'),
}
def get_object_list(self):
def get_source_queryset(self):
return Action.objects.all()
@@ -119,7 +119,7 @@ class NotificationListView(SingleObjectListView):
'title': _('Notifications'),
}
def get_object_list(self):
def get_source_queryset(self):
return self.request.user.notifications.all()
@@ -186,7 +186,7 @@ class ObjectEventListView(EventListView):
klass=queryset, pk=self.kwargs['object_id']
)
def get_object_list(self):
def get_source_queryset(self):
return any_stream(self.object)
@@ -281,5 +281,5 @@ class VerbEventListView(SingleObjectListView):
) % EventType.get(name=self.kwargs['verb']),
}
def get_object_list(self):
def get_source_queryset(self):
return Action.objects.filter(verb=self.kwargs['verb'])

View File

@@ -72,7 +72,7 @@ class FileMetadataViewsTestCase(GenericDocumentViewTestCase):
self.document.latest_version.file_metadata_drivers.all().delete()
response = self._request_document_submit_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(
self.document.latest_version.file_metadata_drivers.count(), 0
@@ -103,7 +103,7 @@ class FileMetadataViewsTestCase(GenericDocumentViewTestCase):
self.document.latest_version.file_metadata_drivers.all().delete()
response = self._request_multiple_document_submit_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(
self.document.latest_version.file_metadata_drivers.count(), 0

View File

@@ -47,7 +47,7 @@ class DocumentDriverListView(ExternalObjectMixin, SingleObjectListView):
) % self.external_object,
}
def get_object_list(self):
def get_source_queryset(self):
return self.external_object.latest_version.file_metadata_drivers.all()
@@ -69,7 +69,7 @@ class DocumentVersionDriverEntryFileMetadataListView(ExternalObjectMixin, Single
},
}
def get_object_list(self):
def get_source_queryset(self):
return self.external_object.entries.all()

View File

@@ -39,7 +39,7 @@ class SmartLinkViewTestCase(SmartLinkTestMixin, SmartLinkViewTestMixin, GenericV
self._create_test_smart_link()
response = self._request_test_smart_link_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(SmartLink.objects.count(), 1)
@@ -58,7 +58,7 @@ class SmartLinkViewTestCase(SmartLinkTestMixin, SmartLinkViewTestMixin, GenericV
self._create_test_smart_link()
response = self._request_test_smart_link_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_smart_link.refresh_from_db()
self.assertEqual(self.test_smart_link.label, TEST_SMART_LINK_LABEL)

View File

@@ -197,7 +197,7 @@ class SmartLinkListView(SingleObjectListView):
'title': _('Smart links'),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_smart_link_queryset()
def get_smart_link_queryset(self):
@@ -311,7 +311,7 @@ class SmartLinkConditionListView(SingleObjectListView):
) % self.get_smart_link(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_smart_link().conditions.all()
def get_smart_link(self):

View File

@@ -26,10 +26,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
self._create_test_user_mailer()
response = self._request_test_document_link_send_view()
self.assertContains(
response=response, text='Select a valid choice', status_code=200
)
self.assertEqual(response.status_code, 404)
def test_mail_link_view_with_access(self):
self._create_test_user_mailer()
@@ -41,7 +38,9 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
obj=self.test_user_mailer, permission=permission_user_mailer_use
)
self._request_test_document_link_send_view()
response = self._request_test_document_link_send_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].from_email, TEST_EMAIL_FROM_ADDRESS)
self.assertEqual(mail.outbox[0].to, [TEST_EMAIL_ADDRESS])
@@ -50,9 +49,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
self._create_test_user_mailer()
response = self._request_test_document_send_view()
self.assertContains(
response=response, text='Select a valid choice', status_code=200
)
self.assertEqual(response.status_code, 404)
def test_mail_document_view_with_access(self):
self._create_test_user_mailer()
@@ -64,7 +61,9 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
obj=self.test_user_mailer, permission=permission_user_mailer_use
)
self._request_test_document_send_view()
response = self._request_test_document_send_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].from_email, TEST_EMAIL_FROM_ADDRESS)
self.assertEqual(mail.outbox[0].to, [TEST_EMAIL_ADDRESS])
@@ -92,7 +91,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
self._create_test_user_mailer()
response = self._request_test_user_mailer_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertQuerysetEqual(
UserMailer.objects.all(), (repr(self.test_user_mailer),)
@@ -150,6 +149,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
response = self._request_test_user_mailer_test_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].from_email, TEST_EMAIL_FROM_ADDRESS)
self.assertEqual(mail.outbox[0].to, [TEST_EMAIL_ADDRESS])
@@ -164,6 +164,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_COMMA
response = self._request_test_user_mailer_test_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].from_email, TEST_EMAIL_FROM_ADDRESS)
self.assertEqual(
@@ -180,6 +181,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_MIXED
response = self._request_test_user_mailer_test_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].from_email, TEST_EMAIL_FROM_ADDRESS)
self.assertEqual(
@@ -194,8 +196,10 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_SEMICOLON
response = self._request_test_user_mailer_test_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].from_email, TEST_EMAIL_FROM_ADDRESS)
self.assertEqual(
@@ -213,6 +217,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_COMMA
response = self._request_test_document_link_send_view()
self.assertEqual(response.status_code, 302)
@@ -233,6 +238,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_MIXED
response = self._request_test_document_link_send_view()
self.assertEqual(response.status_code, 302)
@@ -253,6 +259,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_SEMICOLON
response = self._request_test_document_link_send_view()
self.assertEqual(response.status_code, 302)
@@ -273,6 +280,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_COMMA
response = self._request_test_document_send_view()
self.assertEqual(response.status_code, 302)
@@ -293,6 +301,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_MIXED
response = self._request_test_document_send_view()
self.assertEqual(response.status_code, 302)
@@ -313,6 +322,7 @@ class MailerViewsTestCase(MailerTestMixin, MailerViewTestMixin, GenericDocumentV
)
self.test_email_address = TEST_RECIPIENTS_MULTIPLE_SEMICOLON
response = self._request_test_document_send_view()
self.assertEqual(response.status_code, 302)

View File

@@ -211,7 +211,7 @@ class UserMailerLogEntryListView(SingleObjectListView):
'title': _('%s error log') % self.get_user_mailer(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_user_mailer().error_log.all()
def get_user_mailer(self):

View File

@@ -20,7 +20,7 @@ class NamespaceListView(SingleObjectListView):
template_name = 'appearance/generic_list.html'
view_permission = permission_statistics_view
def get_object_list(self):
def get_source_queryset(self):
return StatisticNamespace.get_all()
@@ -37,7 +37,7 @@ class NamespaceDetailView(SingleObjectListView):
def get_namespace(self):
return StatisticNamespace.get(slug=self.kwargs['slug'])
def get_object_list(self):
def get_source_queryset(self):
return self.get_namespace().statistics

View File

@@ -14,8 +14,8 @@ from mayan.apps.rest_api.permissions import MayanPermission
from .models import MetadataType
from .permissions import (
permission_metadata_document_add, permission_metadata_document_remove,
permission_metadata_document_edit, permission_metadata_document_view,
permission_document_metadata_add, permission_document_metadata_remove,
permission_document_metadata_edit, permission_document_metadata_view,
permission_metadata_type_create, permission_metadata_type_delete,
permission_metadata_type_edit, permission_metadata_type_view
)
@@ -34,9 +34,9 @@ class APIDocumentMetadataListView(generics.ListCreateAPIView):
"""
def get_document(self):
if self.request.method == 'GET':
permission_required = permission_metadata_document_view
permission_required = permission_document_metadata_view
else:
permission_required = permission_metadata_document_add
permission_required = permission_document_metadata_add
document = get_object_or_404(
klass=Document, pk=self.kwargs['document_pk']
@@ -90,13 +90,13 @@ class APIDocumentMetadataView(generics.RetrieveUpdateDestroyAPIView):
def get_document(self):
if self.request.method == 'GET':
permission_required = permission_metadata_document_view
permission_required = permission_document_metadata_view
elif self.request.method == 'PUT':
permission_required = permission_metadata_document_edit
permission_required = permission_document_metadata_edit
elif self.request.method == 'PATCH':
permission_required = permission_metadata_document_edit
permission_required = permission_document_metadata_edit
elif self.request.method == 'DELETE':
permission_required = permission_metadata_document_remove
permission_required = permission_document_metadata_remove
document = get_object_or_404(
klass=Document, pk=self.kwargs['document_pk']

View File

@@ -49,8 +49,8 @@ from .links import (
link_setup_metadata_type_edit, link_setup_metadata_type_list,
)
from .permissions import (
permission_metadata_document_add, permission_metadata_document_edit,
permission_metadata_document_remove, permission_metadata_document_view,
permission_document_metadata_add, permission_document_metadata_edit,
permission_document_metadata_remove, permission_document_metadata_view,
permission_metadata_type_delete, permission_metadata_type_edit,
permission_metadata_type_view
)
@@ -139,10 +139,10 @@ class MetadataApp(MayanAppConfig):
ModelPermission.register(
model=Document, permissions=(
permission_metadata_document_add,
permission_metadata_document_edit,
permission_metadata_document_remove,
permission_metadata_document_view,
permission_document_metadata_add,
permission_document_metadata_edit,
permission_document_metadata_remove,
permission_document_metadata_view,
)
)
ModelPermission.register(

View File

@@ -6,8 +6,8 @@ from mayan.apps.documents.permissions import permission_document_type_edit
from mayan.apps.navigation.classes import Link
from .permissions import (
permission_metadata_document_add, permission_metadata_document_edit,
permission_metadata_document_remove, permission_metadata_document_view,
permission_document_metadata_add, permission_document_metadata_edit,
permission_document_metadata_remove, permission_document_metadata_view,
permission_metadata_type_create, permission_metadata_type_delete,
permission_metadata_type_edit, permission_metadata_type_view
)
@@ -15,13 +15,13 @@ from .permissions import (
link_metadata_add = Link(
args='object.pk',
icon_class_path='mayan.apps.metadata.icons.icon_document_metadata_add',
permissions=(permission_metadata_document_add,), text=_('Add metadata'),
permissions=(permission_document_metadata_add,), text=_('Add metadata'),
view='metadata:metadata_add',
)
link_metadata_edit = Link(
args='object.pk',
icon_class_path='mayan.apps.metadata.icons.icon_document_metadata_edit',
permissions=(permission_metadata_document_edit,),
permissions=(permission_document_metadata_edit,),
text=_('Edit metadata'), view='metadata:metadata_edit'
)
link_metadata_multiple_add = Link(
@@ -39,13 +39,13 @@ link_metadata_multiple_remove = Link(
link_metadata_remove = Link(
args='object.pk',
icon_class_path='mayan.apps.metadata.icons.icon_document_metadata_remove',
permissions=(permission_metadata_document_remove,),
permissions=(permission_document_metadata_remove,),
text=_('Remove metadata'), view='metadata:metadata_remove',
)
link_metadata_view = Link(
args='resolved_object.pk',
icon_class_path='mayan.apps.metadata.icons.icon_document_metadata_view',
permissions=(permission_metadata_document_view,), text=_('Metadata'),
permissions=(permission_document_metadata_view,), text=_('Metadata'),
view='metadata:metadata_view',
)
link_setup_document_type_metadata_types = Link(

View File

@@ -6,17 +6,17 @@ from mayan.apps.permissions import PermissionNamespace
namespace = PermissionNamespace(label=_('Metadata'), name='metadata')
permission_metadata_document_edit = namespace.add_permission(
label=_('Edit a document\'s metadata'), name='metadata_document_edit'
)
permission_metadata_document_add = namespace.add_permission(
permission_document_metadata_add = namespace.add_permission(
label=_('Add metadata to a document'), name='metadata_document_add'
)
permission_metadata_document_remove = namespace.add_permission(
permission_document_metadata_edit = namespace.add_permission(
label=_('Edit a document\'s metadata'), name='metadata_document_edit'
)
permission_document_metadata_remove = namespace.add_permission(
label=_('Remove metadata from a document'),
name='metadata_document_remove'
)
permission_metadata_document_view = namespace.add_permission(
permission_document_metadata_view = namespace.add_permission(
label=_('View metadata from a document'), name='metadata_document_view'
)

View File

@@ -11,19 +11,19 @@ from .literals import (
class MetadataTypeTestMixin(object):
def setUp(self):
super(MetadataTypeTestMixin, self).setUp()
self.metadata_type = MetadataType.objects.create(
self.test_metadata_type = MetadataType.objects.create(
name=TEST_METADATA_TYPE_NAME, label=TEST_METADATA_TYPE_LABEL
)
class MetadataTestsMixin(object):
def _create_metadata_type(self):
self.metadata_type = MetadataType.objects.create(
def _create_test_metadata_type(self):
self.test_metadata_type = MetadataType.objects.create(
label=TEST_METADATA_TYPE_LABEL,
name=TEST_METADATA_TYPE_NAME
)
def _request_metadata_type_create_view(self):
def _request_test_metadata_type_create_view(self):
return self.post(
viewname='metadata:setup_metadata_type_create', data={
'label': TEST_METADATA_TYPE_LABEL,
@@ -31,30 +31,30 @@ class MetadataTestsMixin(object):
}
)
def _request_metadata_type_delete_view(self):
def _request_test_metadata_type_delete_view(self):
return self.post(
viewname='metadata:setup_metadata_type_delete', kwargs={
'pk': self.metadata_type.pk
'pk': self.test_metadata_type.pk
}
)
def _request_metadata_type_edit_view(self):
def _request_test_metadata_type_edit_view(self):
return self.post(
viewname='metadata:setup_metadata_type_edit', kwargs={
'pk': self.metadata_type.pk
'pk': self.test_metadata_type.pk
}, data={
'label': TEST_METADATA_TYPE_LABEL_EDITED,
'name': TEST_METADATA_TYPE_NAME_EDITED
}
)
def _request_metadata_type_relationship_edit_view(self):
def _request_test_metadata_type_relationship_edit_view(self):
# This request assumes there is only one document type and
# blindly sets the first form of the formset.
return self.post(
viewname='metadata:setup_metadata_type_document_types',
kwargs={'pk': self.metadata_type.pk}, data={
kwargs={'pk': self.test_metadata_type.pk}, data={
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '0',
'form-0-relationship_type': 'required'

View File

@@ -10,8 +10,8 @@ from mayan.apps.rest_api.tests import BaseAPITestCase
from ..models import DocumentTypeMetadataType, MetadataType
from ..permissions import (
permission_metadata_document_add, permission_metadata_document_edit,
permission_metadata_document_remove, permission_metadata_document_view,
permission_document_metadata_add, permission_document_metadata_edit,
permission_document_metadata_remove, permission_document_metadata_view,
permission_metadata_type_create, permission_metadata_type_delete,
permission_metadata_type_edit, permission_metadata_type_view
)
@@ -24,12 +24,12 @@ from .literals import (
class MetadataTypeAPITestCase(BaseAPITestCase):
def _create_metadata_type(self):
self.metadata_type = MetadataType.objects.create(
def _create_test_metadata_type(self):
self.test_metadata_type = MetadataType.objects.create(
label=TEST_METADATA_TYPE_LABEL, name=TEST_METADATA_TYPE_NAME
)
def _request_metadata_type_create_view(self):
def _request_test_metadata_type_create_view(self):
return self.post(
viewname='rest_api:metadatatype-list', data={
'label': TEST_METADATA_TYPE_LABEL,
@@ -38,13 +38,13 @@ class MetadataTypeAPITestCase(BaseAPITestCase):
)
def test_metadata_type_create_no_permission(self):
response = self._request_metadata_type_create_view()
response = self._request_test_metadata_type_create_view()
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(MetadataType.objects.count(), 0)
def test_metadata_type_create_with_permission(self):
self.grant_permission(permission=permission_metadata_type_create)
response = self._request_metadata_type_create_view()
response = self._request_test_metadata_type_create_view()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
metadata_type = MetadataType.objects.first()
@@ -55,26 +55,26 @@ class MetadataTypeAPITestCase(BaseAPITestCase):
self.assertEqual(metadata_type.label, TEST_METADATA_TYPE_LABEL)
self.assertEqual(metadata_type.name, TEST_METADATA_TYPE_NAME)
def _request_metadata_type_delete_view(self):
def _request_test_metadata_type_delete_view(self):
return self.delete(
viewname='rest_api:metadatatype-detail',
kwargs={'metadata_type_pk': self.metadata_type.pk}
kwargs={'metadata_type_pk': self.test_metadata_type.pk}
)
def test_metadata_type_delete_no_access(self):
self._create_metadata_type()
response = self._request_metadata_type_delete_view()
self._create_test_metadata_type()
response = self._request_test_metadata_type_delete_view()
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(MetadataType.objects.count(), 1)
def test_metadata_type_delete_with_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
self.grant_access(
obj=self.metadata_type, permission=permission_metadata_type_delete
obj=self.test_metadata_type, permission=permission_metadata_type_delete
)
response = self._request_metadata_type_delete_view()
response = self._request_test_metadata_type_delete_view()
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertEqual(MetadataType.objects.count(), 0)
@@ -82,19 +82,19 @@ class MetadataTypeAPITestCase(BaseAPITestCase):
def _request_metadata_type_detail_view(self):
return self.get(
viewname='rest_api:metadatatype-detail',
kwargs={'metadata_type_pk': self.metadata_type.pk}
kwargs={'metadata_type_pk': self.test_metadata_type.pk}
)
def test_metadata_type_detail_view_no_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
response = self._request_metadata_type_detail_view()
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_metadata_type_detail_view_with_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
self.grant_access(
obj=self.metadata_type, permission=permission_metadata_type_view
obj=self.test_metadata_type, permission=permission_metadata_type_view
)
response = self._request_metadata_type_detail_view()
@@ -104,83 +104,83 @@ class MetadataTypeAPITestCase(BaseAPITestCase):
response.data['label'], TEST_METADATA_TYPE_LABEL
)
def _request_metadata_type_edit_view_via_patch(self):
def _request_test_metadata_type_edit_view_via_patch(self):
return self.patch(
viewname='rest_api:metadatatype-detail',
kwargs={'metadata_type_pk': self.metadata_type.pk}, data={
kwargs={'metadata_type_pk': self.test_metadata_type.pk}, data={
'label': TEST_METADATA_TYPE_LABEL_2,
'name': TEST_METADATA_TYPE_NAME_2
}
)
def test_metadata_type_patch_view_no_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
response = self._request_metadata_type_edit_view_via_patch()
response = self._request_test_metadata_type_edit_view_via_patch()
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.metadata_type.refresh_from_db()
self.assertEqual(self.metadata_type.label, TEST_METADATA_TYPE_LABEL)
self.assertEqual(self.metadata_type.name, TEST_METADATA_TYPE_NAME)
self.test_metadata_type.refresh_from_db()
self.assertEqual(self.test_metadata_type.label, TEST_METADATA_TYPE_LABEL)
self.assertEqual(self.test_metadata_type.name, TEST_METADATA_TYPE_NAME)
def test_metadata_type_patch_view_with_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
self.grant_access(
obj=self.metadata_type, permission=permission_metadata_type_edit
obj=self.test_metadata_type, permission=permission_metadata_type_edit
)
response = self._request_metadata_type_edit_view_via_patch()
response = self._request_test_metadata_type_edit_view_via_patch()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.metadata_type.refresh_from_db()
self.assertEqual(self.metadata_type.label, TEST_METADATA_TYPE_LABEL_2)
self.assertEqual(self.metadata_type.name, TEST_METADATA_TYPE_NAME_2)
self.test_metadata_type.refresh_from_db()
self.assertEqual(self.test_metadata_type.label, TEST_METADATA_TYPE_LABEL_2)
self.assertEqual(self.test_metadata_type.name, TEST_METADATA_TYPE_NAME_2)
def _request_metadata_type_edit_view_via_put(self):
def _request_test_metadata_type_edit_view_via_put(self):
return self.put(
viewname='rest_api:metadatatype-detail',
kwargs={'metadata_type_pk': self.metadata_type.pk}, data={
kwargs={'metadata_type_pk': self.test_metadata_type.pk}, data={
'label': TEST_METADATA_TYPE_LABEL_2,
'name': TEST_METADATA_TYPE_NAME_2
}
)
def test_metadata_type_put_view_no_access(self):
self._create_metadata_type()
response = self._request_metadata_type_edit_view_via_put()
self._create_test_metadata_type()
response = self._request_test_metadata_type_edit_view_via_put()
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.metadata_type.refresh_from_db()
self.assertEqual(self.metadata_type.label, TEST_METADATA_TYPE_LABEL)
self.assertEqual(self.metadata_type.name, TEST_METADATA_TYPE_NAME)
self.test_metadata_type.refresh_from_db()
self.assertEqual(self.test_metadata_type.label, TEST_METADATA_TYPE_LABEL)
self.assertEqual(self.test_metadata_type.name, TEST_METADATA_TYPE_NAME)
def test_metadata_type_put_view_with_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
self.grant_access(
obj=self.metadata_type, permission=permission_metadata_type_edit
obj=self.test_metadata_type, permission=permission_metadata_type_edit
)
response = self._request_metadata_type_edit_view_via_put()
response = self._request_test_metadata_type_edit_view_via_put()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.metadata_type.refresh_from_db()
self.assertEqual(self.metadata_type.label, TEST_METADATA_TYPE_LABEL_2)
self.assertEqual(self.metadata_type.name, TEST_METADATA_TYPE_NAME_2)
self.test_metadata_type.refresh_from_db()
self.assertEqual(self.test_metadata_type.label, TEST_METADATA_TYPE_LABEL_2)
self.assertEqual(self.test_metadata_type.name, TEST_METADATA_TYPE_NAME_2)
def _request_metadata_type_list_view(self):
return self.get(viewname='rest_api:metadatatype-list')
def test_metadata_type_list_view_no_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
response = self._request_metadata_type_list_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 0)
def test_metadata_type_list_view_with_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
self.grant_access(
obj=self.metadata_type, permission=permission_metadata_type_view
obj=self.test_metadata_type, permission=permission_metadata_type_view
)
response = self._request_metadata_type_list_view()
@@ -195,20 +195,20 @@ class DocumentTypeMetadataTypeAPITestCase(DocumentTestMixin, BaseAPITestCase):
def setUp(self):
super(DocumentTypeMetadataTypeAPITestCase, self).setUp()
self.metadata_type = MetadataType.objects.create(
self.test_metadata_type = MetadataType.objects.create(
label=TEST_METADATA_TYPE_LABEL, name=TEST_METADATA_TYPE_NAME
)
def _create_document_type_metadata_type(self):
self.test_document_type_metadata_type = self.test_document_type.metadata.create(
metadata_type=self.metadata_type, required=False
metadata_type=self.test_metadata_type, required=False
)
def _request_document_type_metadata_type_create_view(self):
return self.post(
viewname='rest_api:documenttypemetadatatype-list',
kwargs={'document_type_pk': self.test_document_type.pk}, data={
'metadata_type_pk': self.metadata_type.pk, 'required': False
'metadata_type_pk': self.test_metadata_type.pk, 'required': False
}
)
@@ -363,23 +363,23 @@ class DocumentTypeMetadataTypeAPITestCase(DocumentTestMixin, BaseAPITestCase):
class DocumentMetadataAPITestCase(DocumentTestMixin, BaseAPITestCase):
def setUp(self):
super(DocumentMetadataAPITestCase, self).setUp()
self.metadata_type = MetadataType.objects.create(
self.test_metadata_type = MetadataType.objects.create(
label=TEST_METADATA_TYPE_LABEL, name=TEST_METADATA_TYPE_NAME
)
self.test_document_type.metadata.create(
metadata_type=self.metadata_type, required=False
metadata_type=self.test_metadata_type, required=False
)
def _create_document_metadata(self):
self.test_document_metadata = self.test_document.metadata.create(
metadata_type=self.metadata_type, value=TEST_METADATA_VALUE
metadata_type=self.test_metadata_type, value=TEST_METADATA_VALUE
)
def _request_document_metadata_create_view(self):
return self.post(
viewname='rest_api:documentmetadata-list',
kwargs={'document_pk': self.test_document.pk}, data={
'metadata_type_pk': self.metadata_type.pk,
'metadata_type_pk': self.test_metadata_type.pk,
'value': TEST_METADATA_VALUE
}
)
@@ -392,7 +392,7 @@ class DocumentMetadataAPITestCase(DocumentTestMixin, BaseAPITestCase):
def test_document_metadata_create_view_with_access(self):
self.grant_access(
obj=self.test_document, permission=permission_metadata_document_add
obj=self.test_document, permission=permission_document_metadata_add
)
response = self._request_document_metadata_create_view()
@@ -400,21 +400,21 @@ class DocumentMetadataAPITestCase(DocumentTestMixin, BaseAPITestCase):
document_metadata = self.test_document.metadata.first()
self.assertEqual(response.data['id'], document_metadata.pk)
self.assertEqual(document_metadata.metadata_type, self.metadata_type)
self.assertEqual(document_metadata.metadata_type, self.test_metadata_type)
self.assertEqual(document_metadata.value, TEST_METADATA_VALUE)
def test_document_metadata_create_duplicate_view(self):
self._create_document_metadata()
self.grant_permission(permission=permission_metadata_document_add)
self.grant_permission(permission=permission_document_metadata_add)
response = self._request_document_metadata_create_view()
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(list(response.data.keys())[0], 'non_field_errors')
def test_document_metadata_create_invalid_lookup_value_view(self):
self.metadata_type.lookup = 'invalid,lookup,values,on,purpose'
self.metadata_type.save()
self.grant_permission(permission=permission_metadata_document_add)
self.test_metadata_type.lookup = 'invalid,lookup,values,on,purpose'
self.test_metadata_type.save()
self.grant_permission(permission=permission_document_metadata_add)
response = self._request_document_metadata_create_view()
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
@@ -440,7 +440,7 @@ class DocumentMetadataAPITestCase(DocumentTestMixin, BaseAPITestCase):
self._create_document_metadata()
self.grant_access(
obj=self.test_document,
permission=permission_metadata_document_remove
permission=permission_document_metadata_remove
)
response = self._request_document_metadata_delete_view()
@@ -464,7 +464,7 @@ class DocumentMetadataAPITestCase(DocumentTestMixin, BaseAPITestCase):
self._create_document_metadata()
self.grant_access(
obj=self.test_document,
permission=permission_metadata_document_view
permission=permission_document_metadata_view
)
response = self._request_document_metadata_list_view()
@@ -474,7 +474,7 @@ class DocumentMetadataAPITestCase(DocumentTestMixin, BaseAPITestCase):
)
self.assertEqual(
response.data['results'][0]['metadata_type']['id'],
self.metadata_type.pk
self.test_metadata_type.pk
)
self.assertEqual(
response.data['results'][0]['value'], TEST_METADATA_VALUE
@@ -507,7 +507,7 @@ class DocumentMetadataAPITestCase(DocumentTestMixin, BaseAPITestCase):
self._create_document_metadata()
self.grant_access(
obj=self.test_document,
permission=permission_metadata_document_edit
permission=permission_document_metadata_edit
)
response = self._request_document_metadata_edit_view_via_patch()
@@ -545,7 +545,7 @@ class DocumentMetadataAPITestCase(DocumentTestMixin, BaseAPITestCase):
self._create_document_metadata()
self.grant_access(
obj=self.test_document,
permission=permission_metadata_document_edit
permission=permission_document_metadata_edit
)
response = self._request_document_metadata_edit_view_via_put()

View File

@@ -19,7 +19,7 @@ class MetadataTypeEventsTestCase(MetadataTestsMixin, GenericViewTestCase):
def test_metadata_type_create_event_no_permissions(self):
Action.objects.all().delete()
response = self._request_metadata_type_create_view()
response = self._request_test_metadata_type_create_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(Action.objects.count(), 0)
@@ -29,7 +29,7 @@ class MetadataTypeEventsTestCase(MetadataTestsMixin, GenericViewTestCase):
self.grant_permission(permission=permission_metadata_type_create)
response = self._request_metadata_type_create_view()
response = self._request_test_metadata_type_create_view()
self.assertEqual(response.status_code, 302)
event = Action.objects.first()
@@ -41,30 +41,30 @@ class MetadataTypeEventsTestCase(MetadataTestsMixin, GenericViewTestCase):
self.assertEqual(event.verb, event_metadata_type_created.id)
def test_metadata_type_edit_event_no_permissions(self):
self._create_metadata_type()
self._create_test_metadata_type()
Action.objects.all().delete()
response = self._request_metadata_type_edit_view()
self.assertEqual(response.status_code, 403)
response = self._request_test_metadata_type_edit_view()
self.assertEqual(response.status_code, 404)
self.assertEqual(Action.objects.count(), 0)
def test_metadata_type_edit_event_with_access(self):
self._create_metadata_type()
self._create_test_metadata_type()
Action.objects.all().delete()
self.grant_access(
obj=self.metadata_type, permission=permission_metadata_type_edit
obj=self.test_metadata_type, permission=permission_metadata_type_edit
)
response = self._request_metadata_type_edit_view()
response = self._request_test_metadata_type_edit_view()
self.assertEqual(response.status_code, 302)
event = Action.objects.first()
self.assertEqual(event.actor, self._test_case_user)
self.assertEqual(event.target, self.metadata_type)
self.assertEqual(event.target, self.test_metadata_type)
self.assertEqual(event.verb, event_metadata_type_edited.id)

View File

@@ -21,12 +21,12 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
def setUp(self):
super(MetadataTestCase, self).setUp()
self.test_document_type.metadata.create(
metadata_type=self.metadata_type
metadata_type=self.test_metadata_type
)
def test_no_default(self):
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type
document=self.test_document, metadata_type=self.test_metadata_type
)
document_metadata.full_clean()
@@ -35,11 +35,11 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
self.assertEqual(self.test_document.metadata_value_of.test, None)
def test_default(self):
self.metadata_type.default = TEST_DEFAULT_VALUE
self.metadata_type.save()
self.test_metadata_type.default = TEST_DEFAULT_VALUE
self.test_metadata_type.save()
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type
document=self.test_document, metadata_type=self.test_metadata_type
)
document_metadata.full_clean()
@@ -50,11 +50,11 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
)
def test_lookup_with_incorrect_value(self):
self.metadata_type.lookup = TEST_LOOKUP_TEMPLATE
self.metadata_type.save()
self.test_metadata_type.lookup = TEST_LOOKUP_TEMPLATE
self.test_metadata_type.save()
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type,
document=self.test_document, metadata_type=self.test_metadata_type,
value=TEST_INCORRECT_LOOKUP_VALUE
)
@@ -64,11 +64,11 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
document_metadata.save()
def test_lookup_with_correct_value(self):
self.metadata_type.lookup = TEST_LOOKUP_TEMPLATE
self.metadata_type.save()
self.test_metadata_type.lookup = TEST_LOOKUP_TEMPLATE
self.test_metadata_type.save()
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type,
document=self.test_document, metadata_type=self.test_metadata_type,
value=TEST_CORRECT_LOOKUP_VALUE
)
@@ -84,21 +84,21 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
Checks for GitLab issue #250
Empty optional lookup metadata trigger validation error
"""
self.metadata_type.lookup = TEST_LOOKUP_TEMPLATE
self.metadata_type.save()
self.test_metadata_type.lookup = TEST_LOOKUP_TEMPLATE
self.test_metadata_type.save()
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type
document=self.test_document, metadata_type=self.test_metadata_type
)
document_metadata.full_clean()
document_metadata.save()
def test_validation(self):
self.metadata_type.validation = TEST_DATE_VALIDATOR
self.test_metadata_type.validation = TEST_DATE_VALIDATOR
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type,
document=self.test_document, metadata_type=self.test_metadata_type,
value=TEST_INVALID_DATE
)
@@ -115,10 +115,10 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
self.assertEqual(self.test_document.metadata_value_of.test, TEST_VALID_DATE)
def test_parsing(self):
self.metadata_type.parser = TEST_DATE_PARSER
self.test_metadata_type.parser = TEST_DATE_PARSER
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type,
document=self.test_document, metadata_type=self.test_metadata_type,
value=TEST_INVALID_DATE
)
@@ -140,53 +140,53 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
self.test_document_type.metadata.all().delete()
self.assertFalse(
self.metadata_type.get_required_for(self.test_document_type)
self.test_metadata_type.get_required_for(self.test_document_type)
)
self.test_document_type.metadata.create(
metadata_type=self.metadata_type, required=False
metadata_type=self.test_metadata_type, required=False
)
self.assertFalse(
self.metadata_type.get_required_for(self.test_document_type)
self.test_metadata_type.get_required_for(self.test_document_type)
)
self.test_document_type.metadata.all().delete()
self.test_document_type.metadata.create(
metadata_type=self.metadata_type, required=True
metadata_type=self.test_metadata_type, required=True
)
self.assertTrue(
self.metadata_type.get_required_for(self.test_document_type)
self.test_metadata_type.get_required_for(self.test_document_type)
)
def test_unicode_lookup(self):
# Should NOT return a ValidationError, otherwise test fails
self.metadata_type.lookup = '测试1,测试2,test1,test2'
self.metadata_type.save()
self.metadata_type.validate_value(document_type=None, value='测试1')
self.test_metadata_type.lookup = '测试1,测试2,test1,test2'
self.test_metadata_type.save()
self.test_metadata_type.validate_value(document_type=None, value='测试1')
def test_non_unicode_lookup(self):
# Should NOT return a ValidationError, otherwise test fails
self.metadata_type.lookup = 'test1,test2'
self.metadata_type.save()
self.metadata_type.validate_value(document_type=None, value='test1')
self.test_metadata_type.lookup = 'test1,test2'
self.test_metadata_type.save()
self.test_metadata_type.validate_value(document_type=None, value='test1')
def test_add_new_metadata_type_on_document_type_change(self):
"""
When switching document types, add the required metadata of the new
document type, the value to the default of the metadata type.
"""
self.metadata_type.default = TEST_DEFAULT_VALUE
self.metadata_type.save()
self.test_metadata_type.default = TEST_DEFAULT_VALUE
self.test_metadata_type.save()
self.test_document_type_2 = DocumentType.objects.create(
label=TEST_DOCUMENT_TYPE_2_LABEL
)
self.test_document_type_2.metadata.create(
metadata_type=self.metadata_type, required=True
metadata_type=self.test_metadata_type, required=True
)
self.test_document.set_document_type(document_type=self.test_document_type_2)
@@ -202,7 +202,7 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
old and new document types
"""
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type,
document=self.test_document, metadata_type=self.test_metadata_type,
value=TEST_DEFAULT_VALUE
)
@@ -213,7 +213,7 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
label=TEST_DOCUMENT_TYPE_2_LABEL
)
self.test_document_type_2.metadata.create(metadata_type=self.metadata_type)
self.test_document_type_2.metadata.create(metadata_type=self.test_metadata_type)
self.test_document.set_document_type(document_type=self.test_document_type_2)
@@ -222,7 +222,7 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
self.test_document.metadata.first().value, TEST_DEFAULT_VALUE
)
self.assertEqual(
self.test_document.metadata.first().metadata_type, self.metadata_type
self.test_document.metadata.first().metadata_type, self.test_metadata_type
)
def test_delete_metadata_value_on_document_type_change(self):
@@ -231,7 +231,7 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
new document type
"""
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type,
document=self.test_document, metadata_type=self.test_metadata_type,
value=TEST_DEFAULT_VALUE
)
@@ -252,7 +252,7 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
new document type
"""
document_metadata = DocumentMetadata(
document=self.test_document, metadata_type=self.metadata_type,
document=self.test_document, metadata_type=self.test_metadata_type,
value=TEST_DEFAULT_VALUE
)
@@ -264,7 +264,7 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
)
self.test_document_type_2.metadata.create(
metadata_type=self.metadata_type, required=True
metadata_type=self.test_metadata_type, required=True
)
self.test_document.set_document_type(document_type=self.test_document_type_2)
@@ -274,5 +274,5 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
self.test_document.metadata.first().value, TEST_DEFAULT_VALUE
)
self.assertEqual(
self.test_document.metadata.first().metadata_type, self.metadata_type
self.test_document.metadata.first().metadata_type, self.test_metadata_type
)

File diff suppressed because it is too large Load Diff

View File

@@ -31,12 +31,12 @@ class DocumentUploadMetadataTestCase(MetadataTypeTestMixin, GenericDocumentViewT
)
self.test_document_type.metadata.create(
metadata_type=self.metadata_type, required=True
metadata_type=self.test_metadata_type, required=True
)
def test_upload_interactive_with_unicode_metadata(self):
url = furl(reverse('sources:upload_interactive'))
url.args['metadata0_id'] = self.metadata_type.pk
url.args['metadata0_id'] = self.test_metadata_type.pk
url.args['metadata0_value'] = TEST_METADATA_VALUE_UNICODE
self.grant_access(
@@ -61,7 +61,7 @@ class DocumentUploadMetadataTestCase(MetadataTypeTestMixin, GenericDocumentViewT
def test_upload_interactive_with_ampersand_metadata(self):
url = furl(reverse('sources:upload_interactive'))
url.args['metadata0_id'] = self.metadata_type.pk
url.args['metadata0_id'] = self.test_metadata_type.pk
url.args['metadata0_value'] = TEST_METADATA_VALUE_WITH_AMPERSAND
self.grant_access(

View File

@@ -37,8 +37,8 @@ from .links import (
)
from .models import DocumentMetadata, MetadataType
from .permissions import (
permission_metadata_document_add, permission_metadata_document_edit,
permission_metadata_document_remove, permission_metadata_document_view,
permission_document_metadata_add, permission_document_metadata_edit,
permission_document_metadata_remove, permission_document_metadata_view,
permission_metadata_type_create, permission_metadata_type_delete,
permission_metadata_type_edit, permission_metadata_type_view
)
@@ -47,7 +47,7 @@ from .permissions import (
class DocumentMetadataAddView(MultipleObjectFormActionView):
form_class = DocumentAddMetadataForm
model = Document
object_permission = permission_metadata_document_add
object_permission = permission_document_metadata_add
success_message = _('Metadata add request performed on %(count)d document')
success_message_plural = _(
'Metadata add request performed on %(count)d documents'
@@ -213,7 +213,7 @@ class DocumentMetadataAddView(MultipleObjectFormActionView):
class DocumentMetadataEditView(MultipleObjectFormActionView):
form_class = DocumentMetadataFormSet
model = Document
object_permission = permission_metadata_document_edit
object_permission = permission_document_metadata_edit
success_message = _(
'Metadata edit request performed on %(count)d document'
)
@@ -398,7 +398,7 @@ class DocumentMetadataListView(SingleObjectListView):
def dispatch(self, request, *args, **kwargs):
AccessControlList.objects.check_access(
obj=self.get_document(),
permissions=(permission_metadata_document_view,),
permissions=(permission_document_metadata_view,),
user=self.request.user
)
@@ -431,14 +431,14 @@ class DocumentMetadataListView(SingleObjectListView):
'title': _('Metadata for document: %s') % document,
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_document().metadata.all()
class DocumentMetadataRemoveView(MultipleObjectFormActionView):
form_class = DocumentMetadataRemoveFormSet
model = Document
object_permission = permission_metadata_document_remove
object_permission = permission_document_metadata_remove
success_message = _(
'Metadata remove request performed on %(count)d document'
)
@@ -657,7 +657,7 @@ class MetadataTypeListView(SingleObjectListView):
'title': _('Metadata types'),
}
def get_object_list(self):
def get_source_queryset(self):
return MetadataType.objects.all()

View File

@@ -27,7 +27,7 @@ class OCRViewsTestCase(GenericDocumentViewTestCase):
self.test_document.submit_for_ocr()
response = self._request_document_content_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_content_view_with_access(self):
self.test_document.submit_for_ocr()
@@ -51,7 +51,7 @@ class OCRViewsTestCase(GenericDocumentViewTestCase):
self.test_document.submit_for_ocr()
response = self._request_document_page_content_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_page_content_view_with_access(self):
self.test_document.submit_for_ocr()
@@ -73,7 +73,7 @@ class OCRViewsTestCase(GenericDocumentViewTestCase):
def test_document_submit_view_no_permission(self):
response = self._request_document_submit_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(
''.join(self.test_document.latest_version.ocr_content()), ''
@@ -102,7 +102,7 @@ class OCRViewsTestCase(GenericDocumentViewTestCase):
def test_multiple_document_submit_view_no_permission(self):
response = self._request_multiple_document_submit_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(
''.join(self.test_document.latest_version.ocr_content()), ''
@@ -159,7 +159,7 @@ class OCRViewsTestCase(GenericDocumentViewTestCase):
def test_document_type_ocr_settings_view_no_permission(self):
response = self._request_document_type_ocr_settings_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_type_ocr_settings_view_with_access(self):
self.grant_access(

View File

@@ -10,6 +10,7 @@ from mayan.apps.common.generics import (
FormView, MultipleObjectConfirmActionView, SingleObjectDetailView,
SingleObjectDownloadView, SingleObjectEditView, SingleObjectListView
)
from mayan.apps.common.mixins import ExternalObjectMixin
from mayan.apps.documents.forms import DocumentTypeFilteredSelectForm
from mayan.apps.documents.models import Document, DocumentPage, DocumentType
@@ -126,21 +127,23 @@ class DocumentTypeSubmitView(FormView):
return reverse(viewname='common:tools_list')
class DocumentTypeSettingsEditView(SingleObjectEditView):
class DocumentTypeSettingsEditView(ExternalObjectMixin, SingleObjectEditView):
external_object_class = DocumentType
external_object_permission = permission_document_type_ocr_setup
external_object_pk_url_kwarg = 'pk'
fields = ('auto_ocr',)
object_permission = permission_document_type_ocr_setup
post_action_redirect = reverse_lazy(
viewname='documents:document_type_list'
)
def get_document_type(self):
return get_object_or_404(klass=DocumentType, pk=self.kwargs['pk'])
return self.external_object
def get_extra_context(self):
return {
'object': self.get_document_type(),
'title': _(
'Edit OCR settings for document type: %s'
'Edit OCR settings for document type: %s.'
) % self.get_document_type()
}
@@ -155,7 +158,7 @@ class EntryListView(SingleObjectListView):
}
view_permission = permission_document_type_ocr_setup
def get_object_list(self):
def get_source_queryset(self):
return DocumentVersionOCRError.objects.all()
@@ -172,7 +175,7 @@ class DocumentOCRErrorsListView(SingleObjectListView):
'title': _('OCR errors for document: %s') % self.get_document(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_document().latest_version.ocr_errors.all()

View File

@@ -30,10 +30,9 @@ class PermissionAPIViewTestCase(PermissionAPIViewTestMixin, BaseAPITestCase):
class RoleAPIViewTestCase(GroupTestMixin, PermissionTestMixin, RoleAPIViewTestMixin, RoleTestMixin, BaseAPITestCase):
def test_role_create_api_view_no_permission(self):
response = self._request_test_role_create_api_view()
role_count = Role.objects.count()
response = self._request_test_role_create_api_view()
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(Role.objects.count(), role_count)

View File

@@ -36,7 +36,7 @@ class RoleEventsTestCase(RoleTestMixin, RoleViewTestMixin, GenericViewTestCase):
Action.objects.all().delete()
response = self._request_test_role_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Action.objects.count(), 0)
def test_role_edited_event_with_access(self):

View File

@@ -31,13 +31,13 @@ class RoleViewsTestCase(RoleTestMixin, RoleViewTestMixin, GenericViewTestCase):
self.assertEqual(Role.objects.count(), role_count + 1)
def test_role_delete_view_no_access(self):
def test_role_delete_view_no_permission(self):
self._create_test_role()
role_count = Role.objects.count()
response = self._request_test_role_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Role.objects.count(), role_count)
@@ -52,13 +52,13 @@ class RoleViewsTestCase(RoleTestMixin, RoleViewTestMixin, GenericViewTestCase):
self.assertEqual(Role.objects.count(), role_count - 1)
def test_role_edit_view_no_access(self):
def test_role_edit_view_no_permission(self):
self._create_test_role()
role_label = self.test_role.label
response = self._request_test_role_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_role.refresh_from_db()
self.assertEqual(self.test_role.label, role_label)
@@ -75,7 +75,7 @@ class RoleViewsTestCase(RoleTestMixin, RoleViewTestMixin, GenericViewTestCase):
self.test_role.refresh_from_db()
self.assertNotEqual(self.test_role.label, role_label)
def test_role_list_view_no_access(self):
def test_role_list_view_no_permission(self):
self._create_test_role()
response = self._request_test_role_list_view()
@@ -93,7 +93,7 @@ class RoleViewsTestCase(RoleTestMixin, RoleViewTestMixin, GenericViewTestCase):
response=response, text=self.test_role.label, status_code=200
)
def test_role_permissions_view_no_access(self):
def test_role_permissions_view_no_permission(self):
self._create_test_role()
response = self._request_test_role_permissions_view()
@@ -108,7 +108,7 @@ class RoleViewsTestCase(RoleTestMixin, RoleViewTestMixin, GenericViewTestCase):
response = self._request_test_role_permissions_view()
self.assertEqual(response.status_code, 200)
def test_role_groups_view_no_access(self):
def test_role_groups_view_no_permission(self):
self._create_test_role()
response = self._request_test_role_groups_view()
@@ -123,7 +123,7 @@ class RoleViewsTestCase(RoleTestMixin, RoleViewTestMixin, GenericViewTestCase):
class GroupRoleViewTestCase(GroupTestMixin, GroupRoleViewTestMixin, RoleTestMixin, GenericViewTestCase):
def test_group_roles_view_no_access(self):
def test_group_roles_view_no_permission(self):
self._create_test_group()
response = self._request_test_group_roles_view()

View File

@@ -34,7 +34,7 @@ class NamespaceDetailView(SingleObjectListView):
_('Namespace: %s, not found') % self.kwargs['namespace_name']
)
def get_object_list(self):
def get_source_queryset(self):
return self.get_namespace().settings
@@ -45,7 +45,7 @@ class NamespaceListView(SingleObjectListView):
}
view_permission = permission_settings_view
def get_object_list(self):
def get_source_queryset(self):
return Namespace.get_all()

View File

@@ -70,7 +70,7 @@ class SourceLogListView(SingleObjectListView):
'title': _('Log entries for source: %s') % self.get_source(),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_source().logs.all()
def get_source(self):
@@ -592,7 +592,7 @@ class SetupSourceEditView(SingleObjectEditView):
class SetupSourceListView(SingleObjectListView):
queryset = Source.objects.select_subclasses()
source_queryset = Source.objects.select_subclasses()
view_permission = permission_sources_setup_view
def get_extra_context(self):

View File

@@ -44,7 +44,7 @@ class TagEventsTestCase(TagTestMixin, TagViewTestMixin, GenericViewTestCase):
action_count = Action.objects.count()
response = self._request_test_tag_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Action.objects.count(), action_count)

View File

@@ -38,7 +38,7 @@ class TagViewTestCase(TagTestMixin, TagViewTestMixin, GenericViewTestCase):
tag_count = Tag.objects.count()
response = self._request_test_tag_delete_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(Tag.objects.count(), tag_count)
@@ -60,7 +60,7 @@ class TagViewTestCase(TagTestMixin, TagViewTestMixin, GenericViewTestCase):
tag_count = Tag.objects.count()
response = self._request_test_tag_delete_multiple_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(Tag.objects.count(), tag_count)
@@ -82,7 +82,7 @@ class TagViewTestCase(TagTestMixin, TagViewTestMixin, GenericViewTestCase):
tag_label = self.test_tag.label
response = self._request_test_tag_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, tag_label)
@@ -131,9 +131,7 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
self._create_test_tag()
response = self._request_test_document_tag_attach_view()
# Show same view with a warning message that ID XX is not one of the
# available choices.
self.assertEqual(response.status_code, 200)
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
@@ -143,7 +141,7 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
response = self._request_test_document_tag_attach_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
@@ -172,7 +170,7 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
self._create_test_tag()
response = self._request_test_document_multiple_tag_multiple_attach_view()
self.assertEqual(response.status_code, 200)
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
@@ -182,7 +180,7 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
response = self._request_test_document_multiple_tag_multiple_attach_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
@@ -212,7 +210,7 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
self.test_document.tags.add(self.test_tag)
response = self._request_test_document_tag_multiple_remove_view()
self.assertEqual(response.status_code, 200)
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_tag in self.test_document.tags.all())
@@ -223,7 +221,7 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
response = self._request_test_document_tag_multiple_remove_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_tag in self.test_document.tags.all())
@@ -255,7 +253,7 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
self.test_document.tags.add(self.test_tag)
response = self._request_test_document_multiple_tag_remove_view()
self.assertEqual(response.status_code, 200)
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_tag in self.test_document.tags.all())
@@ -266,7 +264,7 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
response = self._request_test_document_multiple_tag_remove_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_tag in self.test_document.tags.all())

View File

@@ -220,7 +220,7 @@ class TagListView(SingleObjectListView):
'title': _('Tags'),
}
def get_object_list(self):
def get_source_queryset(self):
return self.get_tag_queryset()
def get_tag_queryset(self):

View File

@@ -16,7 +16,7 @@ class QueueListView(SingleObjectListView):
}
view_permission = permission_task_view
def get_object_list(self):
def get_source_queryset(self):
return CeleryQueue.all()
@@ -33,7 +33,7 @@ class QueueActiveTaskListView(SingleObjectListView):
def get_object(self):
return CeleryQueue.get(queue_name=self.kwargs['queue_name'])
def get_object_list(self):
def get_source_queryset(self):
try:
return self.get_task_list()
except Exception as exception:

View File

@@ -28,7 +28,8 @@ class GroupEventsViewTestCase(GroupTestMixin, GroupViewTestMixin, UserTestMixin,
)
Action.objects.all().delete()
self._request_test_group_create_view()
response = self._request_test_group_create_view()
self.assertEqual(response.status_code, 302)
action = Action.objects.last()
@@ -43,7 +44,8 @@ class GroupEventsViewTestCase(GroupTestMixin, GroupViewTestMixin, UserTestMixin,
)
Action.objects.all().delete()
self._request_test_group_edit_view()
response = self._request_test_group_edit_view()
self.assertEqual(response.status_code, 302)
action = Action.objects.last()
@@ -58,7 +60,8 @@ class GroupEventsAPITestCase(GroupAPITestMixin, GroupTestMixin, GroupViewTestMix
)
Action.objects.all().delete()
self._request_test_group_create_api_view()
response = self._request_test_group_create_api_view()
self.assertEqual(response.status_code, 201)
action = Action.objects.last()
@@ -76,7 +79,8 @@ class GroupEventsAPITestCase(GroupAPITestMixin, GroupTestMixin, GroupViewTestMix
)
Action.objects.all().delete()
self._request_test_group_edit_patch_api_view()
response = self._request_test_group_edit_patch_api_view()
self.assertEqual(response.status_code, 200)
action = Action.objects.last()
@@ -133,7 +137,8 @@ class UserEventsViewTestCase(UserAPITestMixin, UserTestMixin, UserViewTestMixin,
)
Action.objects.all().delete()
self._request_test_user_create_view()
response = self._request_test_user_create_view()
self.assertEqual(response.status_code, 302)
action = Action.objects.last()
@@ -149,7 +154,8 @@ class UserEventsViewTestCase(UserAPITestMixin, UserTestMixin, UserViewTestMixin,
)
Action.objects.all().delete()
self._request_test_user_edit_view()
response = self._request_test_user_edit_view()
self.assertEqual(response.status_code, 302)
action = Action.objects.last()
@@ -165,7 +171,8 @@ class UserEventsAPITestCase(UserAPITestMixin, UserTestMixin, UserViewTestMixin,
)
Action.objects.all().delete()
self._request_test_user_create_api_view()
response = self._request_test_user_create_api_view()
self.assertEqual(response.status_code, 201)
action = Action.objects.last()
@@ -182,7 +189,8 @@ class UserEventsAPITestCase(UserAPITestMixin, UserTestMixin, UserViewTestMixin,
)
Action.objects.all().delete()
self._request_test_user_edit_patch_api_view()
response = self._request_test_user_edit_patch_api_view()
self.assertEqual(response.status_code, 200)
action = Action.objects.last()

View File

@@ -6,7 +6,7 @@ from django.contrib.auth.models import Group
from mayan.apps.common.tests import GenericViewTestCase
from mayan.apps.documents.tests import GenericDocumentViewTestCase
from mayan.apps.metadata.models import MetadataType
from mayan.apps.metadata.permissions import permission_metadata_document_edit
from mayan.apps.metadata.permissions import permission_document_metadata_edit
from mayan.apps.metadata.tests.literals import (
TEST_METADATA_TYPE_LABEL, TEST_METADATA_TYPE_NAME,
)
@@ -48,7 +48,7 @@ class GroupViewsTestCase(GroupTestMixin, GroupViewTestMixin, UserTestMixin, Gene
group_count = Group.objects.count()
response = self._request_test_group_delete_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(Group.objects.count(), group_count)
@@ -71,7 +71,7 @@ class GroupViewsTestCase(GroupTestMixin, GroupViewTestMixin, UserTestMixin, Gene
group_name = self.test_group.name
response = self._request_test_group_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_group.refresh_from_db()
self.assertEqual(self.test_group.name, group_name)
@@ -173,7 +173,7 @@ class SuperUserViewTestCase(UserTestMixin, UserViewTestMixin, GenericViewTestCas
obj=self.test_superuser, permission=permission_user_delete
)
response = self._request_test_superuser_delete_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(
get_user_model().objects.filter(is_superuser=True).count(),
superuser_count
@@ -228,7 +228,7 @@ class UserViewTestCase(UserTestMixin, UserViewTestMixin, GenericViewTestCase):
user_count = get_user_model().objects.count()
response = self._request_test_user_delete_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(get_user_model().objects.count(), user_count)
@@ -250,7 +250,7 @@ class UserViewTestCase(UserTestMixin, UserViewTestMixin, GenericViewTestCase):
user_count = get_user_model().objects.count()
response = self._request_test_user_delete_multiple_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 404)
self.assertEqual(get_user_model().objects.count(), user_count)
@@ -274,7 +274,7 @@ class UserViewTestCase(UserTestMixin, UserViewTestMixin, GenericViewTestCase):
response = self._request_test_user_password_set_view(
password=TEST_USER_PASSWORD_EDITED
)
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_user.refresh_from_db()
self.assertEqual(self.test_user.password, password_hash)
@@ -300,7 +300,7 @@ class UserViewTestCase(UserTestMixin, UserViewTestMixin, GenericViewTestCase):
response = self._request_test_user_password_set_multiple_view(
password=TEST_USER_PASSWORD_EDITED
)
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.test_user.refresh_from_db()
self.assertEqual(self.test_user.password, password_hash)
@@ -388,7 +388,7 @@ class MetadataLookupIntegrationTestCase(GenericDocumentViewTestCase):
self.metadata_type.save()
self.document.metadata.create(metadata_type=self.metadata_type)
self.grant_access(
obj=self.document, permission=permission_metadata_document_edit
obj=self.document, permission=permission_document_metadata_edit
)
response = self.get(
@@ -407,7 +407,7 @@ class MetadataLookupIntegrationTestCase(GenericDocumentViewTestCase):
self.metadata_type.save()
self.document.metadata.create(metadata_type=self.metadata_type)
self.grant_access(
obj=self.document, permission=permission_metadata_document_edit
obj=self.document, permission=permission_document_metadata_edit
)
response = self.get(

View File

@@ -173,7 +173,7 @@ class UserCreateView(SingleObjectCreateView):
class UserDeleteView(MultipleObjectConfirmActionView):
object_permission = permission_user_delete
queryset = get_user_queryset()
source_queryset = get_user_queryset()
success_message = _('User delete request performed on %(count)d user')
success_message_plural = _(
'User delete request performed on %(count)d users'
@@ -232,7 +232,7 @@ class UserDetailsView(SingleObjectDetailView):
)
object_permission = permission_user_view
pk_url_kwarg = 'pk'
queryset = get_user_queryset()
source_queryset = get_user_queryset()
def get_extra_context(self, **kwargs):
return {
@@ -247,7 +247,7 @@ class UserEditView(SingleObjectEditView):
post_action_redirect = reverse_lazy(
viewname='user_management:user_list'
)
queryset = get_user_queryset()
source_queryset = get_user_queryset()
def get_extra_context(self):
return {
@@ -306,7 +306,7 @@ class UserListView(SingleObjectListView):
'title': _('Users'),
}
def get_object_list(self):
def get_source_queryset(self):
return get_user_queryset()