Update documents app

Rename the DeletedDocument proxy model to a TrashedDocument.

Rename the deleted_document views to trashed_document.

Rename the document and deleted_document URL parameters to
trashed_document.

Update URL parameters to the '_id' form.

Add keyword arguments.

Update use of .filter_by_access().

Enclose trashed document restore method in a transaction.

Sort arguments.

Update app for compliance with MERCs 5 and 6.

Add document page view tests.

Add favorite document view tests.

Movernize tests.

Replace use of urlencode with furl.

Update views to use ExternalObjectMixin.

Refactor the document and version download views.

Rename the DocumentDocumentTypeEditView to DocumentChangeTypeView.

Move the trashed document views to their own module.

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2019-01-28 05:25:48 -04:00
parent 7532429b0b
commit 74dfa53787
40 changed files with 1914 additions and 1615 deletions

View File

@@ -3,8 +3,8 @@ from __future__ import unicode_literals
from django.contrib import admin
from .models import (
DeletedDocument, Document, DocumentPage, DocumentType,
DocumentTypeFilename, DocumentVersion, DuplicatedDocument, RecentDocument
Document, DocumentPage, DocumentType, DocumentTypeFilename, DocumentVersion,
DuplicatedDocument, RecentDocument, TrashedDocument
)
@@ -29,14 +29,6 @@ class DocumentVersionInline(admin.StackedInline):
allow_add = True
@admin.register(DeletedDocument)
class DeletedDocumentAdmin(admin.ModelAdmin):
date_hierarchy = 'deleted_date_time'
list_filter = ('document_type',)
list_display = ('uuid', 'label', 'document_type', 'deleted_date_time')
readonly_fields = ('uuid', 'document_type')
@admin.register(Document)
class DocumentAdmin(admin.ModelAdmin):
date_hierarchy = 'date_added'
@@ -69,3 +61,11 @@ class RecentDocumentAdmin(admin.ModelAdmin):
list_display_links = ('document', 'datetime_accessed')
list_filter = ('user',)
readonly_fields = ('user', 'document', 'datetime_accessed')
@admin.register(TrashedDocument)
class TrashedDocumentAdmin(admin.ModelAdmin):
date_hierarchy = 'deleted_date_time'
list_filter = ('document_type',)
list_display = ('uuid', 'label', 'document_type', 'deleted_date_time')
readonly_fields = ('uuid', 'document_type')

View File

@@ -9,7 +9,7 @@ from django.shortcuts import get_object_or_404
from django.views.decorators.cache import cache_control, patch_cache_control
from django_downloadview import DownloadMixin, VirtualFile
from rest_framework import generics, status
from rest_framework import generics, status, viewsets
from rest_framework.response import Response
from mayan.apps.acls.models import AccessControlList
@@ -17,12 +17,12 @@ from mayan.apps.rest_api.filters import MayanObjectPermissionsFilter
from mayan.apps.rest_api.permissions import MayanPermission
from .literals import DOCUMENT_IMAGE_TASK_TIMEOUT
from .models import Document, DocumentType, RecentDocument
from .models import Document, DocumentVersion, DocumentType, RecentDocument
from .permissions import (
permission_document_create, permission_document_delete,
permission_document_create, permission_trashed_document_delete,
permission_document_download, permission_document_edit,
permission_document_new_version, permission_document_properties_edit,
permission_document_restore, permission_document_trash,
permission_trashed_document_restore, permission_document_trash,
permission_document_type_create, permission_document_type_delete,
permission_document_type_edit, permission_document_type_view,
permission_document_version_revert, permission_document_version_view,
@@ -30,10 +30,11 @@ from .permissions import (
)
from .serializers import (
DeletedDocumentSerializer, DocumentPageSerializer, DocumentSerializer,
DocumentTypeSerializer, DocumentVersionSerializer, NewDocumentSerializer,
NewDocumentVersionSerializer, RecentDocumentSerializer,
WritableDocumentSerializer, WritableDocumentTypeSerializer,
WritableDocumentVersionSerializer
DocumentTypeSerializer, DocumentVersionSerializer,# NewDocumentSerializer,
#NewDocumentVersionSerializer, RecentDocumentSerializer,
RecentDocumentSerializer,
#WritableDocumentSerializer, WritableDocumentTypeSerializer,
#WritableDocumentVersionSerializer
)
from .settings import settings_document_page_image_cache_time
from .tasks import task_generate_document_page_image
@@ -41,12 +42,172 @@ from .tasks import task_generate_document_page_image
logger = logging.getLogger(__name__)
from rest_framework.decorators import action, detail_route
from rest_framework.response import Response
class DocumentViewSet(viewsets.ModelViewSet):
lookup_field = 'pk'
lookup_url_kwarg = 'document_id'
queryset = Document.objects.all()
serializer_class = DocumentSerializer
"""
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='document_id',
url_name='document-version-list', url_path='document_versions'
)
def document_version_list(self, request, *args, **kwargs):
serializer = DocumentVersionSerializer(
instance=self.get_object().versions.all(), many=True,
context={'request': request}
)
return Response(serializer.data)
"""
class DocumentPageViewSet(viewsets.ModelViewSet):
lookup_field = 'pk'
lookup_url_kwarg = 'document_page_id'
serializer_class = DocumentPageSerializer
def get_queryset(self):
return get_object_or_404(
klass=DocumentVersion, document_id=self.kwargs['document_id'],
pk=self.kwargs['document_version_id']
).pages.all()
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='document_page_id',
url_name='image', url_path='image'
)
@cache_control(private=True)
def document_page_image(self, request, *args, **kwargs):
"""
asdasd
"""
transformation_dict = {
'kwargs': {},
'name': {}
}
transformation_list = []
querystring = furl()
querystring.args.update(self.request.GET)
querystring.args.update(self.request.POST)
for key, value in querystring.args.items():
if key.startswith('transformation_'):
literal, index, element = key.split('_')
transformation_dict[element][index] = value
for order, identifier in transformation_dict['name'].items():
if order in transformation_dict['kwargs'].keys():
kwargs = {}
for kwargs_entry in transformation_dict['kwargs'][order].split(','):
key, value = kwargs_entry.split(':')
kwargs[key] = float(value)
transformation_list.append({
'name': identifier,
'kwargs': kwargs
})
width = request.GET.get('width')
height = request.GET.get('height')
zoom = request.GET.get('zoom')
if zoom:
zoom = int(zoom)
rotation = request.GET.get('rotation')
if rotation:
rotation = int(rotation)
task = task_generate_document_page_image.apply_async(
kwargs=dict(
document_page_id=self.get_object().pk, width=width,
height=height, zoom=zoom, rotation=rotation,
transformation_list=transformation_list
)
)
cache_filename = task.get(timeout=DOCUMENT_IMAGE_TASK_TIMEOUT)
with self.get_object().cache_partition.get_file(filename=cache_filename).open() as file_object:
response = HttpResponse(file_object.read(), content_type='image')
if '_hash' in request.GET:
patch_cache_control(
response,
max_age=settings_document_page_image_cache_time.value
)
return response
"""
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='document_page_id',
url_name='document-page-list', url_path='document_pages'
)
def document_page_list(self, request, *args, **kwargs):
serializer = DocumentPageSerializer(
instance=self.get_object().versions.all(), many=True,
context={'request': request}
)
return Response(serializer.data)
"""
class DocumentTypeViewSet(viewsets.ModelViewSet):
lookup_field = 'pk'
lookup_url_kwarg = 'document_type_id'
queryset = DocumentType.objects.all()
serializer_class = DocumentTypeSerializer
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='document_type_id',
url_name='document-list', url_path='documents'
)
def document_list(self, request, *args, **kwargs):
serializer = DocumentSerializer(
instance=self.get_object().documents.all(), many=True,
context={'request': request}
)
return Response(serializer.data)
class DocumentVersionViewSet(viewsets.ModelViewSet):
lookup_field = 'pk'
lookup_url_kwarg = 'document_version_id'
serializer_class = DocumentVersionSerializer
"""
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='document_version_id',
url_name='document-pages-list', url_path='document_pages'
)
def document_pages_list(self, request, *args, **kwargs):
serializer = DocumentPageSerializer(
instance=self.get_object().pages.all(), many=True,
context={'request': request}
)
return Response(serializer.data)
"""
def get_queryset(self):
return get_object_or_404(
klass=Document, pk=self.kwargs['document_id']
).versions.all()
'''
class APIDeletedDocumentListView(generics.ListAPIView):
"""
Returns a list of all the trashed documents.
"""
filter_backends = (MayanObjectPermissionsFilter,)
lookup_url_kwarg = 'document_pk'
lookup_url_kwarg = 'document_id'
mayan_object_permissions = {'GET': (permission_document_view,)}
permission_classes = (MayanPermission,)
queryset = Document.trash.all()
@@ -59,9 +220,9 @@ class APIDeletedDocumentView(generics.RetrieveDestroyAPIView):
delete: Delete the trashed document.
get: Retreive the details of the trashed document.
"""
lookup_url_kwarg = 'document_pk'
lookup_url_kwarg = 'document_id'
mayan_object_permissions = {
'DELETE': (permission_document_delete,),
'DELETE': (permission_trashed_document_delete,),
'GET': (permission_document_view,)
}
permission_classes = (MayanPermission,)
@@ -73,9 +234,9 @@ class APIDeletedDocumentRestoreView(generics.GenericAPIView):
"""
post: Restore a trashed document.
"""
lookup_url_kwarg = 'document_pk'
lookup_url_kwarg = 'document_id'
mayan_object_permissions = {
'POST': (permission_document_restore,)
'POST': (permission_trashed_document_restore,)
}
permission_classes = (MayanPermission,)
queryset = Document.trash.all()
@@ -95,7 +256,7 @@ class APIDocumentDownloadView(DownloadMixin, generics.RetrieveAPIView):
"""
get: Download the latest version of a document.
"""
lookup_url_kwarg = 'document_pk'
lookup_url_kwarg = 'document_id'
mayan_object_permissions = {
'GET': (permission_document_download,)
}
@@ -146,7 +307,7 @@ class APIDocumentListView(generics.ListCreateAPIView):
def perform_create(self, serializer):
AccessControlList.objects.check_access(
permissions=(permission_document_create,), user=self.request.user,
permission=permission_document_create,), user=self.request.user,
obj=serializer.validated_data['document_type']
)
serializer.save(_user=self.request.user)
@@ -156,7 +317,7 @@ class APIDocumentPageImageView(generics.RetrieveAPIView):
"""
get: Returns an image representation of the selected document.
"""
lookup_url_kwarg = 'document_page_pk'
lookup_url_kwarg = 'document_page_id'
def get_document(self):
if self.request.method == 'GET':
@@ -165,7 +326,7 @@ class APIDocumentPageImageView(generics.RetrieveAPIView):
permission_required = permission_document_edit
document = get_object_or_404(
klass=Document.passthrough, pk=self.kwargs['document_pk']
klass=Document.passthrough, pk=self.kwargs['document_id']
)
AccessControlList.objects.check_access(
@@ -175,7 +336,7 @@ class APIDocumentPageImageView(generics.RetrieveAPIView):
def get_document_version(self):
return get_object_or_404(
klass=self.get_document().versions.all(), pk=self.kwargs['document_version_pk']
klass=self.get_document().versions.all(), pk=self.kwargs['document_version_id']
)
def get_queryset(self):
@@ -253,7 +414,7 @@ class APIDocumentPageView(generics.RetrieveUpdateAPIView):
patch: Edit the selected document page.
put: Edit the selected document page.
"""
lookup_url_kwarg = 'document_page_pk'
lookup_url_kwarg = 'document_page_id'
serializer_class = DocumentPageSerializer
def get_document(self):
@@ -263,7 +424,7 @@ class APIDocumentPageView(generics.RetrieveUpdateAPIView):
permission_required = permission_document_edit
document = get_object_or_404(
klass=Document, pk=self.kwargs['document_pk']
klass=Document, pk=self.kwargs['document_id']
)
AccessControlList.objects.check_access(
@@ -274,7 +435,7 @@ class APIDocumentPageView(generics.RetrieveUpdateAPIView):
def get_document_version(self):
return get_object_or_404(
klass=self.get_document().versions.all(),
pk=self.kwargs['document_version_pk']
pk=self.kwargs['document_version_id']
)
def get_queryset(self):
@@ -287,7 +448,7 @@ class APIDocumentTypeListView(generics.ListCreateAPIView):
post: Create a new document type.
"""
filter_backends = (MayanObjectPermissionsFilter,)
lookup_url_kwarg = 'document_type_pk'
lookup_url_kwarg = 'document_type_id'
mayan_object_permissions = {'GET': (permission_document_type_view,)}
mayan_view_permissions = {'POST': (permission_document_type_create,)}
permission_classes = (MayanPermission,)
@@ -314,7 +475,7 @@ class APIDocumentTypeView(generics.RetrieveUpdateDestroyAPIView):
patch: Edit the properties of the selected document type.
put: Edit the properties of the selected document type.
"""
lookup_url_kwarg = 'document_type_pk'
lookup_url_kwarg = 'document_type_id'
mayan_object_permissions = {
'GET': (permission_document_type_view,),
'PUT': (permission_document_type_edit,),
@@ -342,13 +503,13 @@ class APIDocumentTypeDocumentListView(generics.ListAPIView):
Returns a list of all the documents of a particular document type.
"""
filter_backends = (MayanObjectPermissionsFilter,)
lookup_url_kwarg = 'document_type_pk'
lookup_url_kwarg = 'document_type_id'
mayan_object_permissions = {'GET': (permission_document_view,)}
serializer_class = DocumentSerializer
def get_queryset(self):
document_type = get_object_or_404(
klass=DocumentType, pk=self.kwargs['document_type_pk']
klass=DocumentType, pk=self.kwargs['document_type_id']
)
AccessControlList.objects.check_access(
permissions=permission_document_type_view, user=self.request.user,
@@ -362,15 +523,15 @@ class APIDocumentVersionDownloadView(DownloadMixin, generics.RetrieveAPIView):
"""
get: Download a document version.
"""
lookup_url_kwarg = 'document_version_pk'
lookup_url_kwarg = 'document_version_id'
def get_document(self):
document = get_object_or_404(
klass=Document, pk=self.kwargs['document_pk']
klass=Document, pk=self.kwargs['document_id']
)
AccessControlList.objects.check_access(
permissions=(permission_document_download,), user=self.request.user,
permission=permission_document_download,), user=self.request.user,
obj=document
)
return document
@@ -418,7 +579,7 @@ class APIDocumentView(generics.RetrieveUpdateDestroyAPIView):
patch: Edit the properties of the selected document.
put: Edit the properties of the selected document.
"""
lookup_url_kwarg = 'document_pk'
lookup_url_kwarg = 'document_id'
mayan_object_permissions = {
'GET': (permission_document_view,),
'PUT': (permission_document_properties_edit,),
@@ -463,7 +624,7 @@ class APIDocumentVersionPageListView(generics.ListAPIView):
def get_document(self):
document = get_object_or_404(
klass=Document, pk=self.kwargs['document_pk']
klass=Document, pk=self.kwargs['document_id']
)
AccessControlList.objects.check_access(
@@ -474,7 +635,7 @@ class APIDocumentVersionPageListView(generics.ListAPIView):
def get_document_version(self):
return get_object_or_404(
klass=self.get_document().versions.all(),
pk=self.kwargs['document_version_pk']
pk=self.kwargs['document_version_id']
)
def get_queryset(self):
@@ -490,7 +651,7 @@ class APIDocumentVersionsListView(generics.ListCreateAPIView):
mayan_object_permissions = {
'GET': (permission_document_version_view,),
}
mayan_permission_attribute_check = 'document'
#mayan_permission_attribute_check = 'document'
permission_classes = (MayanPermission,)
def create(self, request, *args, **kwargs):
@@ -514,16 +675,16 @@ class APIDocumentVersionsListView(generics.ListCreateAPIView):
def get_queryset(self):
return get_object_or_404(
klass=Document, pk=self.kwargs['document_pk']
klass=Document, pk=self.kwargs['document_id']
).versions.all()
def perform_create(self, serializer):
document = get_object_or_404(
klass=Document, pk=self.kwargs['document_pk']
klass=Document, pk=self.kwargs['document_id']
)
AccessControlList.objects.check_access(
permissions=(permission_document_new_version,),
permission=permission_document_new_version,),
user=self.request.user, obj=document
)
serializer.save(document=document, _user=self.request.user)
@@ -536,7 +697,7 @@ class APIDocumentVersionView(generics.RetrieveUpdateDestroyAPIView):
patch: Edit the selected document version.
put: Edit the selected document version.
"""
lookup_url_kwarg = 'document_version_pk'
lookup_url_kwarg = 'document_version_id'
def get_document(self):
if self.request.method == 'GET':
@@ -547,7 +708,7 @@ class APIDocumentVersionView(generics.RetrieveUpdateDestroyAPIView):
permission_required = permission_document_edit
document = get_object_or_404(
klass=Document, pk=self.kwargs['document_pk']
klass=Document, pk=self.kwargs['document_id']
)
AccessControlList.objects.check_access(
@@ -569,3 +730,4 @@ class APIDocumentVersionView(generics.RetrieveUpdateDestroyAPIView):
return DocumentVersionSerializer
else:
return WritableDocumentVersionSerializer
'''

View File

@@ -53,17 +53,17 @@ from .handlers import (
)
from .links import (
link_clear_image_cache, link_document_clear_transformations,
link_document_clone_transformations, link_document_delete,
link_document_document_type_edit, link_document_download,
link_document_clone_transformations, link_trashed_document_delete,
link_document_change_type, link_document_download,
link_document_duplicates_list, link_document_edit,
link_document_favorites_add, link_document_favorites_remove,
link_document_list, link_document_list_deleted,
link_document_list, link_trashed_document_list,
link_document_list_favorites, link_document_list_recent_access,
link_document_list_recent_added,
link_document_multiple_clear_transformations,
link_document_multiple_delete, link_document_multiple_document_type_edit,
link_trashed_document_multiple_delete, link_document_multiple_change_type,
link_document_multiple_download, link_document_multiple_favorites_add,
link_document_multiple_favorites_remove, link_document_multiple_restore,
link_document_multiple_favorites_remove, link_trashed_document_multiple_restore,
link_document_multiple_trash, link_document_multiple_update_page_count,
link_document_page_navigation_first, link_document_page_navigation_last,
link_document_page_navigation_next, link_document_page_navigation_previous,
@@ -72,7 +72,7 @@ from .links import (
link_document_page_view_reset, link_document_page_zoom_in,
link_document_page_zoom_out, link_document_pages, link_document_preview,
link_document_print, link_document_properties,
link_document_quick_download, link_document_restore, link_document_trash,
link_document_quick_download, link_trashed_document_restore, link_document_trash,
link_document_type_create, link_document_type_delete,
link_document_type_edit, link_document_type_filename_create,
link_document_type_filename_delete, link_document_type_filename_edit,
@@ -90,14 +90,14 @@ from .literals import (
)
from .menus import menu_documents
from .permissions import (
permission_document_create, permission_document_delete,
permission_document_create,
permission_document_download, permission_document_edit,
permission_document_new_version, permission_document_print,
permission_document_properties_edit, permission_document_restore,
permission_document_trash, permission_document_type_delete,
permission_document_type_edit, permission_document_type_view,
permission_document_version_revert, permission_document_version_view,
permission_document_view
permission_document_properties_edit, permission_document_trash,
permission_document_type_delete, permission_document_type_edit,
permission_document_type_view, permission_document_version_revert,
permission_document_version_view, permission_document_view,
permission_trashed_document_delete, permission_trashed_document_restore
)
from .queues import * # NOQA
# Just import to initialize the search models
@@ -119,14 +119,18 @@ class DocumentsApp(MayanAppConfig):
super(DocumentsApp, self).ready()
from actstream import registry
DeletedDocument = self.get_model('DeletedDocument')
Document = self.get_model('Document')
DocumentPage = self.get_model('DocumentPage')
DocumentPageSearchResult = self.get_model('DocumentPageSearchResult')
DocumentType = self.get_model('DocumentType')
DocumentTypeFilename = self.get_model('DocumentTypeFilename')
DocumentVersion = self.get_model('DocumentVersion')
DuplicatedDocumentProxy = self.get_model('DuplicatedDocumentProxy')
Document = self.get_model(model_name='Document')
DocumentPage = self.get_model(model_name='DocumentPage')
DocumentPageSearchResult = self.get_model(
model_name='DocumentPageSearchResult'
)
DocumentType = self.get_model(model_name='DocumentType')
DocumentTypeFilename = self.get_model(model_name='DocumentTypeFilename')
DocumentVersion = self.get_model(model_name='DocumentVersion')
DuplicatedDocumentProxy = self.get_model(
model_name='DuplicatedDocumentProxy'
)
TrashedDocument = self.get_model(model_name='TrashedDocument')
DynamicSerializerField.add_serializer(
klass=Document,
@@ -185,15 +189,16 @@ class DocumentsApp(MayanAppConfig):
ModelPermission.register(
model=Document, permissions=(
permission_acl_edit, permission_acl_view,
permission_document_delete, permission_document_download,
permission_document_edit, permission_document_new_version,
permission_document_print, permission_document_properties_edit,
permission_document_restore, permission_document_trash,
permission_document_download, permission_document_edit,
permission_document_new_version, permission_document_print,
permission_document_properties_edit, permission_document_trash,
permission_document_version_revert,
permission_document_version_view, permission_document_view,
permission_events_view, permission_transformation_create,
permission_transformation_delete,
permission_transformation_edit, permission_transformation_view,
permission_trashed_document_delete,
permission_trashed_document_restore
)
)
@@ -297,22 +302,22 @@ class DocumentsApp(MayanAppConfig):
widget=TwoStateWidget
)
# DeletedDocument
# TrashedDocument
SourceColumn(
attribute='label', is_identifier=True, is_sortable=True,
source=DeletedDocument
source=TrashedDocument
)
SourceColumn(
func=lambda context: document_page_thumbnail_widget.render(
instance=context['object']
), label=_('Thumbnail'), source=DeletedDocument
), label=_('Thumbnail'), source=TrashedDocument
)
SourceColumn(
attribute='document_type', is_sortable=True, source=DeletedDocument
attribute='document_type', is_sortable=True, source=TrashedDocument
)
SourceColumn(
attribute='get_rendered_deleted_date_time', source=DeletedDocument
attribute='get_rendered_deleted_date_time', source=TrashedDocument
)
# DocumentVersion
@@ -445,7 +450,7 @@ class DocumentsApp(MayanAppConfig):
links=(
link_document_list_recent_access,
link_document_list_recent_added, link_document_list_favorites,
link_document_list, link_document_list_deleted,
link_document_list, link_trashed_document_list,
link_duplicated_document_list,
)
)
@@ -493,7 +498,7 @@ class DocumentsApp(MayanAppConfig):
menu_sidebar.bind_links(
links=(link_trash_can_empty,),
sources=(
'documents:document_list_deleted', 'documents:trash_can_empty'
'documents:trashed_document_list', 'documents:trash_can_empty'
)
)
@@ -501,7 +506,7 @@ class DocumentsApp(MayanAppConfig):
menu_object.bind_links(
links=(
link_document_favorites_add, link_document_favorites_remove,
link_document_edit, link_document_document_type_edit,
link_document_edit, link_document_change_type,
link_document_print, link_document_trash,
link_document_quick_download, link_document_download,
link_document_clear_transformations,
@@ -510,8 +515,8 @@ class DocumentsApp(MayanAppConfig):
), sources=(Document,)
)
menu_object.bind_links(
links=(link_document_restore, link_document_delete),
sources=(DeletedDocument,)
links=(link_trashed_document_restore, link_trashed_document_delete),
sources=(TrashedDocument,)
)
# Document facet links
@@ -548,13 +553,14 @@ class DocumentsApp(MayanAppConfig):
link_document_multiple_clear_transformations,
link_document_multiple_trash, link_document_multiple_download,
link_document_multiple_update_page_count,
link_document_multiple_document_type_edit,
link_document_multiple_change_type,
), sources=(Document,)
)
menu_multi_item.bind_links(
links=(
link_document_multiple_restore, link_document_multiple_delete
), sources=(DeletedDocument,)
link_trashed_document_multiple_restore,
link_trashed_document_multiple_delete
), sources=(TrashedDocument,)
)
# Document pages
@@ -614,7 +620,7 @@ class DocumentsApp(MayanAppConfig):
receiver=handler_scan_duplicates_for,
)
registry.register(DeletedDocument)
registry.register(TrashedDocument)
registry.register(Document)
registry.register(DocumentType)
registry.register(DocumentVersion)

View File

@@ -32,17 +32,19 @@ class DashboardWidgetDocumentPagesTotal(DashboardWidgetNumeric):
DocumentPage = apps.get_model(
app_label='documents', model_name='DocumentPage'
)
self.count = AccessControlList.objects.filter_by_access(
permission=permission_document_view, user=request.user,
queryset=DocumentPage.objects.all()
self.count = AccessControlList.objects.restrict_queryset(
permission=permission_document_view,
queryset=DocumentPage.objects.all(), user=request.user
).count()
return super(DashboardWidgetDocumentPagesTotal, self).render(request)
return super(DashboardWidgetDocumentPagesTotal, self).render(
request=request
)
class DashboardWidgetDocumentsTotal(DashboardWidgetNumeric):
icon_class = icon_dashboard_total_document
label = _('Total documents')
link = reverse_lazy('documents:document_list')
link = reverse_lazy(viewname='documents:document_list')
def render(self, request):
AccessControlList = apps.get_model(
@@ -51,36 +53,40 @@ class DashboardWidgetDocumentsTotal(DashboardWidgetNumeric):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
self.count = AccessControlList.objects.filter_by_access(
permission=permission_document_view, user=request.user,
queryset=Document.objects.all()
self.count = AccessControlList.objects.restrict_queryset(
permission=permission_document_view,
queryset=Document.objects.all(), user=request.user
).count()
return super(DashboardWidgetDocumentsTotal, self).render(request)
return super(DashboardWidgetDocumentsTotal, self).render(
request=request
)
class DashboardWidgetDocumentsInTrash(DashboardWidgetNumeric):
icon_class = icon_dashboard_documents_in_trash
label = _('Documents in trash')
link = reverse_lazy('documents:document_list_deleted')
link = reverse_lazy(viewname='documents:trashed_document_list')
def render(self, request):
AccessControlList = apps.get_model(
app_label='acls', model_name='AccessControlList'
)
DeletedDocument = apps.get_model(
app_label='documents', model_name='DeletedDocument'
TrashedDocument = apps.get_model(
app_label='documents', model_name='TrashedDocument'
)
self.count = AccessControlList.objects.filter_by_access(
permission=permission_document_view, user=request.user,
queryset=DeletedDocument.objects.all()
self.count = AccessControlList.objects.restrict_queryset(
permission=permission_document_view,
queryset=TrashedDocument.objects.all(), user=request.user
).count()
return super(DashboardWidgetDocumentsInTrash, self).render(request)
return super(DashboardWidgetDocumentsInTrash, self).render(
request=request
)
class DashboardWidgetDocumentsTypesTotal(DashboardWidgetNumeric):
icon_class = icon_dashboard_document_types
label = _('Document types')
link = reverse_lazy('documents:document_type_list')
link = reverse_lazy(viewname='documents:document_type_list')
def render(self, request):
AccessControlList = apps.get_model(
@@ -89,11 +95,13 @@ class DashboardWidgetDocumentsTypesTotal(DashboardWidgetNumeric):
DocumentType = apps.get_model(
app_label='documents', model_name='DocumentType'
)
self.count = AccessControlList.objects.filter_by_access(
permission=permission_document_type_view, user=request.user,
queryset=DocumentType.objects.all()
self.count = AccessControlList.objects.restrict_queryset(
permission=permission_document_type_view,
queryset=DocumentType.objects.all(), user=request.user
).count()
return super(DashboardWidgetDocumentsTypesTotal, self).render(request)
return super(DashboardWidgetDocumentsTypesTotal, self).render(
request=request
)
class DashboardWidgetDocumentsNewThisMonth(DashboardWidgetNumeric):
@@ -106,7 +114,9 @@ class DashboardWidgetDocumentsNewThisMonth(DashboardWidgetNumeric):
def render(self, request):
self.count = new_documents_this_month(user=request.user)
return super(DashboardWidgetDocumentsNewThisMonth, self).render(request)
return super(DashboardWidgetDocumentsNewThisMonth, self).render(
request=request
)
class DashboardWidgetDocumentsPagesNewThisMonth(DashboardWidgetNumeric):
@@ -119,4 +129,6 @@ class DashboardWidgetDocumentsPagesNewThisMonth(DashboardWidgetNumeric):
def render(self, request):
self.count = new_document_pages_this_month(user=request.user)
return super(DashboardWidgetDocumentsPagesNewThisMonth, self).render(request)
return super(DashboardWidgetDocumentsPagesNewThisMonth, self).render(
request=request
)

View File

@@ -4,35 +4,35 @@ from django.utils.translation import ugettext_lazy as _
from mayan.apps.events import EventTypeNamespace
namespace = EventTypeNamespace(name='documents', label=_('Documents'))
namespace = EventTypeNamespace(label=_('Documents'), name='documents')
event_document_create = namespace.add_event_type(
name='document_create', label=_('Document created')
label=_('Document created'), name='document_create'
)
event_document_download = namespace.add_event_type(
name='document_download', label=_('Document downloaded')
label=_('Document downloaded'), name='document_download'
)
event_document_new_version = namespace.add_event_type(
name='document_new_version', label=_('New version uploaded')
label=_('New version uploaded'), name='document_new_version'
)
event_document_properties_edit = namespace.add_event_type(
name='document_edit', label=_('Document properties edited')
label=_('Document properties edited'), name='document_edit'
)
# The type of an existing document is changed to another type
event_document_type_change = namespace.add_event_type(
name='document_type_change', label=_('Document type changed')
label=_('Document type changed'), name='document_type_change'
)
# A document type is created
event_document_type_created = namespace.add_event_type(
name='document_type_created', label=_('Document type created')
label=_('Document type created'), name='document_type_created'
)
# An existing document type is modified
event_document_type_edited = namespace.add_event_type(
name='document_type_edit', label=_('Document type edited')
label=_('Document type edited'), name='document_type_edit'
)
event_document_version_revert = namespace.add_event_type(
name='document_version_revert', label=_('Document version reverted')
label=_('Document version reverted'), name='document_version_revert'
)
event_document_view = namespace.add_event_type(
name='document_view', label=_('Document viewed')
label=_('Document viewed'), name='document_view'
)

View File

@@ -45,7 +45,7 @@ class DocumentTypeFilteredSelectForm(forms.Form):
queryset = DocumentType.objects.all()
if permission:
queryset = AccessControlList.objects.filter_by_access(
queryset = AccessControlList.objects.restrict_queryset(
permission=permission, queryset=queryset, user=user
)

View File

@@ -18,9 +18,6 @@ icon_dashboard_new_documents_this_month = Icon(
icon_dashboard_total_document = Icon(
driver_name='fontawesome', symbol='file'
)
icon_document_delete = Icon(
driver_name='fontawesome', symbol='times'
)
icon_document_download = Icon(
driver_name='fontawesome', symbol='download'
)
@@ -42,9 +39,6 @@ icon_document_image_loading = Icon(
driver_name='fontawesomecss', css_classes='far fa-clock fa-2x'
)
icon_document_list = Icon(driver_name='fontawesome', symbol='book')
icon_document_list_deleted = Icon(
driver_name='fontawesome', symbol='trash-alt'
)
icon_document_list_favorites = Icon(driver_name='fontawesome', symbol='star')
icon_document_list_recent_access = Icon(
driver_name='fontawesome', symbol='clock'
@@ -52,12 +46,6 @@ icon_document_list_recent_access = Icon(
icon_document_list_recent_added = Icon(
driver_name='fontawesome', symbol='asterisk'
)
icon_document_multiple_delete = Icon(
driver_name='fontawesome', symbol='trash-alt'
)
icon_document_multiepl_restore = Icon(
driver_name='fontawesome', symbol='recycle'
)
icon_document_page_navigation_first = Icon(
driver_name='fontawesome', symbol='step-backward'
)
@@ -95,7 +83,6 @@ icon_document_print = Icon(
driver_name='fontawesome', symbol='print'
)
icon_document_properties = Icon(driver_name='fontawesome', symbol='info')
icon_document_restore = Icon(driver_name='fontawesome', symbol='recycle')
icon_document_trash = Icon(
driver_name='fontawesome', symbol='trash-alt'
)
@@ -141,3 +128,18 @@ icon_menu_documents = Icon(driver_name='fontawesome', symbol='book')
icon_trash_can_empty = Icon(
driver_name='fontawesome', symbol='trash-alt'
)
icon_trashed_document_delete = Icon(
driver_name='fontawesome', symbol='times'
)
icon_trashed_document_list = Icon(
driver_name='fontawesome', symbol='trash-alt'
)
icon_trashed_document_multiple_delete = Icon(
driver_name='fontawesome', symbol='trash-alt'
)
icon_trashed_document_multiple_restore = Icon(
driver_name='fontawesome', symbol='recycle'
)
icon_trashed_document_restore = Icon(
driver_name='fontawesome', symbol='recycle'
)

View File

@@ -9,19 +9,18 @@ from mayan.apps.navigation import Link
from .icons import (
icon_clear_image_cache, icon_document_duplicates_list, icon_document_list,
icon_document_list_deleted, icon_document_list_favorites,
icon_document_list_favorites,
icon_document_list_recent_access, icon_document_list_recent_added,
icon_document_delete, icon_document_download, icon_document_edit,
icon_trashed_document_delete, icon_document_download, icon_document_edit,
icon_document_favorites_add, icon_document_favorites_remove,
icon_document_multiple_delete,
icon_document_multiple_restore, icon_document_page_navigation_first,
icon_document_page_navigation_first,
icon_document_page_navigation_last,
icon_document_page_navigation_next, icon_document_page_navigation_previous,
icon_document_page_return, icon_document_page_rotate_left,
icon_document_page_rotate_right, icon_document_page_view,
icon_document_page_view_reset, icon_document_page_zoom_in,
icon_document_page_zoom_out, icon_document_pages, icon_document_preview,
icon_document_print, icon_document_properties, icon_document_restore,
icon_document_print, icon_document_properties, icon_trashed_document_restore,
icon_document_trash, icon_document_type_create,
icon_document_type_delete, icon_document_type_edit,
icon_document_type_filename, icon_document_type_filename_create,
@@ -30,17 +29,20 @@ from .icons import (
icon_document_version_list, icon_document_version_return_document,
icon_document_version_return_list, icon_document_version_view,
icon_duplicated_document_list, icon_duplicated_document_scan,
icon_trash_can_empty
icon_trash_can_empty,
icon_trashed_document_list,
icon_trashed_document_multiple_delete,
icon_trashed_document_multiple_restore,
)
from .permissions import (
permission_document_delete, permission_document_download,
permission_document_print, permission_document_properties_edit,
permission_document_restore, permission_document_tools,
permission_document_download, permission_document_print,
permission_document_properties_edit, permission_document_tools,
permission_document_trash, permission_document_type_create,
permission_document_type_delete, permission_document_type_edit,
permission_document_type_view, permission_document_version_revert,
permission_document_version_view, permission_document_view,
permission_empty_trash
permission_empty_trash, permission_trashed_document_delete,
permission_trashed_document_restore
)
from .settings import setting_zoom_max_level, setting_zoom_min_level
@@ -74,22 +76,26 @@ def is_min_zoom(context):
# Facet
link_document_preview = Link(
args='resolved_object.id', icon_class=icon_document_preview,
icon_class=icon_document_preview,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_view, text=_('Preview'),
view='documents:document_preview'
)
link_document_properties = Link(
args='resolved_object.id', icon_class=icon_document_properties,
icon_class=icon_document_properties,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_view, text=_('Properties'),
view='documents:document_properties'
)
link_document_version_list = Link(
args='resolved_object.pk', icon_class=icon_document_version_list,
icon_class=icon_document_version_list,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_version_view, text=_('Versions'),
view='documents:document_version_list'
)
link_document_pages = Link(
args='resolved_object.pk', icon_class=icon_document_pages,
icon_class=icon_document_pages,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_view, text=_('Pages'),
view='documents:document_pages'
)
@@ -97,68 +103,68 @@ link_document_pages = Link(
# Actions
link_document_clear_transformations = Link(
args='resolved_object.id', permission=permission_transformation_delete,
kwargs={'document_id': 'resolved_object.id'},
text=_('Clear transformations'),
view='documents:document_clear_transformations'
)
link_document_clone_transformations = Link(
args='resolved_object.id', permission=permission_transformation_edit,
permission=permission_transformation_edit,
kwargs={'document_id': 'resolved_object.id'},
text=_('Clone transformations'),
view='documents:document_clone_transformations'
)
link_document_delete = Link(
args='resolved_object.id', icon_class=icon_document_delete,
permission=permission_document_delete, tags='dangerous',
text=_('Delete'), view='documents:document_delete'
)
link_document_favorites_add = Link(
args='resolved_object.id', icon_class=icon_document_favorites_add,
icon_class=icon_document_favorites_add,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_view, text=_('Add to favorites'),
view='documents:document_add_to_favorites'
)
link_document_favorites_remove = Link(
args='resolved_object.id', icon_class=icon_document_favorites_remove,
icon_class=icon_document_favorites_remove,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_view, text=_('Remove from favorites'),
view='documents:document_remove_from_favorites'
)
link_document_trash = Link(
args='resolved_object.id', icon_class=icon_document_trash,
icon_class=icon_document_trash,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_trash, tags='dangerous',
text=_('Move to trash'), view='documents:document_trash'
)
link_document_edit = Link(
args='resolved_object.id', icon_class=icon_document_edit,
icon_class=icon_document_edit,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_properties_edit,
text=_('Edit properties'), view='documents:document_edit'
)
link_document_document_type_edit = Link(
args='resolved_object.id',
link_document_change_type = Link(
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_properties_edit, text=_('Change type'),
view='documents:document_document_type_edit'
view='documents:document_change_type'
)
link_document_download = Link(
args='resolved_object.id', icon_class=icon_document_download,
icon_class=icon_document_download,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_download, text=_('Advanced download'),
view='documents:document_download_form'
)
link_document_print = Link(
args='resolved_object.id', icon_class=icon_document_print,
icon_class=icon_document_print,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_print, text=_('Print'),
view='documents:document_print'
)
link_document_quick_download = Link(
args='resolved_object.id', permission=permission_document_download,
permission=permission_document_download,
kwargs={'document_id': 'resolved_object.id'},
text=_('Quick download'), view='documents:document_download'
)
link_document_update_page_count = Link(
args='resolved_object.pk', permission=permission_document_tools,
kwargs={'document_id': 'resolved_object.id'},
permission=permission_document_tools,
text=_('Recalculate page count'),
view='documents:document_update_page_count'
)
link_document_restore = Link(
args='object.pk', icon_class=icon_document_restore,
permission=permission_document_restore, text=_('Restore'),
view='documents:document_restore'
)
link_document_multiple_clear_transformations = Link(
permission=permission_transformation_delete,
text=_('Clear transformations'),
@@ -168,10 +174,6 @@ link_document_multiple_trash = Link(
tags='dangerous', text=_('Move to trash'),
view='documents:document_multiple_trash'
)
link_document_multiple_delete = Link(
icon_class=icon_document_multiple_delete, tags='dangerous',
text=_('Delete'), view='documents:document_multiple_delete'
)
link_document_multiple_favorites_add = Link(
text=_('Add to favorites'),
view='documents:document_multiple_add_to_favorites'
@@ -180,9 +182,9 @@ link_document_multiple_favorites_remove = Link(
text=_('Remove from favorites'),
view='documents:document_multiple_remove_from_favorites'
)
link_document_multiple_document_type_edit = Link(
link_document_multiple_change_type = Link(
text=_('Change type'),
view='documents:document_multiple_document_type_edit'
view='documents:document_multiple_change_type'
)
link_document_multiple_download = Link(
text=_('Advanced download'),
@@ -192,31 +194,54 @@ link_document_multiple_update_page_count = Link(
text=_('Recalculate page count'),
view='documents:document_multiple_update_page_count'
)
link_document_multiple_restore = Link(
icon_class=icon_document_multiple_restore, text=_('Restore'),
view='documents:document_multiple_restore'
link_trashed_document_delete = Link(
icon_class=icon_trashed_document_delete,
kwargs={'trashed_document_id': 'resolved_object.id'},
permission=permission_trashed_document_delete, tags='dangerous',
text=_('Delete'), view='documents:trashed_document_delete'
)
link_trashed_document_list = Link(
icon_class=icon_trashed_document_list, text=_('Trash can'),
view='documents:trashed_document_list'
)
link_trashed_document_restore = Link(
icon_class=icon_trashed_document_restore,
kwargs={'trashed_document_id': 'resolved_object.id'},
permission=permission_trashed_document_restore, text=_('Restore'),
view='documents:trashed_document_restore'
)
link_trashed_document_multiple_delete = Link(
icon_class=icon_trashed_document_multiple_delete, tags='dangerous',
text=_('Delete'), view='documents:trashed_document_multiple_delete'
)
link_trashed_document_multiple_restore = Link(
icon_class=icon_trashed_document_multiple_restore, text=_('Restore'),
view='documents:trashed_document_multiple_restore'
)
# Versions
link_document_version_download = Link(
args='resolved_object.pk', icon_class=icon_document_version_download,
icon_class=icon_document_version_download,
kwargs={'document_version_id': 'resolved_object.pk'},
permission=permission_document_download, text=_('Download version'),
view='documents:document_version_download_form'
)
link_document_version_return_document = Link(
args='resolved_object.document.pk',
icon_class=icon_document_version_return_document,
kwargs={'document_id': 'resolved_object.document.pk'},
permission=permission_document_view, text=_('Document'),
view='documents:document_preview'
)
link_document_version_return_list = Link(
args='resolved_object.document.pk',
icon_class=icon_document_version_return_list,
kwargs={'document_id': 'resolved_object.document.pk'},
permission=permission_document_version_view, text=_('Versions'),
view='documents:document_version_list'
)
link_document_version_view = Link(
args='resolved_object.pk', icon_class=icon_document_version_view,
icon_class=icon_document_version_view,
kwargs={'document_version_id': 'resolved_object.pk'},
permission=permission_document_version_view, text=_('Preview'),
view='documents:document_version_view'
)
@@ -238,10 +263,6 @@ link_document_list_recent_added = Link(
icon_class=icon_document_list_recent_added, text=_('Recently added'),
view='documents:document_list_recent_added'
)
link_document_list_deleted = Link(
icon_class=icon_document_list_deleted, text=_('Trash can'),
view='documents:document_list_deleted'
)
# Tools
link_clear_image_cache = Link(
@@ -260,73 +281,80 @@ link_trash_can_empty = Link(
# Document pages
link_document_page_navigation_first = Link(
args='resolved_object.pk', conditional_disable=is_first_page,
icon_class=icon_document_page_navigation_first,
keep_query=True, permission=permission_document_view,
text=_('First page'), view='documents:document_page_navigation_first'
conditional_disable=is_first_page,
icon_class=icon_document_page_navigation_first, keep_query=True,
kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('First page'),
view='documents:document_page_navigation_first'
)
link_document_page_navigation_last = Link(
args='resolved_object.pk', conditional_disable=is_last_page,
icon_class=icon_document_page_navigation_last,
keep_query=True, text=_('Last page'),
permission=permission_document_view,
conditional_disable=is_last_page,
icon_class=icon_document_page_navigation_last, keep_query=True,
kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Last page'),
view='documents:document_page_navigation_last'
)
link_document_page_navigation_previous = Link(
args='resolved_object.pk', conditional_disable=is_first_page,
icon_class=icon_document_page_navigation_previous,
keep_query=True, permission=permission_document_view,
text=_('Previous page'),
conditional_disable=is_first_page,
icon_class=icon_document_page_navigation_previous, keep_query=True,
kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Previous page'),
view='documents:document_page_navigation_previous'
)
link_document_page_navigation_next = Link(
args='resolved_object.pk', conditional_disable=is_last_page,
icon_class=icon_document_page_navigation_next,
keep_query=True, text=_('Next page'),
conditional_disable=is_last_page,
icon_class=icon_document_page_navigation_next, keep_query=True,
kwargs={'document_page_id': 'resolved_object.pk'}, text=_('Next page'),
permission=permission_document_view,
view='documents:document_page_navigation_next'
)
link_document_page_return = Link(
args='resolved_object.document.pk', icon_class=icon_document_page_return,
icon_class=icon_document_page_return,
kwargs={'document_id': 'resolved_object.document.pk'},
permission=permission_document_view, text=_('Document'),
view='documents:document_preview'
)
link_document_page_rotate_left = Link(
args='resolved_object.pk', icon_class=icon_document_page_rotate_left,
keep_query=True, permission=permission_document_view,
text=_('Rotate left'), view='documents:document_page_rotate_left'
icon_class=icon_document_page_rotate_left, keep_query=True,
kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Rotate left'),
view='documents:document_page_rotate_left'
)
link_document_page_rotate_right = Link(
args='resolved_object.pk', icon_class=icon_document_page_rotate_right,
keep_query=True, permission=permission_document_view,
text=_('Rotate right'), view='documents:document_page_rotate_right'
icon_class=icon_document_page_rotate_right, keep_query=True,
kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Rotate right'),
view='documents:document_page_rotate_right'
)
link_document_page_view = Link(
icon_class=icon_document_page_view,
kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Page image'),
view='documents:document_page_view', args='resolved_object.pk'
view='documents:document_page_view'
)
link_document_page_view_reset = Link(
icon_class=icon_document_page_view_reset,
kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Reset view'),
view='documents:document_page_view_reset', args='resolved_object.pk'
view='documents:document_page_view_reset'
)
link_document_page_zoom_in = Link(
args='resolved_object.pk', conditional_disable=is_max_zoom,
icon_class=icon_document_page_zoom_in, keep_query=True,
conditional_disable=is_max_zoom, icon_class=icon_document_page_zoom_in,
keep_query=True, kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Zoom in'),
view='documents:document_page_zoom_in'
)
link_document_page_zoom_out = Link(
args='resolved_object.pk', conditional_disable=is_min_zoom,
icon_class=icon_document_page_zoom_out, keep_query=True,
conditional_disable=is_min_zoom, icon_class=icon_document_page_zoom_out,
keep_query=True, kwargs={'document_page_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Zoom out'),
view='documents:document_page_zoom_out'
)
# Document versions
link_document_version_revert = Link(
args='object.pk', condition=is_not_current_version,
condition=is_not_current_version,
kwargs={'document_version_id': 'object.pk'},
permission=permission_document_version_revert, tags='dangerous',
text=_('Revert'), view='documents:document_version_revert'
)
@@ -338,32 +366,38 @@ link_document_type_create = Link(
text=_('Create document type'), view='documents:document_type_create'
)
link_document_type_delete = Link(
args='resolved_object.id', icon_class=icon_document_type_delete,
icon_class=icon_document_type_delete,
kwargs={'document_type_id': 'resolved_object.pk'},
permission=permission_document_type_delete, tags='dangerous',
text=_('Delete'), view='documents:document_type_delete'
)
link_document_type_edit = Link(
args='resolved_object.id', icon_class=icon_document_type_edit,
icon_class=icon_document_type_edit,
kwargs={'document_type_id': 'resolved_object.pk'},
permission=permission_document_type_edit, text=_('Edit'),
view='documents:document_type_edit'
)
link_document_type_filename_create = Link(
args='document_type.id', icon_class=icon_document_type_filename_create,
icon_class=icon_document_type_filename_create,
kwargs={'document_type_id': 'resolved_object.pk'},
permission=permission_document_type_edit,
text=_('Add quick label to document type'),
view='documents:document_type_filename_create'
)
link_document_type_filename_delete = Link(
args='resolved_object.id', permission=permission_document_type_edit,
kwargs={'filename_id': 'resolved_object.pk'},
permission=permission_document_type_edit,
tags='dangerous', text=_('Delete'),
view='documents:document_type_filename_delete'
)
link_document_type_filename_edit = Link(
args='resolved_object.id', permission=permission_document_type_edit,
kwargs={'filename_id': 'resolved_object.pk'},
permission=permission_document_type_edit,
text=_('Edit'), view='documents:document_type_filename_edit'
)
link_document_type_filename_list = Link(
args='resolved_object.id', icon_class=icon_document_type_filename,
icon_class=icon_document_type_filename,
kwargs={'document_type_id': 'resolved_object.pk'},
permission=permission_document_type_view, text=_('Quick labels'),
view='documents:document_type_filename_list'
)
@@ -382,7 +416,8 @@ link_duplicated_document_list = Link(
view='documents:duplicated_document_list'
)
link_document_duplicates_list = Link(
args='resolved_object.id', icon_class=icon_document_duplicates_list,
icon_class=icon_document_duplicates_list,
kwargs={'document_id': 'resolved_object.pk'},
permission=permission_document_view, text=_('Duplicates'),
view='documents:document_duplicates_list'
)

View File

@@ -40,7 +40,9 @@ class DocumentPageManager(models.Manager):
except DocumentVersion.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document_version__pk=document_version.pk, page_number=page_number)
return self.get(
document_version__id=document_version.pk, page_number=page_number
)
class DocumentTypeManager(models.Manager):
@@ -61,13 +63,13 @@ class DocumentTypeManager(models.Manager):
'Document type: %s, has a deletion period delta of: %s',
document_type, delta
)
for document in document_type.deleted_documents.filter(deleted_date_time__lt=now() - delta):
for trashed_document in document_type.trashed_documents.filter(deleted_date_time__lt=now() - delta):
logger.info(
'Document "%s" with id: %d, trashed on: %s, exceded '
'delete period', document, document.pk,
document.deleted_date_time
'delete period', trashed_document, trashed_document.pk,
trashed_document.deleted_date_time
)
document.delete()
trashed_document.delete()
else:
logger.info(
'Document type: %s, has a no retention delta', document_type
@@ -120,7 +122,7 @@ class DocumentVersionManager(models.Manager):
except Document.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document__pk=document.pk, checksum=checksum)
return self.get(document__id=document.pk, checksum=checksum)
class DuplicatedDocumentManager(models.Manager):
@@ -204,7 +206,7 @@ class FavoriteDocumentManager(models.Manager):
except User.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document__pk=document.pk, user__pk=user.pk)
return self.get(document__id=document.pk, user__id=user.pk)
def get_for_user(self, user):
Document = apps.get_model(
@@ -254,7 +256,7 @@ class RecentDocumentManager(models.Manager):
raise self.model.DoesNotExist
return self.get(
document__pk=document.pk, user__pk=user.pk,
document__id=document.pk, user__id=user.pk,
datetime_accessed=datetime_accessed
)

View File

@@ -31,8 +31,8 @@ from ..signals import post_document_type_change
from .document_type_models import DocumentType
__all__ = (
'Document', 'DeletedDocument', 'DuplicatedDocument', 'FavoriteDocument',
'RecentDocument'
'Document', 'DuplicatedDocument', 'FavoriteDocument', 'RecentDocument',
'TrashedDocument'
)
logger = logging.getLogger(__name__)
@@ -137,7 +137,7 @@ class Document(models.Model):
def get_absolute_url(self):
return reverse(
viewname='documents:document_preview',
kwargs={'document_pk': self.pk}
kwargs={'document_id': self.pk}
)
def get_api_image_url(self, *args, **kwargs):
@@ -279,13 +279,6 @@ class Document(models.Model):
return DocumentPage.objects.none()
class DeletedDocument(Document):
objects = TrashCanManager()
class Meta:
proxy = True
@python_2_unicode_compatible
class DuplicatedDocument(models.Model):
document = models.ForeignKey(
@@ -316,9 +309,9 @@ class DuplicatedDocumentProxy(Document):
verbose_name_plural = _('Duplicated documents')
def get_duplicate_count(self, user):
queryset = AccessControlList.objects.filter_by_access(
permission=permission_document_view, user=user,
queryset=self.get_duplicates()
queryset = AccessControlList.objects.restrict_queryset(
permission=permission_document_view, queryset=self.get_duplicates(),
user=user
)
return queryset.count()
@@ -382,3 +375,10 @@ class RecentDocument(models.Model):
def natural_key(self):
return (self.datetime_accessed, self.document.natural_key(), self.user.natural_key())
natural_key.dependencies = ['documents.Document', settings.AUTH_USER_MODEL]
class TrashedDocument(Document):
objects = TrashCanManager()
class Meta:
proxy = True

View File

@@ -103,7 +103,7 @@ class DocumentPage(models.Model):
def get_absolute_url(self):
return reverse(
viewname='documents:document_page_view',
kwargs={'document_page_pk': self.pk}
kwargs={'document_page_id': self.pk}
)
def get_api_image_url(self, *args, **kwargs):
@@ -126,10 +126,10 @@ class DocumentPage(models.Model):
final_url = furl()
final_url.args = kwargs
final_url.path = reverse(
viewname='rest_api:documentpage-image', kwargs={
'document_pk': self.document.pk,
'document_version_pk': self.document_version.pk,
'document_page_pk': self.pk
viewname='rest_api:document_page-image', kwargs={
'document_id': self.document.pk,
'document_version_id': self.document_version.pk,
'document_page_id': self.pk
}
)
final_url.args['_hash'] = transformations_hash

View File

@@ -73,23 +73,16 @@ class DocumentType(models.Model):
return super(DocumentType, self).delete(*args, **kwargs)
@property
def deleted_documents(self):
DeletedDocument = apps.get_model(
app_label='documents', model_name='DeletedDocument'
)
return DeletedDocument.objects.filter(document_type=self)
def get_absolute_url(self):
return reverse(
viewname='documents:document_type_document_list',
kwargs={'document_type_pk': self.pk}
kwargs={'document_type_id': self.pk}
)
def get_document_count(self, user):
queryset = AccessControlList.objects.filter_by_access(
permission=permission_document_view, user=user,
queryset=self.documents
queryset = AccessControlList.objects.restrict_queryset(
permission=permission_document_view, queryset=self.documents,
user=user
)
return queryset.count()
get_document_count.short_description = _('Documents')
@@ -134,6 +127,13 @@ class DocumentType(models.Model):
return result
@property
def trashed_documents(self):
TrashedDocument = apps.get_model(
app_label='documents', model_name='TrashedDocument'
)
return TrashedDocument.objects.filter(document_type=self)
@python_2_unicode_compatible
class DocumentTypeFilename(models.Model):

View File

@@ -151,7 +151,7 @@ class DocumentVersion(models.Model):
def get_absolute_url(self):
return reverse(
viewname='documents:document_version_view',
kwargs={'document_version_pk': self.pk}
kwargs={'document_version_id': self.pk}
)
def get_api_image_url(self, *args, **kwargs):
@@ -195,6 +195,7 @@ class DocumentVersion(models.Model):
filename, self.get_rendered_timestamp(), extension
)
else:
#TODO: use get_rendered_timestamp here
return Template(
'{{ instance.document }} - {{ instance.timestamp }}'
).render(context=Context({'instance': self}))
@@ -205,6 +206,10 @@ class DocumentVersion(models.Model):
)
get_rendered_timestamp.short_description = _('Date and time')
@property
def label(self):
return self.get_rendered_string()
def natural_key(self):
return (self.checksum, self.document.natural_key())
natural_key.dependencies = ['documents.Document']
@@ -250,9 +255,19 @@ class DocumentVersion(models.Model):
self.document, self
)
event_document_version_revert.commit(actor=_user, target=self.document)
for version in self.document.versions.filter(timestamp__gt=self.timestamp):
version.delete()
try:
with transaction.atomic():
event_document_version_revert.commit(
actor=_user, target=self.document
)
for version in self.document.versions.filter(timestamp__gt=self.timestamp):
version.delete()
except Exception as exception:
logger.error(
'Error reverting document version for document "%s"; %s',
self.document, exception
)
raise
def save(self, *args, **kwargs):
"""

View File

@@ -7,62 +7,62 @@ from mayan.apps.permissions import PermissionNamespace
namespace = PermissionNamespace(label=_('Documents'), name='documents')
permission_document_create = namespace.add_permission(
name='document_create', label=_('Create documents')
)
permission_document_delete = namespace.add_permission(
name='document_delete', label=_('Delete documents')
label=_('Create documents'), name='document_create'
)
permission_document_trash = namespace.add_permission(
name='document_trash', label=_('Trash documents')
label=_('Trash documents'), name='document_trash'
)
permission_document_download = namespace.add_permission(
name='document_download', label=_('Download documents')
label=_('Download documents'), name='document_download'
)
permission_document_edit = namespace.add_permission(
name='document_edit', label=_('Edit documents')
label=_('Edit documents'), name='document_edit'
)
permission_document_new_version = namespace.add_permission(
name='document_new_version', label=_('Create new document versions')
label=_('Create new document versions'), name='document_new_version'
)
permission_document_properties_edit = namespace.add_permission(
name='document_properties_edit', label=_('Edit document properties')
label=_('Edit document properties'), name='document_properties_edit'
)
permission_document_print = namespace.add_permission(
name='document_print', label=_('Print documents')
)
permission_document_restore = namespace.add_permission(
name='document_restore', label=_('Restore trashed document')
label=_('Print documents'), name='document_print'
)
permission_document_tools = namespace.add_permission(
name='document_tools', label=_('Execute document modifying tools')
label=_('Execute document modifying tools'), name='document_tools'
)
permission_document_version_revert = namespace.add_permission(
name='document_version_revert',
label=_('Revert documents to a previous version')
label=_('Revert documents to a previous version'),
name='document_version_revert'
)
permission_document_version_view = namespace.add_permission(
name='document_version_view',
label=_('View documents\' versions list')
label=_('View documents\' versions list'),
name='document_version_view'
)
permission_document_view = namespace.add_permission(
name='document_view', label=_('View documents')
label=_('View documents'), name='document_view'
)
permission_empty_trash = namespace.add_permission(
name='document_empty_trash', label=_('Empty trash')
label=_('Empty trash'), name='document_empty_trash'
)
permission_trashed_document_delete = namespace.add_permission(
label=_('Delete trashed documents'), name='document_delete'
)
permission_trashed_document_restore = namespace.add_permission(
label=_('Restore trashed document'), name='document_restore'
)
setup_namespace = PermissionNamespace(
label=_('Document types'), name='documents_types'
)
permission_document_type_create = setup_namespace.add_permission(
name='document_type_create', label=_('Create document types')
label=_('Create document types'), name='document_type_create'
)
permission_document_type_delete = setup_namespace.add_permission(
name='document_type_delete', label=_('Delete document types')
label=_('Delete document types'), name='document_type_delete'
)
permission_document_type_edit = setup_namespace.add_permission(
name='document_type_edit', label=_('Edit document types')
label=_('Edit document types'), name='document_type_edit'
)
permission_document_type_view = setup_namespace.add_permission(
name='document_type_view', label=_('View document types')
label=_('View document types'), name='document_type_view'
)

View File

@@ -6,55 +6,55 @@ from mayan.apps.common.queues import queue_tools
from mayan.apps.task_manager.classes import CeleryQueue
queue_converter = CeleryQueue(
name='converter', label=_('Converter'), transient=True
label=_('Converter'), name='converter', transient=True
)
queue_documents_periodic = CeleryQueue(
name='documents_periodic', label=_('Documents periodic'), transient=True
label=_('Documents periodic'), name='documents_periodic', transient=True
)
queue_uploads = CeleryQueue(
name='uploads', label=_('Uploads')
label=_('Uploads'), name='uploads'
)
queue_documents = CeleryQueue(
name='documents', label=_('Documents')
label=_('Documents'), name='documents'
)
queue_converter.add_task_type(
name='mayan.apps.documents.tasks.task_generate_document_page_image',
label=_('Generate document page image')
label=_('Generate document page image'),
name='mayan.apps.documents.tasks.task_generate_document_page_image'
)
queue_documents.add_task_type(
name='mayan.apps.documents.tasks.task_delete_document',
label=_('Delete a document')
label=_('Delete a document'),
name='mayan.apps.documents.tasks.task_delete_document'
)
queue_documents.add_task_type(
name='mayan.apps.documents.tasks.task_clean_empty_duplicate_lists',
label=_('Clean empty duplicate lists')
label=_('Clean empty duplicate lists'),
name='mayan.apps.documents.tasks.task_clean_empty_duplicate_lists'
)
queue_documents_periodic.add_task_type(
name='mayan.apps.documents.tasks.task_check_delete_periods',
label=_('Check document type delete periods')
label=_('Check document type delete periods'),
name='mayan.apps.documents.tasks.task_check_delete_periods'
)
queue_documents_periodic.add_task_type(
name='mayan.apps.documents.tasks.task_check_trash_periods',
label=_('Check document type trash periods')
label=_('Check document type trash periods'),
name='mayan.apps.documents.tasks.task_check_trash_periods'
)
queue_documents_periodic.add_task_type(
name='mayan.apps.documents.tasks.task_delete_stubs',
label=_('Delete document stubs')
label=_('Delete document stubs'),
name='mayan.apps.documents.tasks.task_delete_stubs'
)
queue_tools.add_task_type(
name='mayan.apps.documents.tasks.task_clear_image_cache',
label=_('Clear image cache')
label=_('Clear image cache'),
name='mayan.apps.documents.tasks.task_clear_image_cache'
)
queue_uploads.add_task_type(
name='mayan.apps.documents.tasks.task_update_page_count',
label=_('Update document page count')
label=_('Update document page count'),
name='mayan.apps.documents.tasks.task_update_page_count'
)
queue_uploads.add_task_type(
name='mayan.apps.documents.tasks.task_upload_new_version',
label=_('Upload new document version')
label=_('Upload new document version'),
name='mayan.apps.documents.tasks.task_upload_new_version'
)

View File

@@ -6,6 +6,7 @@ from rest_framework import serializers
from rest_framework.reverse import reverse
from mayan.apps.common.models import SharedUploadedFile
from mayan.apps.rest_api.relations import MultiKwargHyperlinkedIdentityField
from .models import (
Document, DocumentPage, DocumentType, DocumentTypeFilename,
@@ -16,40 +17,80 @@ from .tasks import task_upload_new_version
class DocumentPageSerializer(serializers.HyperlinkedModelSerializer):
document_version_url = serializers.SerializerMethodField()
image_url = serializers.SerializerMethodField()
url = serializers.SerializerMethodField()
#document_versions_url = serializers.SerializerMethodField()
image_url = MultiKwargHyperlinkedIdentityField(
view_kwargs=(
{
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_page_id',
},
{
'lookup_field': 'document.pk', 'lookup_url_kwarg': 'document_id',
},
{
'lookup_field': 'document_version_id', 'lookup_url_kwarg': 'document_version_id',
},
),
view_name='rest_api:document_page-image'
)
#url = serializers.SerializerMethodField()
document_version_url = MultiKwargHyperlinkedIdentityField(
view_kwargs=(
{
'lookup_field': 'document_version_id', 'lookup_url_kwarg': 'document_version_id',
},
{
'lookup_field': 'document.pk', 'lookup_url_kwarg': 'document_id',
}
),
view_name='rest_api:document_version-detail'
)
url = MultiKwargHyperlinkedIdentityField(
view_kwargs=(
{
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_page_id',
},
{
'lookup_field': 'document.pk', 'lookup_url_kwarg': 'document_id',
},
{
'lookup_field': 'document_version_id', 'lookup_url_kwarg': 'document_version_id',
},
),
view_name='rest_api:document_page-detail'
)
class Meta:
fields = ('document_version_url', 'image_url', 'page_number', 'url')
#fields = ('document_version_url', 'page_number', 'url')
model = DocumentPage
def get_document_version_url(self, instance):
"""
def get_document_versions_url(self, instance):
return reverse(
viewname='rest_api:documentversion-detail', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.document_version.pk
'document_id': instance.document.pk,
'document_version_id': instance.document_version.pk
}, request=self.context['request'], format=self.context['format']
)
def get_image_url(self, instance):
return reverse(
viewname='rest_api:documentpage-image', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.document_version.pk,
'document_page_pk': instance.pk,
'document_id': instance.document.pk,
'document_version_id': instance.document_version.pk,
'document_page_id': instance.pk,
}, request=self.context['request'], format=self.context['format']
)
def get_url(self, instance):
return reverse(
viewname='rest_api:documentpage-detail', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.document_version.pk,
'document_page_pk': instance.pk,
'document_id': instance.document.pk,
'document_version_id': instance.document_version.pk,
'document_page_id': instance.pk,
}, request=self.context['request'], format=self.context['format']
)
"""
class DocumentTypeFilenameSerializer(serializers.ModelSerializer):
class Meta:
@@ -59,33 +100,35 @@ class DocumentTypeFilenameSerializer(serializers.ModelSerializer):
class DocumentTypeSerializer(serializers.HyperlinkedModelSerializer):
documents_url = serializers.HyperlinkedIdentityField(
lookup_field='pk', lookup_url_kwarg='document_type_pk',
view_name='rest_api:documenttype-document-list'
lookup_url_kwarg='document_type_id',
view_name='rest_api:document_type-document-list'
)
documents_count = serializers.SerializerMethodField()
filenames = DocumentTypeFilenameSerializer(many=True, read_only=True)
#documents_count = serializers.SerializerMethodField()
#filenames = DocumentTypeFilenameSerializer(many=True, read_only=True)
class Meta:
extra_kwargs = {
'url': {
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_type_pk',
'view_name': 'rest_api:documenttype-detail'
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_type_id',
'view_name': 'rest_api:document_type-detail'
}
}
fields = (
'delete_time_period', 'delete_time_unit', 'documents_url',
'documents_count', 'id', 'label', 'filenames', 'trash_time_period',
#'delete_time_period', 'delete_time_unit',
#'documents_count', 'id', 'label', 'filenames', 'trash_time_period',
'id', 'label', 'trash_time_period',
'trash_time_unit', 'url'
)
model = DocumentType
def get_documents_count(self, obj):
return obj.documents.count()
#def get_documents_count(self, obj):
# return obj.documents.count()
"""
class WritableDocumentTypeSerializer(serializers.ModelSerializer):
documents_url = serializers.HyperlinkedIdentityField(
lookup_field='pk', lookup_url_kwarg='document_type_pk',
lookup_field='pk', lookup_url_kwarg='document_type_id',
view_name='rest_api:documenttype-document-list'
)
documents_count = serializers.SerializerMethodField()
@@ -93,7 +136,7 @@ class WritableDocumentTypeSerializer(serializers.ModelSerializer):
class Meta:
extra_kwargs = {
'url': {
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_type_pk',
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_type_id',
'view_name': 'rest_api:documenttype-detail'
}
}
@@ -106,26 +149,69 @@ class WritableDocumentTypeSerializer(serializers.ModelSerializer):
def get_documents_count(self, obj):
return obj.documents.count()
"""
class DocumentVersionSerializer(serializers.HyperlinkedModelSerializer):
document_url = serializers.SerializerMethodField()
download_url = serializers.SerializerMethodField()
pages_url = serializers.SerializerMethodField()
#document_url = serializers.SerializerMethodField()
#download_url = serializers.SerializerMethodField()
document_url = serializers.HyperlinkedIdentityField(
lookup_field='document_id', lookup_url_kwarg='document_id',
view_name='rest_api:document-detail'
)
#pages_url = serializers.SerializerMethodField()
pages_url = MultiKwargHyperlinkedIdentityField(
view_kwargs=(
{
'lookup_field': 'document_id', 'lookup_url_kwarg': 'document_id',
},
{
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_version_id',
}
),
view_name='rest_api:document_page-list'
)
size = serializers.SerializerMethodField()
url = serializers.SerializerMethodField()
#url = serializers.SerializerMethodField()
url = MultiKwargHyperlinkedIdentityField(
view_kwargs=(
{
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_version_id',
},
{
'lookup_field': 'document_id', 'lookup_url_kwarg': 'document_id',
},
),
view_name='rest_api:document_version-detail'
)
class Meta:
extra_kwargs = {
'document': {
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_pk',
'view_name': 'rest_api:document-detail'
},
#'document': {
# 'lookup_field': 'pk', 'lookup_url_kwarg': 'document_id',
# 'view_name': 'rest_api:document-detail'
#},
'file': {'use_url': False},
#'url': {
# 'view_kwargs': (
# {
# 'lookup_field': 'pk', 'lookup_url_kwarg': 'document_version_id',
# },
# {
# 'lookup_field': 'document__pk', 'lookup_url_kwarg': 'document_id',
# },
# ),
# #'lookup_field': 'pk', 'lookup_url_kwarg': 'document_version_id',
# 'view_name': 'rest_api:document_version-detail'
#},
}
fields = (
'checksum', 'comment', 'document_url', 'download_url', 'encoding',
#'checksum', 'comment', 'document_url', 'download_url', 'encoding',
'checksum', 'comment', 'document_url', 'encoding',
#'checksum', 'comment', 'encoding',
'file', 'mimetype', 'pages_url', 'size', 'timestamp', 'url'
#'file', 'mimetype', 'size', 'timestamp', 'url'
)
model = DocumentVersion
read_only_fields = ('document', 'file', 'size')
@@ -133,38 +219,62 @@ class DocumentVersionSerializer(serializers.HyperlinkedModelSerializer):
def get_size(self, instance):
return instance.size
def build_url_field(self, field_name, model_class):
"""
Create a field representing the object's own URL.
"""
field_class = self.serializer_url_field
field_kwargs = {'kwargs': 1}
return field_class, field_kwargs
"""
def get_document_url(self, instance):
return reverse(
viewname='rest_api:document-detail', kwargs={
'document_pk': instance.document.pk
}, request=self.context['request'], format=self.context['format']
'document_id': instance.document.pk
}, request=self.context['request']#, format=self.context['format']
)
def get_download_url(self, instance):
return reverse(
viewname='rest_api:documentversion-download', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.pk
}, request=self.context['request'], format=self.context['format']
viewname='rest_api:document_version-download', kwargs={
'document_id': instance.document.pk,
'document_version_id': instance.pk
}, request=self.context['request']#, format=self.context['format']
)
def get_pages_url(self, instance):
return reverse(
viewname='rest_api:documentversion-page-list', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.pk
}, request=self.context['request'], format=self.context['format']
viewname='rest_api:document_version-page-list', kwargs={
'document_id': instance.document.pk,
'document_version_id': instance.pk
}, request=self.context['request']#, format=self.context['format']
)
def get_url(self, instance):
def get_url(self, obj, view_name, request, format):
print ' obj, view_name, request, format', obj, view_name, request, format
# Unsaved objects will not yet have a valid URL.
if hasattr(obj, 'pk') and obj.pk in (None, ''):
return None
lookup_value = getattr(obj, self.lookup_field)
kwargs = {self.lookup_url_kwarg: lookup_value}
return self.reverse(view_name, kwargs=kwargs, request=request, format=format)
"""
"""
def get_url(self, instance, *args, **kwargs):
print ', *args, **kwargs', args, kwargs
return reverse(
viewname='rest_api:documentversion-detail', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.pk
}, request=self.context['request'], format=self.context['format']
viewname='rest_api:document_version-detail', kwargs={
'document_id': instance.document.pk,
'document_version_id': instance.pk
}, request=self.context['request']#, format=self.context['format']
)
"""
"""
class WritableDocumentVersionSerializer(serializers.ModelSerializer):
document_url = serializers.SerializerMethodField()
download_url = serializers.SerializerMethodField()
@@ -185,31 +295,31 @@ class WritableDocumentVersionSerializer(serializers.ModelSerializer):
def get_document_url(self, instance):
return reverse(
viewname='rest_api:document-detail', kwargs={
'document_pk': instance.document.pk
'document_id': instance.document.pk
}, request=self.context['request'], format=self.context['format']
)
def get_download_url(self, instance):
return reverse(
viewname='rest_api:documentversion-download', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.pk
'document_id': instance.document.pk,
'document_version_id': instance.pk
}, request=self.context['request'], format=self.context['format']
)
def get_pages_url(self, instance):
return reverse(
viewname='rest_api:documentversion-page-list', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.pk
'document_id': instance.document.pk,
'document_version_id': instance.pk
}, request=self.context['request'], format=self.context['format']
)
def get_url(self, instance):
return reverse(
viewname='rest_api:documentversion-detail', kwargs={
'document_pk': instance.document.pk,
'document_version_pk': instance.pk
'document_id': instance.document.pk,
'document_version_id': instance.pk
}, request=self.context['request'], format=self.context['format']
)
@@ -228,23 +338,23 @@ class NewDocumentVersionSerializer(serializers.Serializer):
document_id=document.pk,
shared_uploaded_file_id=shared_uploaded_file.pk, user_id=_user.pk
)
"""
class DeletedDocumentSerializer(serializers.HyperlinkedModelSerializer):
document_type_label = serializers.SerializerMethodField()
restore = serializers.HyperlinkedIdentityField(
lookup_field='pk', lookup_url_kwarg='document_pk',
lookup_field='pk', lookup_url_kwarg='document_id',
view_name='rest_api:trasheddocument-restore'
)
class Meta:
extra_kwargs = {
'document_type': {
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_type_pk',
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_type_id',
'view_name': 'rest_api:documenttype-detail'
},
'url': {
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_pk',
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_id',
'view_name': 'rest_api:trasheddocument-detail'
}
}
@@ -264,41 +374,49 @@ class DeletedDocumentSerializer(serializers.HyperlinkedModelSerializer):
class DocumentSerializer(serializers.HyperlinkedModelSerializer):
document_type = DocumentTypeSerializer()
document_type = DocumentTypeSerializer(read_only=True)
#document_type_url = serializers.HyperlinkedIdentityField(
# lookup_field='document_type_id', lookup_url_kwarg='document_type_id',
# view_name='rest_api:document_type-detail'
#)
latest_version = DocumentVersionSerializer(many=False, read_only=True)
versions_url = serializers.HyperlinkedIdentityField(
lookup_field='pk', lookup_url_kwarg='document_pk',
view_name='rest_api:document-version-list'
lookup_field='pk', lookup_url_kwarg='document_id',
view_name='rest_api:document_version-list'
)
#view_name='rest_api:document_type-document-list'
class Meta:
extra_kwargs = {
'document_type': {
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_type_pk',
'view_name': 'rest_api:documenttype-detail'
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_type_id',
'view_name': 'rest_api:document_type-detail'
},
'url': {
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_pk',
'lookup_field': 'pk', 'lookup_url_kwarg': 'document_id',
'view_name': 'rest_api:document-detail'
}
}
fields = (
'date_added', 'description', 'document_type', 'id', 'label',
#'date_added', 'description', 'document_type_url', 'id', 'label',
'language', 'latest_version', 'url', 'uuid', 'versions_url',
#'language', 'url', 'uuid', 'versions_url'
)
model = Document
read_only_fields = ('document_type',)
#read_only_fields = ('document_type', 'label')
"""
class WritableDocumentSerializer(serializers.ModelSerializer):
document_type = DocumentTypeSerializer(read_only=True)
latest_version = DocumentVersionSerializer(many=False, read_only=True)
versions = serializers.HyperlinkedIdentityField(
lookup_field='pk', lookup_url_kwarg='document_pk',
lookup_field='pk', lookup_url_kwarg='document_id',
view_name='rest_api:document-version-list'
)
url = serializers.HyperlinkedIdentityField(
lookup_field='pk', lookup_url_kwarg='document_pk',
lookup_field='pk', lookup_url_kwarg='document_id',
view_name='rest_api:document-detail',
)
@@ -344,7 +462,7 @@ class NewDocumentSerializer(serializers.ModelSerializer):
'description', 'document_type', 'id', 'file', 'label', 'language',
)
model = Document
"""
class RecentDocumentSerializer(serializers.ModelSerializer):
class Meta:

View File

@@ -13,7 +13,7 @@ from .literals import (
)
from .utils import callback_update_cache_size
namespace = Namespace(name='documents', label=_('Documents'))
namespace = Namespace(label=_('Documents'), name='documents')
setting_document_cache_maximum_size = namespace.add_setting(
global_name='DOCUMENTS_CACHE_MAXIMUM_SIZE',

View File

@@ -2,11 +2,11 @@ from __future__ import unicode_literals
from django.dispatch import Signal
post_version_upload = Signal(providing_args=('instance',), use_caching=True)
post_document_created = Signal(providing_args=('instance',), use_caching=True)
post_document_type_change = Signal(
providing_args=('instance',), use_caching=True
)
post_document_created = Signal(providing_args=('instance',), use_caching=True)
post_initial_document_type = Signal(
providing_args=('instance',), use_caching=True
)
post_version_upload = Signal(providing_args=('instance',), use_caching=True)

View File

@@ -68,9 +68,8 @@ def new_documents_this_month(user=None):
queryset = Document.objects.all()
if user:
queryset = AccessControlList.objects.filter_by_access(
permission=permission_document_view, user=user,
queryset=queryset
queryset = AccessControlList.objects.restrict_queryset(
permission=permission_document_view, queryset=queryset, user=user
)
qss = qsstats.QuerySetStats(queryset, 'date_added')
@@ -110,9 +109,9 @@ def new_document_pages_this_month(user=None):
queryset = DocumentPage.objects.all()
if user:
queryset = AccessControlList.objects.filter_by_access(
permission=permission_document_view, user=user,
queryset=queryset
queryset = AccessControlList.objects.restrict_queryset(
permission=permission_document_view, queryset=queryset,
user=user
)
qss = qsstats.QuerySetStats(
@@ -230,44 +229,44 @@ def total_document_page_per_month():
namespace = StatisticNamespace(slug='documents', label=_('Documents'))
namespace.add_statistic(
klass=StatisticLineChart,
slug='new-documents-per-month',
label=_('New documents per month'),
func=new_documents_per_month,
minute='0'
klass=StatisticLineChart,
label=_('New documents per month'),
minute='0',
slug='new-documents-per-month'
)
namespace.add_statistic(
klass=StatisticLineChart,
slug='new-document-versions-per-month',
label=_('New document versions per month'),
func=new_document_versions_per_month,
minute='0'
klass=StatisticLineChart,
label=_('New document versions per month'),
minute='0',
slug='new-document-versions-per-month'
)
namespace.add_statistic(
klass=StatisticLineChart,
slug='new-document-pages-per-month',
label=_('New document pages per month'),
func=new_document_pages_per_month,
minute='0'
klass=StatisticLineChart,
label=_('New document pages per month'),
minute='0',
slug='new-document-pages-per-month'
)
namespace.add_statistic(
klass=StatisticLineChart,
slug='total-documents-at-each-month',
label=_('Total documents at each month'),
func=total_document_per_month,
minute='0'
klass=StatisticLineChart,
label=_('Total documents at each month'),
minute='0',
slug='total-documents-at-each-month'
)
namespace.add_statistic(
klass=StatisticLineChart,
slug='total-document-versions-at-each-month',
label=_('Total document versions at each month'),
func=total_document_version_per_month,
minute='0'
klass=StatisticLineChart,
label=_('Total document versions at each month'),
minute='0',
slug='total-document-versions-at-each-month'
)
namespace.add_statistic(
klass=StatisticLineChart,
slug='total-document-pages-at-each-month',
label=_('Total document pages at each month'),
func=total_document_page_per_month,
minute='0'
klass=StatisticLineChart,
label=_('Total document pages at each month'),
minute='0',
slug='total-document-pages-at-each-month'
)

View File

@@ -58,14 +58,14 @@ def task_clear_image_cache():
@app.task(ignore_result=True)
def task_delete_document(deleted_document_id):
DeletedDocument = apps.get_model(
app_label='documents', model_name='DeletedDocument'
def task_delete_document(trashed_document_id):
TrashedDocument = apps.get_model(
app_label='documents', model_name='TrashedDocument'
)
logger.debug('Executing')
deleted_document = DeletedDocument.objects.get(pk=deleted_document_id)
deleted_document.delete()
trashed_document = TrashedDocument.objects.get(pk=trashed_document_id)
trashed_document.delete()
logger.debug('Finshed')

View File

@@ -18,27 +18,25 @@ class DocumentTestMixin(object):
auto_create_document_type = True
auto_upload_document = True
test_document_filename = TEST_SMALL_DOCUMENT_FILENAME
test_document_path = None
def _create_document_type(self):
self.document_type = DocumentType.objects.create(
label=TEST_DOCUMENT_TYPE_LABEL
)
def upload_document(self, filename=None):
self._calculate_test_document_path()
with open(self.test_document_path, mode='rb') as file_object:
document = self.document_type.new_document(
file_object=file_object,
label=filename or self.test_document_filename
)
return document
def _create_document(self, *args, **kwargs):
"""
Alias for upload_document()
"""
self.test_document = self.upload_document(*args, **kwargs)
def _calculate_test_document_path(self):
self.test_document_path = os.path.join(
settings.BASE_DIR, 'apps', 'documents', 'tests', 'contrib',
'sample_documents', self.test_document_filename
)
if not self.test_document_path:
self.test_document_path = os.path.join(
settings.BASE_DIR, 'apps', 'documents', 'tests', 'contrib',
'sample_documents', self.test_document_filename
)
def setUp(self):
super(DocumentTestMixin, self).setUp()
@@ -54,6 +52,18 @@ class DocumentTestMixin(object):
document_type.delete()
super(DocumentTestMixin, self).tearDown()
def upload_document(self, document_type=None, filename=None):
self._calculate_test_document_path()
document_type = document_type or self.document_type
with open(self.test_document_path, mode='rb') as file_object:
document = document_type.new_document(
file_object=file_object,
label=filename or self.test_document_filename
)
return document
class DocumentTypeQuickLabelTestMixin(object):
def _create_quick_label(self):

View File

@@ -11,10 +11,10 @@ from mayan.apps.rest_api.tests import BaseAPITestCase
from ..models import Document, DocumentType
from ..permissions import (
permission_document_create, permission_document_delete,
permission_document_download, permission_document_edit,
permission_document_new_version, permission_document_properties_edit,
permission_document_restore, permission_document_trash,
permission_document_create, permission_document_download,
permission_document_edit, permission_document_new_version,
permission_document_properties_edit, permission_document_trash,
permission_trashed_document_delete, permission_trashed_document_restore,
permission_document_type_create, permission_document_type_delete,
permission_document_type_edit, permission_document_version_revert,
permission_document_version_view, permission_document_view
@@ -61,7 +61,7 @@ class DocumentTypeAPITestCase(BaseAPITestCase):
def _request_document_type_patch(self):
return self.patch(
viewname='rest_api:documenttype-detail', kwargs={
'document_type_pk': self.document_type.pk
'document_type_id': self.document_type.pk
}, data={'label': TEST_DOCUMENT_TYPE_LABEL_EDITED}
)
@@ -90,7 +90,7 @@ class DocumentTypeAPITestCase(BaseAPITestCase):
def _request_document_type_put(self):
return self.put(
viewname='rest_api:documenttype-detail', kwargs={
'document_type_pk': self.document_type.pk
'document_type_id': self.document_type.pk
}, data={'label': TEST_DOCUMENT_TYPE_LABEL_EDITED}
)
@@ -119,7 +119,7 @@ class DocumentTypeAPITestCase(BaseAPITestCase):
def _request_document_type_delete(self):
return self.delete(
viewname='rest_api:documenttype-detail', kwargs={
'document_type_pk': self.document_type.pk
'document_type_id': self.document_type.pk
}
)
@@ -207,7 +207,7 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
with open(TEST_DOCUMENT_PATH, mode='rb') as file_descriptor:
return self.post(
viewname='rest_api:document-version-list', kwargs={
'document_pk': self.document.pk
'document_id': self.document.pk
}, data={
'comment': '', 'file': file_descriptor,
}
@@ -247,8 +247,8 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_version_revert(self):
return self.delete(
viewname='rest_api:documentversion-detail', kwargs={
'document_pk': self.document.pk,
'document_version_pk': self.document.latest_version.pk
'document_id': self.document.pk,
'document_version_id': self.document.latest_version.pk
}
)
@@ -275,7 +275,7 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_version_list(self):
return self.get(
viewname='rest_api:document-version-list',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_version_list_no_permission(self):
@@ -301,7 +301,7 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_download(self):
return self.get(
viewname='rest_api:document-download',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_download_no_permission(self):
@@ -329,8 +329,8 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_version_download(self):
return self.get(
viewname='rest_api:documentversion-download', kwargs={
'document_pk': self.document.pk,
'document_version_pk': self.document.latest_version.pk,
'document_id': self.document.pk,
'document_version_id': self.document.latest_version.pk,
}
)
@@ -362,8 +362,8 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
response = self.get(
viewname='rest_api:documentversion-download', kwargs={
'document_pk': self.document.pk,
'document_version_pk': self.document.latest_version.pk,
'document_id': self.document.pk,
'document_version_id': self.document.latest_version.pk,
}, data={'preserve_extension': True}
)
@@ -380,8 +380,8 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_version_edit_via_patch(self):
return self.patch(
viewname='rest_api:documentversion-detail', kwargs={
'document_pk': self.document.pk,
'document_version_pk': self.document.latest_version.pk,
'document_id': self.document.pk,
'document_version_id': self.document.latest_version.pk,
}, data={'comment': TEST_DOCUMENT_VERSION_COMMENT_EDITED}
)
@@ -407,8 +407,8 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_version_edit_via_put(self):
return self.put(
viewname='rest_api:documentversion-detail', kwargs={
'document_pk': self.document.pk,
'document_version_pk': self.document.latest_version.pk,
'document_id': self.document.pk,
'document_version_id': self.document.latest_version.pk,
}, data={'comment': TEST_DOCUMENT_VERSION_COMMENT_EDITED}
)
@@ -434,7 +434,7 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_description_edit_via_patch(self):
return self.patch(
viewname='rest_api:document-detail',
kwargs={'document_pk': self.document.pk},
kwargs={'document_id': self.document.pk},
data={'description': TEST_DOCUMENT_DESCRIPTION_EDITED}
)
@@ -459,7 +459,7 @@ class DocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_description_edit_via_put(self):
return self.put(
viewname='rest_api:document-detail',
kwargs={'document_pk': self.document.pk},
kwargs={'document_id': self.document.pk},
data={'description': TEST_DOCUMENT_DESCRIPTION_EDITED}
)
@@ -491,8 +491,8 @@ class DocumentPageAPITestCase(DocumentTestMixin, BaseAPITestCase):
page = self.document.pages.first()
return self.get(
viewname='rest_api:documentpage-image', kwargs={
'document_pk': page.document.pk,
'document_version_pk': page.document_version.pk, 'document_page_pk': page.pk
'document_id': page.document.pk,
'document_version_id': page.document_version.pk, 'document_page_id': page.pk
}
)
@@ -518,7 +518,7 @@ class TrashedDocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_document_move_to_trash(self):
return self.delete(
viewname='rest_api:document-detail',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_move_to_trash_no_permission(self):
@@ -540,7 +540,7 @@ class TrashedDocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_trashed_document_delete_view(self):
return self.delete(
viewname='rest_api:trasheddocument-detail',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_trashed_document_delete_from_trash_no_access(self):
@@ -554,7 +554,7 @@ class TrashedDocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def test_trashed_document_delete_from_trash_with_access(self):
self.document = self.upload_document()
self.document.delete()
self.grant_access(permission=permission_document_delete, obj=self.document)
self.grant_access(permission=permission_trashed_document_delete, obj=self.document)
response = self._request_trashed_document_delete_view()
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertEqual(Document.objects.count(), 0)
@@ -563,7 +563,7 @@ class TrashedDocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_trashed_document_detail_view(self):
return self.get(
viewname='rest_api:trasheddocument-detail',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_trashed_document_detail_view_no_access(self):
@@ -608,7 +608,7 @@ class TrashedDocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def _request_trashed_document_restore_view(self):
return self.post(
viewname='rest_api:trasheddocument-restore',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_trashed_document_restore_no_access(self):
@@ -622,7 +622,7 @@ class TrashedDocumentAPITestCase(DocumentTestMixin, BaseAPITestCase):
def test_trashed_document_restore_with_access(self):
self.document = self.upload_document()
self.document.delete()
self.grant_access(permission=permission_document_restore, obj=self.document)
self.grant_access(permission=permission_trashed_document_restore, obj=self.document)
response = self._request_trashed_document_restore_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(Document.trash.count(), 0)

View File

@@ -9,19 +9,15 @@ from .literals import TEST_MULTI_PAGE_TIFF
class DocumentPageViewTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(DocumentPageViewTestCase, self).setUp()
self.login_user()
def _document_page_list_view(self):
return self.get(
viewname='documents:document_pages',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_page_list_view_no_permission(self):
response = self._document_page_list_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_page_list_view_with_access(self):
self.grant_access(
@@ -32,18 +28,39 @@ class DocumentPageViewTestCase(GenericDocumentViewTestCase):
response=response, text=self.document.label, status_code=200
)
def _request_document_page_view(self, document_page):
return self.get(
viewname='documents:document_page_view', kwargs={
'document_page_id': document_page.pk
}
)
def test_document_page_view_no_permissions(self):
response = self._request_document_page_view(
document_page=self.document.pages.first()
)
self.assertEqual(response.status_code, 404)
def test_document_page_view_with_access(self):
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_page_view(
document_page=self.document.pages.first()
)
self.assertContains(
response=response, text=force_text(self.document.pages.first()),
status_code=200
)
class DocumentPageNavigationViewTestCase(GenericDocumentViewTestCase):
test_document_filename = TEST_MULTI_PAGE_TIFF
def setUp(self):
super(DocumentPageNavigationViewTestCase, self).setUp()
self.login_user()
def _request_document_page_navigation_next_view(self):
return self.get(
viewname='documents:document_page_navigation_next',
kwargs={'document_page_pk': self.document.pages.first().pk},
kwargs={'document_page_id': self.document.pages.first().pk},
follow=True
)
@@ -51,7 +68,6 @@ class DocumentPageNavigationViewTestCase(GenericDocumentViewTestCase):
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_page_navigation_next_view()
self.assertContains(
@@ -62,7 +78,7 @@ class DocumentPageNavigationViewTestCase(GenericDocumentViewTestCase):
def _request_document_page_navigation_last_view(self):
return self.get(
viewname='documents:document_page_navigation_last',
kwargs={'document_page_pk': self.document.pages.first().pk},
kwargs={'document_page_id': self.document.pages.first().pk},
follow=True
)
@@ -70,7 +86,6 @@ class DocumentPageNavigationViewTestCase(GenericDocumentViewTestCase):
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_page_navigation_last_view()
self.assertContains(
@@ -81,7 +96,7 @@ class DocumentPageNavigationViewTestCase(GenericDocumentViewTestCase):
def _request_document_page_navigation_previous_view(self):
return self.get(
viewname='documents:document_page_navigation_previous',
kwargs={'document_page_pk': self.document.pages.last().pk},
kwargs={'document_page_id': self.document.pages.last().pk},
follow=True
)
@@ -89,7 +104,6 @@ class DocumentPageNavigationViewTestCase(GenericDocumentViewTestCase):
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_page_navigation_previous_view()
self.assertContains(
@@ -100,7 +114,7 @@ class DocumentPageNavigationViewTestCase(GenericDocumentViewTestCase):
def _request_document_page_navigation_first_view(self):
return self.get(
viewname='documents:document_page_navigation_first',
kwargs={'document_page_pk': self.document.pages.last().pk},
kwargs={'document_page_id': self.document.pages.last().pk},
follow=True
)
@@ -108,7 +122,6 @@ class DocumentPageNavigationViewTestCase(GenericDocumentViewTestCase):
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_page_navigation_first_view()
self.assertContains(

View File

@@ -16,10 +16,6 @@ from .mixins import DocumentTypeQuickLabelTestMixin
class DocumentTypeViewsTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(DocumentTypeViewsTestCase, self).setUp()
self.login_user()
def _request_document_type_create(self):
return self.post(
viewname='documents:document_type_create',
@@ -50,12 +46,12 @@ class DocumentTypeViewsTestCase(GenericDocumentViewTestCase):
def _request_document_type_delete(self):
return self.post(
viewname='documents:document_type_delete',
kwargs={'document_type_pk': self.document_type.pk}
kwargs={'document_type_id': self.document_type.pk}
)
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)
def test_document_type_delete_view_with_access(self):
@@ -69,7 +65,7 @@ class DocumentTypeViewsTestCase(GenericDocumentViewTestCase):
def _request_document_type_edit(self):
return self.post(
viewname='documents:document_type_edit',
kwargs={'document_type_pk': self.document_type.pk},
kwargs={'document_type_id': self.document_type.pk},
data={
'label': TEST_DOCUMENT_TYPE_LABEL_EDITED,
'delete_time_period': DEFAULT_DELETE_PERIOD,
@@ -79,7 +75,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.document_type.refresh_from_db()
self.assertEqual(
self.document_type.label, TEST_DOCUMENT_TYPE_LABEL
@@ -98,14 +94,10 @@ class DocumentTypeViewsTestCase(GenericDocumentViewTestCase):
class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericDocumentViewTestCase):
def setUp(self):
super(DocumentTypeQuickLabelViewsTestCase, self).setUp()
self.login_user()
def _request_quick_label_create(self):
return self.post(
viewname='documents:document_type_filename_create',
kwargs={'document_type_pk': self.document_type.pk},
kwargs={'document_type_id': self.document_type.pk},
data={
'filename': TEST_DOCUMENT_TYPE_QUICK_LABEL,
}
@@ -117,7 +109,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.document_type.filenames.count(), 0)
def test_document_type_quick_label_create_with_access(self):
@@ -132,7 +124,7 @@ class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, Gener
def _request_quick_label_delete(self):
return self.post(
viewname='documents:document_type_filename_delete',
kwargs={'filename_pk': self.document_type_filename.pk},
kwargs={'filename_id': self.document_type_filename.pk},
)
def test_document_type_quick_label_delete_no_access(self):
@@ -158,7 +150,7 @@ class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, Gener
def _request_quick_label_edit(self):
return self.post(
viewname='documents:document_type_filename_edit',
kwargs={'filename_pk': self.document_type_filename.pk},
kwargs={'filename_id': self.document_type_filename.pk},
data={
'filename': TEST_DOCUMENT_TYPE_QUICK_LABEL_EDITED,
}
@@ -168,7 +160,7 @@ class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, Gener
self._create_quick_label()
response = self._request_quick_label_edit()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.document_type_filename.refresh_from_db()
self.assertEqual(
self.document_type_filename.filename,
@@ -193,13 +185,13 @@ class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, Gener
def _request_quick_label_list_view(self):
return self.get(
viewname='documents:document_type_filename_list',
kwargs={'document_type_pk': self.document_type.pk},
kwargs={'document_type_id': self.document_type.pk},
)
def test_document_type_quick_label_list_no_access(self):
self._create_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_quick_label()

View File

@@ -1,7 +1,10 @@
from __future__ import unicode_literals
from django.utils.encoding import force_text
from ..permissions import (
permission_document_version_revert, permission_document_version_view
permission_document_download, permission_document_version_revert,
permission_document_version_view
)
from .base import GenericDocumentViewTestCase
@@ -9,26 +12,101 @@ from .literals import TEST_SMALL_DOCUMENT_PATH, TEST_VERSION_COMMENT
class DocumentVersionTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(DocumentVersionTestCase, self).setUp()
self.login_user()
def _upload_new_version(self):
with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object:
self.document.new_version(
self.test_document_version = self.document.new_version(
comment=TEST_VERSION_COMMENT, file_object=file_object
)
def _request_document_version_detail_view(self):
return self.get(
viewname='documents:document_version_view',
kwargs={'document_version_id': self.test_document_version.pk}
)
def test_document_version_detail_no_permission(self):
self._upload_new_version()
response = self._request_document_version_detail_view()
self.assertEqual(response.status_code, 404)
def test_document_version_detail_with_access(self):
self._upload_new_version()
self.grant_access(
obj=self.document, permission=permission_document_version_view
)
response = self._request_document_version_detail_view()
self.assertEqual(response.status_code, 200)
def _request_document_version_download(self, data=None):
data = data or {}
return self.get(
viewname='documents:document_version_download', kwargs={
'document_version_id': self.document.latest_version.pk,
}, data=data
)
def test_document_version_download_view_no_permission(self):
response = self._request_document_version_download()
self.assertEqual(response.status_code, 404)
def test_document_version_download_view_with_permission(self):
# Set the expected_content_type for
# common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = '{}; charset=utf-8'.format(
self.document.latest_version.mimetype
)
self.grant_access(
obj=self.document, permission=permission_document_download
)
response = self._request_document_version_download()
self.assertEqual(response.status_code, 200)
with self.document.open() as file_object:
self.assert_download_response(
response=response, content=file_object.read(),
basename=force_text(self.document.latest_version),
mime_type='{}; charset=utf-8'.format(
self.document.latest_version.mimetype
)
)
def test_document_version_download_preserve_extension_view_with_permission(self):
# Set the expected_content_type for
# common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = '{}; charset=utf-8'.format(
self.document.latest_version.mimetype
)
self.grant_access(
obj=self.document, permission=permission_document_download
)
response = self._request_document_version_download(
data={'preserve_extension': True}
)
self.assertEqual(response.status_code, 200)
with self.document.open() as file_object:
self.assert_download_response(
response=response, content=file_object.read(),
basename=self.document.latest_version.get_rendered_string(
preserve_extension=True
), mime_type='{}; charset=utf-8'.format(
self.document.latest_version.mimetype
)
)
def _request_document_version_list_view(self):
return self.get(
viewname='documents:document_version_list',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_version_list_no_permission(self):
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()
@@ -40,32 +118,28 @@ class DocumentVersionTestCase(GenericDocumentViewTestCase):
response=response, text=TEST_VERSION_COMMENT, status_code=200
)
def _request_document_version_revert_view(self, document_version):
def _request_document_version_revert_view(self):
return self.post(
viewname='documents:document_version_revert',
kwargs={'document_version_pk': document_version.pk}
kwargs={'document_version_id': self.test_document_version_first.pk}
)
def test_document_version_revert_no_permission(self):
first_version = self.document.latest_version
self.test_document_version_first = self.document.latest_version
self._upload_new_version()
response = self._request_document_version_revert_view(
document_version=first_version
)
self.assertEqual(response.status_code, 403)
response = self._request_document_version_revert_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(self.document.versions.count(), 2)
def test_document_version_revert_with_access(self):
first_version = self.document.latest_version
self.test_document_version_first = self.document.latest_version
self._upload_new_version()
self.grant_access(
obj=self.document, permission=permission_document_version_revert
)
response = self._request_document_version_revert_view(
document_version=first_version
)
response = self._request_document_version_revert_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(self.document.versions.count(), 1)

View File

@@ -3,18 +3,16 @@ from __future__ import unicode_literals
import os
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import force_text
from mayan.apps.converter.models import Transformation
from mayan.apps.converter.permissions import permission_transformation_delete
from ..literals import PAGE_RANGE_ALL
from ..models import DeletedDocument, Document, DocumentType
from ..models import Document, DocumentType, FavoriteDocument
from ..permissions import (
permission_document_create, permission_document_download,
permission_document_print, permission_document_properties_edit,
permission_document_tools, permission_document_view,
permission_empty_trash
permission_document_tools, permission_document_view
)
from .base import GenericDocumentViewTestCase
@@ -26,19 +24,15 @@ from .mixins import DocumentTypeQuickLabelTestMixin
class DocumentsViewsTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(DocumentsViewsTestCase, self).setUp()
self.login_user()
def _request_document_properties_view(self):
return self.get(
viewname='documents:document_properties',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
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(
@@ -68,8 +62,8 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
def _request_document_type_edit(self, document_type):
return self.post(
viewname='documents:document_document_type_edit',
kwargs={'document_pk': self.document.pk},
viewname='documents:document_change_type',
kwargs={'document_id': self.document.pk},
data={'document_type': document_type.pk}
)
@@ -122,7 +116,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
def _request_multiple_document_type_edit(self, document_type):
return self.post(
viewname='documents:document_multiple_document_type_edit',
viewname='documents:document_multiple_change_type',
data={
'id_list': self.document.pk,
'document_type': document_type.pk
@@ -174,40 +168,51 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
Document.objects.first().document_type, document_type_2
)
def _request_document_download_form_view(self):
def _request_document_download_form_get_view(self):
return self.get(
viewname='documents:document_download_form',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_download_form_view_no_permission(self):
response = self._request_document_download_form_view()
def test_document_download_form_view_get_no_permission(self):
response = self._request_document_download_form_get_view()
self.assertEqual(response.status_code, 404)
self.assertNotContains(
response=response, text=self.document.label, status_code=200
)
def test_document_download_form_view_with_access(self):
def test_document_download_form_get_view_with_access(self):
self.grant_access(
obj=self.document, permission=permission_document_download
)
response = self._request_document_download_form_view()
response = self._request_document_download_form_get_view()
self.assertEqual(response.status_code, 200)
self.assertContains(
response=response, text=self.document.label, status_code=200
def _request_document_download_form_post_view(self):
return self.post(
viewname='documents:document_download_form',
kwargs={'document_id': self.document.pk}
)
def test_document_download_form_post_view_no_permission(self):
response = self._request_document_download_form_post_view()
self.assertEqual(response.status_code, 404)
def test_document_download_form_post_view_with_access(self):
self.grant_access(
obj=self.document, permission=permission_document_download
)
response = self._request_document_download_form_post_view()
self.assertEqual(response.status_code, 302)
def _request_document_download_view(self):
return self.get(
viewname='documents:document_download',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_download_view_no_permission(self):
response = self._request_document_download_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_download_view_with_permission(self):
def test_document_download_view_with_access(self):
# Set the expected_content_type for
# common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = '{}; charset=utf-8'.format(
@@ -235,7 +240,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
def test_document_multiple_download_view_no_permission(self):
response = self._request_document_multiple_download_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_multiple_download_view_with_permission(self):
# Set the expected_content_type for
@@ -257,70 +262,10 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
mime_type=self.document.file_mimetype
)
def _request_document_version_download(self, data=None):
data = data or {}
return self.get(
viewname='documents:document_version_download', kwargs={
'document_version_pk': self.document.latest_version.pk,
}, data=data
)
def test_document_version_download_view_no_permission(self):
response = self._request_document_version_download()
self.assertEqual(response.status_code, 403)
def test_document_version_download_view_with_permission(self):
# Set the expected_content_type for
# common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = '{}; charset=utf-8'.format(
self.document.latest_version.mimetype
)
self.grant_access(
obj=self.document, permission=permission_document_download
)
response = self._request_document_version_download()
self.assertEqual(response.status_code, 200)
with self.document.open() as file_object:
self.assert_download_response(
response=response, content=file_object.read(),
basename=force_text(self.document.latest_version),
mime_type='{}; charset=utf-8'.format(
self.document.latest_version.mimetype
)
)
def test_document_version_download_preserve_extension_view_with_permission(self):
# Set the expected_content_type for
# common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = '{}; charset=utf-8'.format(
self.document.latest_version.mimetype
)
self.grant_access(
obj=self.document, permission=permission_document_download
)
response = self._request_document_version_download(
data={'preserve_extension': True}
)
self.assertEqual(response.status_code, 200)
with self.document.open() as file_object:
self.assert_download_response(
response=response, content=file_object.read(),
basename=self.document.latest_version.get_rendered_string(
preserve_extension=True
), mime_type='{}; charset=utf-8'.format(
self.document.latest_version.mimetype
)
)
def _request_document_update_page_count_view(self):
return self.post(
viewname='documents:document_update_page_count',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_update_page_count_view_no_permission(self):
@@ -372,7 +317,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
def _request_document_clear_transformations_view(self):
return self.post(
viewname='documents:document_clear_transformations',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_clear_transformations_view_no_permission(self):
@@ -482,57 +427,10 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
Transformation.objects.get_for_model(document_page).count(), 0
)
def _request_empty_trash_view(self):
return self.post(viewname='documents:trash_can_empty')
def test_trash_can_empty_view_no_permission(self):
self.document.delete()
self.assertEqual(DeletedDocument.objects.count(), 1)
response = self._request_empty_trash_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(DeletedDocument.objects.count(), 1)
def test_trash_can_empty_view_with_permission(self):
self.document.delete()
self.assertEqual(DeletedDocument.objects.count(), 1)
self.grant_permission(permission=permission_empty_trash)
response = self._request_empty_trash_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 0)
def _request_document_page_view(self, document_page):
return self.get(
viewname='documents:document_page_view', kwargs={
'document_page_pk': document_page.pk
}
)
def test_document_page_view_no_permissions(self):
response = self._request_document_page_view(
document_page=self.document.pages.first()
)
self.assertEqual(response.status_code, 403)
def test_document_page_view_with_access(self):
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_page_view(
document_page=self.document.pages.first()
)
self.assertContains(
response=response, text=force_text(self.document.pages.first()),
status_code=200
)
def _request_document_print_view(self):
return self.get(
viewname='documents:document_print', kwargs={
'document_pk': self.document.pk
'document_id': self.document.pk
}, data={
'page_group': PAGE_RANGE_ALL
}
@@ -540,7 +438,7 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
def test_document_print_view_no_access(self):
response = self._request_document_print_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_print_view_with_access(self):
self.grant_access(
@@ -551,10 +449,6 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
class DocumentsQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericDocumentViewTestCase):
def setUp(self):
super(DocumentsQuickLabelViewsTestCase, self).setUp()
self.login_user()
def _request_document_quick_label_edit_view(self, extra_data=None):
data = {
'document_type_available_filenames': self.document_type_filename.pk,
@@ -566,14 +460,14 @@ class DocumentsQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericD
return self.post(
viewname='documents:document_edit',
kwargs={'document_pk': self.document.pk},
kwargs={'document_id': self.document.pk},
data=data
)
def test_document_quick_label_no_permission(self):
self._create_quick_label()
response = self._request_document_quick_label_edit_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.document.refresh_from_db()
def test_document_quick_label_with_access(self):
@@ -621,3 +515,72 @@ class DocumentsQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericD
self.assertEqual(
self.document.label, self.document_type_filename.filename
)
class FavoriteDocumentsTestCase(GenericDocumentViewTestCase):
def _request_document_add_to_favorites_view(self):
return self.post(
viewname='documents:document_add_to_favorites',
kwargs={'document_id': self.document.pk}
)
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(FavoriteDocument.objects.count(), 0)
def test_document_add_to_favorites_view_with_access(self):
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_add_to_favorites_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(FavoriteDocument.objects.count(), 1)
def _document_add_to_favorites(self):
FavoriteDocument.objects.add_for_user(
document=self.document, user=self._test_case_user
)
def _request_document_list_favorites(self):
return self.get(
viewname='documents:document_list_favorites',
)
def test_document_list_favorites_view_no_permission(self):
self._document_add_to_favorites()
response = self._request_document_list_favorites()
self.assertNotContains(
response=response, text=self.document.label, status_code=200
)
def test_document_list_favorites_view_with_access(self):
self._document_add_to_favorites()
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_list_favorites()
self.assertContains(
response=response, text=self.document.label, status_code=200
)
def _request_document_remove_from_favorites(self):
return self.post(
viewname='documents:document_remove_from_favorites',
kwargs={'document_id': self.document.pk}
)
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(FavoriteDocument.objects.count(), 1)
def test_document_remove_from_favorites_view_with_access(self):
self._document_add_to_favorites()
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_remove_from_favorites()
self.assertEqual(response.status_code, 302)
self.assertEqual(FavoriteDocument.objects.count(), 0)

View File

@@ -7,10 +7,6 @@ from .literals import TEST_SMALL_DOCUMENT_FILENAME, TEST_SMALL_DOCUMENT_PATH
class DuplicatedDocumentsViewsTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(DuplicatedDocumentsViewsTestCase, self).setUp()
self.login_user()
def _upload_duplicate_document(self):
with open(TEST_SMALL_DOCUMENT_PATH, mode='rb') as file_object:
self.document_duplicate = self.document_type.new_document(
@@ -23,7 +19,7 @@ class DuplicatedDocumentsViewsTestCase(GenericDocumentViewTestCase):
def _request_document_duplicates_list_view(self):
return self.get(
viewname='documents:document_duplicates_list',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_duplicated_document_list_no_permissions(self):
@@ -53,7 +49,7 @@ class DuplicatedDocumentsViewsTestCase(GenericDocumentViewTestCase):
self._upload_duplicate_document()
response = self._request_document_duplicates_list_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
def test_document_duplicates_list_with_access(self):
self._upload_duplicate_document()

View File

@@ -3,10 +3,6 @@ from __future__ import unicode_literals
from actstream.models import Action
from django_downloadview import assert_download_response
from mayan.apps.user_management.tests.literals import (
TEST_USER_PASSWORD, TEST_USER_USERNAME
)
from ..events import event_document_download, event_document_view
from ..permissions import (
permission_document_download, permission_document_view
@@ -21,38 +17,30 @@ TEST_TRANSFORMATION_ARGUMENT = 'degrees: 180'
class DocumentEventsTestCase(GenericDocumentViewTestCase):
def test_document_download_event_no_permissions(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
def _request_document_download_view(self):
return self.get(
viewname='documents:document_download',
kwargs={'document_id': self.document.pk}
)
def test_document_download_event_no_permissions(self):
Action.objects.all().delete()
response = self.get(
viewname='documents:document_download',
kwargs={'document_pk': self.document.pk}
)
response = self._request_document_download_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(list(Action.objects.any(obj=self.document)), [])
def test_document_download_event_with_permissions(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
Action.objects.all().delete()
self.role.permissions.add(
permission_document_download.stored_permission
self.grant_access(
obj=self.document, permission=permission_document_download
)
self.expected_content_type = 'image/png; charset=utf-8'
response = self.get(
viewname='documents:document_download',
kwargs={'document_pk': self.document.pk}
)
response = self._request_document_download_view()
# Download the file to close the file descriptor
with self.document.open() as file_object:
@@ -65,40 +53,31 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase):
self.assertEqual(event.verb, event_document_download.id)
self.assertEqual(event.target, self.document)
self.assertEqual(event.actor, self.user)
self.assertEqual(event.actor, self._test_case_user)
def _request_document_preview_view(self):
return self.get(
viewname='documents:document_preview',
kwargs={'document_id': self.document.pk}
)
def test_document_view_event_no_permissions(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
Action.objects.all().delete()
response = self.get(
viewname='documents:document_preview',
kwargs={'document_pk': self.document.pk}
)
response = self._request_document_preview_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 404)
self.assertEqual(list(Action.objects.any(obj=self.document)), [])
def test_document_view_event_with_permissions(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
def test_document_view_event_with_access(self):
Action.objects.all().delete()
self.role.permissions.add(
permission_document_view.stored_permission
)
self.get(
viewname='documents:document_preview',
kwargs={'document_pk': self.document.pk}
)
self.grant_access(obj=self.document, permission=permission_document_view)
response = self._request_document_preview_view()
self.assertEqual(response.status_code, 200)
event = Action.objects.any(obj=self.document).first()
self.assertEqual(event.verb, event_document_view.id)
self.assertEqual(event.target, self.document)
self.assertEqual(event.actor, self.user)
self.assertEqual(event.actor, self._test_case_user)

View File

@@ -4,14 +4,13 @@ import time
from django.urls import reverse
from mayan.apps.acls.models import AccessControlList
from ..links import (
link_document_restore, link_document_version_download,
link_trashed_document_restore, link_document_version_download,
link_document_version_revert
)
from ..models import TrashedDocument
from ..permissions import (
permission_document_download, permission_document_restore,
permission_document_download, permission_trashed_document_restore,
permission_document_version_revert
)
@@ -26,15 +25,13 @@ class DocumentsLinksTestCase(GenericDocumentViewTestCase):
self.assertTrue(self.document.versions.count(), 2)
self.login_user()
self.add_test_view(test_object=self.document.versions.first())
context = self.get_test_view()
resolved_link = link_document_version_revert.resolve(context=context)
self.assertEqual(resolved_link, None)
def test_document_version_revert_link_with_permission(self):
def test_document_version_revert_link_with_access(self):
# Needed by MySQL as milliseconds value is not store in timestamp
# field
time.sleep(1.01)
@@ -44,13 +41,8 @@ class DocumentsLinksTestCase(GenericDocumentViewTestCase):
self.assertTrue(self.document.versions.count(), 2)
self.login_user()
acl = AccessControlList.objects.create(
content_object=self.document, role=self.role
)
acl.permissions.add(
permission_document_version_revert.stored_permission
self.grant_access(
obj=self.document, permission=permission_document_version_revert
)
self.add_test_view(test_object=self.document.versions.first())
@@ -61,27 +53,22 @@ class DocumentsLinksTestCase(GenericDocumentViewTestCase):
self.assertEqual(
resolved_link.url,
reverse(
'documents:document_version_revert',
args=(self.document.versions.first().pk,)
viewname='documents:document_version_revert',
kwargs={'document_version_id': self.document.versions.first().pk}
)
)
def test_document_version_download_link_no_permission(self):
self.login_user()
self.add_test_view(test_object=self.document.latest_version)
context = self.get_test_view()
resolved_link = link_document_version_download.resolve(context=context)
self.assertEqual(resolved_link, None)
def test_document_version_download_link_with_permission(self):
self.login_user()
acl = AccessControlList.objects.create(
content_object=self.document, role=self.role
def test_document_version_download_link_with_access(self):
self.grant_access(
obj=self.document, permission=permission_document_download
)
acl.permissions.add(permission_document_download.stored_permission)
self.add_test_view(test_object=self.document.latest_version)
context = self.get_test_view()
@@ -91,45 +78,41 @@ class DocumentsLinksTestCase(GenericDocumentViewTestCase):
self.assertEqual(
resolved_link.url,
reverse(
'documents:document_version_download_form',
args=(self.document.latest_version.pk,)
viewname='documents:document_version_download_form',
kwargs={'document_version_id': self.document.latest_version.pk}
)
)
class DeletedDocumentsLinksTestCase(GenericDocumentViewTestCase):
def _request_trashed_document_restore_link(self):
self.add_test_view(
test_object=TrashedDocument.objects.get(pk=self.document.pk)
)
context = self.get_test_view()
return link_trashed_document_restore.resolve(context=context)
def test_deleted_document_restore_link_no_permission(self):
self.document.delete()
self.login_user()
self.add_test_view(test_object=self.document)
context = self.get_test_view()
resolved_link = link_document_restore.resolve(context=context)
resolved_link = self._request_trashed_document_restore_link()
self.assertEqual(resolved_link, None)
def test_deleted_document_restore_link_with_permission(self):
def test_deleted_document_restore_link_with_access(self):
self.document.delete()
self.login_user()
acl = AccessControlList.objects.create(
content_object=self.document, role=self.role
)
acl.permissions.add(
permission_document_restore.stored_permission
self.grant_access(
obj=self.document, permission=permission_trashed_document_restore
)
self.add_test_view(test_object=self.document)
context = self.get_test_view()
resolved_link = link_document_restore.resolve(context=context)
resolved_link = self._request_trashed_document_restore_link()
self.assertNotEqual(resolved_link, None)
self.assertEqual(
resolved_link.url,
reverse(
'documents:document_restore',
args=(self.document.pk,)
viewname='documents:trashed_document_restore',
kwargs={'trashed_document_id': self.document.pk}
)
)

View File

@@ -7,7 +7,7 @@ from mayan.apps.common.tests import BaseTestCase
from ..literals import STUB_EXPIRATION_INTERVAL
from ..models import (
DeletedDocument, Document, DocumentType, DuplicatedDocument
Document, DocumentType, DuplicatedDocument, TrashedDocument
)
from .base import GenericDocumentTestCase
@@ -58,12 +58,12 @@ class DocumentTestCase(DocumentTestMixin, BaseTestCase):
# Trash the document
self.document.delete()
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(TrashedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0)
# Restore the document
self.document.restore()
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(TrashedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 1)
def test_trashing_documents(self):
@@ -71,12 +71,12 @@ class DocumentTestCase(DocumentTestMixin, BaseTestCase):
# Trash the document
self.document.delete()
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(TrashedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0)
# Delete the document
self.document.delete()
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(TrashedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 0)
def test_auto_trashing(self):
@@ -94,12 +94,12 @@ class DocumentTestCase(DocumentTestMixin, BaseTestCase):
time.sleep(1.01)
self.assertEqual(Document.objects.count(), 1)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(TrashedDocument.objects.count(), 0)
DocumentType.objects.check_trash_periods()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(TrashedDocument.objects.count(), 1)
def test_auto_delete(self):
"""
@@ -112,12 +112,12 @@ class DocumentTestCase(DocumentTestMixin, BaseTestCase):
self.document_type.save()
self.assertEqual(Document.objects.count(), 1)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(TrashedDocument.objects.count(), 0)
self.document.delete()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(TrashedDocument.objects.count(), 1)
# Needed by MySQL as milliseconds value is not stored in timestamp
# field
@@ -126,7 +126,7 @@ class DocumentTestCase(DocumentTestMixin, BaseTestCase):
DocumentType.objects.check_delete_periods()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(TrashedDocument.objects.count(), 0)
class PDFCompatibilityTestCase(BaseTestCase):

View File

@@ -9,12 +9,12 @@ from mayan.apps.documents.tests import DocumentTestMixin
class DocumentSearchTestCase(DocumentTestMixin, BaseTestCase):
def _perform_document_page_search(self):
return document_page_search.search(
query_string={'q': self.document.label}, user=self.user
query_string={'q': self.document.label}, user=self._test_case_user
)
def _perform_document_search(self):
return document_search.search(
query_string={'q': self.document.label}, user=self.user
query_string={'q': self.document.label}, user=self._test_case_user
)
def test_document_page_search_no_access(self):

View File

@@ -1,56 +1,26 @@
from __future__ import unicode_literals
from ..models import DeletedDocument, Document
from ..models import Document, TrashedDocument
from ..permissions import (
permission_document_delete, permission_document_restore,
permission_document_trash, permission_document_view
permission_document_trash, permission_document_view,
permission_empty_trash, permission_trashed_document_delete,
permission_trashed_document_restore
)
from .base import GenericDocumentViewTestCase
class DeletedDocumentTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(DeletedDocumentTestCase, self).setUp()
self.login_user()
def _request_document_restore_view(self):
return self.post(
viewname='documents:document_restore',
kwargs={'document_pk': self.document.pk}
)
def test_document_restore_view_no_permission(self):
self.document.delete()
self.assertEqual(Document.objects.count(), 0)
response = self._request_document_restore_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0)
def test_document_restore_view_with_access(self):
self.document.delete()
self.assertEqual(Document.objects.count(), 0)
self.grant_access(
obj=self.document, permission=permission_document_restore
)
response = self._request_document_restore_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 1)
class TrashedDocumentTestCase(GenericDocumentViewTestCase):
def _request_document_trash_view(self):
return self.post(
viewname='documents:document_trash',
kwargs={'document_pk': self.document.pk}
kwargs={'document_id': self.document.pk}
)
def test_document_trash_no_permissions(self):
response = self._request_document_trash_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(response.status_code, 302)
self.assertEqual(TrashedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 1)
def test_document_trash_with_access(self):
@@ -60,58 +30,107 @@ class DeletedDocumentTestCase(GenericDocumentViewTestCase):
response = self._request_document_trash_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(DeletedDocument.objects.count(), 1)
self.assertEqual(TrashedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0)
def _request_document_delete_view(self):
def _request_trashed_document_restore_view(self):
return self.post(
viewname='documents:document_delete',
kwargs={'document_pk': self.document.pk}
viewname='documents:trashed_document_restore',
kwargs={'trashed_document_id': self.document.pk}
)
def test_document_delete_no_permissions(self):
def test_trashed_document_restore_view_no_permission(self):
self.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, 403)
response = self._request_trashed_document_restore_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(TrashedDocument.objects.count(), 1)
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
def test_document_delete_with_access(self):
def test_trashed_document_restore_view_with_access(self):
self.document.delete()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(DeletedDocument.objects.count(), 1)
self.grant_access(
obj=self.document, permission=permission_document_delete
obj=self.document, permission=permission_trashed_document_restore
)
response = self._request_trashed_document_restore_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(TrashedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 1)
def _request_trashed_document_delete_view(self):
return self.post(
viewname='documents:trashed_document_delete',
kwargs={'trashed_document_id': self.document.pk}
)
response = self._request_document_delete_view()
def test_trashed_document_delete_no_permissions(self):
self.document.delete()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(TrashedDocument.objects.count(), 1)
response = self._request_trashed_document_delete_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(DeletedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(TrashedDocument.objects.count(), 1)
def test_trashed_document_delete_with_access(self):
self.document.delete()
self.assertEqual(Document.objects.count(), 0)
self.assertEqual(TrashedDocument.objects.count(), 1)
self.grant_access(
obj=self.document, permission=permission_trashed_document_delete
)
response = self._request_trashed_document_delete_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(TrashedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 0)
def _request_document_list_deleted_view(self):
return self.get(viewname='documents:document_list_deleted')
def _request_trashed_document_list_view(self):
return self.get(viewname='documents:trashed_document_list')
def test_deleted_document_list_view_no_permissions(self):
def test_trashed_document_list_view_no_permissions(self):
self.document.delete()
response = self._request_document_list_deleted_view()
response = self._request_trashed_document_list_view()
self.assertNotContains(
response=response, text=self.document.label, status_code=200
)
def test_deleted_document_list_view_with_access(self):
def test_trashed_document_list_view_with_access(self):
self.document.delete()
self.grant_access(
obj=self.document, permission=permission_document_view
)
response = self._request_document_list_deleted_view()
response = self._request_trashed_document_list_view()
self.assertContains(
response=response, text=self.document.label, status_code=200
)
def _request_empty_trash_view(self):
return self.post(viewname='documents:trash_can_empty')
def test_trash_can_empty_view_no_permission(self):
self.document.delete()
self.assertEqual(TrashedDocument.objects.count(), 1)
response = self._request_empty_trash_view()
self.assertEqual(response.status_code, 403)
self.assertEqual(TrashedDocument.objects.count(), 1)
def test_trash_can_empty_view_with_permission(self):
self.document.delete()
self.assertEqual(TrashedDocument.objects.count(), 1)
self.grant_permission(permission=permission_empty_trash)
response = self._request_empty_trash_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(TrashedDocument.objects.count(), 0)
self.assertEqual(Document.objects.count(), 0)

View File

@@ -2,29 +2,34 @@ from __future__ import unicode_literals
from django.conf.urls import url
"""
from .api_views import (
APIDeletedDocumentListView, APIDeletedDocumentRestoreView,
APIDeletedDocumentView, APIDocumentDownloadView, APIDocumentListView,
APITrashedDocumentListView, APITrashedDocumentRestoreView,
APITrashedDocumentView, APIDocumentDownloadView, APIDocumentListView,
APIDocumentPageImageView, APIDocumentPageView,
APIDocumentTypeDocumentListView, APIDocumentTypeListView,
APIDocumentTypeView, APIDocumentVersionDownloadView,
APIDocumentVersionPageListView, APIDocumentVersionsListView,
APIDocumentVersionView, APIDocumentView, APIRecentDocumentListView
)
"""
from .api_views import (
DocumentPageViewSet, DocumentTypeViewSet, DocumentVersionViewSet,
DocumentViewSet
)
from .views import (
ClearImageCacheView, DeletedDocumentDeleteManyView,
DeletedDocumentDeleteView, DeletedDocumentListView,
DocumentDocumentTypeEditView, DocumentDownloadFormView,
ClearImageCacheView, DocumentChangeTypeView, DocumentDownloadFormView,
DocumentDownloadView, DocumentDuplicatesListView, DocumentEditView,
DocumentListView, DocumentPageListView, DocumentPageNavigationFirst,
DocumentPageNavigationLast, DocumentPageNavigationNext,
DocumentPageNavigationPrevious, DocumentPageRotateLeftView,
DocumentPageRotateRightView, DocumentPageView, DocumentPageViewResetView,
DocumentPageZoomInView, DocumentPageZoomOutView, DocumentPreviewView,
DocumentPrint, DocumentRestoreManyView, DocumentRestoreView,
DocumentTransformationsClearView, DocumentTransformationsCloneView,
DocumentTrashManyView, DocumentTrashView, DocumentTypeCreateView,
DocumentTypeDeleteView, DocumentTypeDocumentListView, DocumentTypeEditView,
DocumentPrintView, DocumentTransformationsClearView,
DocumentTransformationsCloneView, DocumentTrashView,
DocumentTypeCreateView, DocumentTypeDeleteView,
DocumentTypeDocumentListView, DocumentTypeEditView,
DocumentTypeFilenameCreateView, DocumentTypeFilenameDeleteView,
DocumentTypeFilenameEditView, DocumentTypeFilenameListView,
DocumentTypeListView, DocumentUpdatePageCountView,
@@ -33,12 +38,51 @@ from .views import (
DocumentView, DuplicatedDocumentListView, EmptyTrashCanView,
FavoriteAddView, FavoriteDocumentListView, FavoriteRemoveView,
RecentAccessDocumentListView, RecentAddedDocumentListView,
ScanDuplicatedDocuments
ScanDuplicatedDocuments, TrashedDocumentDeleteView, TrashedDocumentListView,
TrashedDocumentRestoreView
)
urlpatterns_trashed_documents = (
url(
regex=r'^documents/(?P<document_id>\d+)/trash/$',
name='document_trash', view=DocumentTrashView.as_view()
),
url(
regex=r'^documents/multiple/trash/$', name='document_multiple_trash',
view=DocumentTrashView.as_view()
),
url(
regex=r'^trashed_documents/$', name='trashed_document_list',
view=TrashedDocumentListView.as_view()
),
url(
regex=r'^trashed_documents/(?P<trashed_document_id>\d+)/restore/$',
name='trashed_document_restore',
view=TrashedDocumentRestoreView.as_view()
),
url(
regex=r'^trashed_documents/multiple/restore/$',
name='trashed_document_multiple_restore',
view=TrashedDocumentRestoreView.as_view()
),
url(
regex=r'^trashed_documents/(?P<trashed_document_id>\d+)/delete/$',
name='trashed_document_delete', view=TrashedDocumentDeleteView.as_view()
),
url(
regex=r'^trashed_documents/multiple/delete/$',
name='trashed_document_multiple_delete',
view=TrashedDocumentDeleteView.as_view()
),
url(
regex=r'^trash/empty/$', name='trash_can_empty',
view=EmptyTrashCanView.as_view()
)
)
urlpatterns = [
url(
regex=r'^documents/all/$', name='document_list',
regex=r'^documents/$', name='document_list',
view=DocumentListView.as_view()
),
url(
@@ -50,10 +94,8 @@ urlpatterns = [
regex=r'^documents/recent_added/$', name='document_list_recent_added',
view=RecentAddedDocumentListView.as_view()
),
url(
regex=r'^documents/deleted/$', name='document_list_deleted',
view=DeletedDocumentListView.as_view()
),
url(
regex=r'^documents/duplicated/$', name='duplicated_document_list',
view=DuplicatedDocumentListView.as_view()
@@ -63,20 +105,20 @@ urlpatterns = [
view=FavoriteDocumentListView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/preview/$',
regex=r'^documents/(?P<document_id>\d+)/preview/$',
name='document_preview', view=DocumentPreviewView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/properties/$',
regex=r'^documents/(?P<document_id>\d+)/properties/$',
name='document_properties', view=DocumentView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/duplicates/$',
regex=r'^documents/(?P<document_id>\d+)/duplicates/$',
name='document_duplicates_list',
view=DocumentDuplicatesListView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/add_to_favorites/$',
regex=r'^documents/(?P<document_id>\d+)/add_to_favorites/$',
name='document_add_to_favorites', view=FavoriteAddView.as_view()
),
url(
@@ -85,7 +127,7 @@ urlpatterns = [
view=FavoriteAddView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/remove_from_favorites/$',
regex=r'^documents/(?P<document_id>\d+)/remove_from_favorites/$',
name='document_remove_from_favorites',
view=FavoriteRemoveView.as_view()
),
@@ -95,50 +137,25 @@ urlpatterns = [
view=FavoriteRemoveView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/restore/$',
name='document_restore', view=DocumentRestoreView.as_view()
),
url(
regex=r'^documents/multiple/restore/$',
name='document_multiple_restore',
view=DocumentRestoreManyView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/delete/$',
name='document_delete', view=DeletedDocumentDeleteView.as_view()
),
url(
regex=r'^documents/multiple/delete/$', name='document_multiple_delete',
view=DeletedDocumentDeleteManyView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/type/$',
name='document_document_type_edit',
view=DocumentDocumentTypeEditView.as_view()
regex=r'^documents/(?P<document_id>\d+)/type/$',
name='document_change_type',
view=DocumentChangeTypeView.as_view()
),
url(
regex=r'^documents/multiple/type/$',
name='document_multiple_document_type_edit',
view=DocumentDocumentTypeEditView.as_view()
name='document_multiple_change_type',
view=DocumentChangeTypeView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/trash/$',
name='document_trash', view=DocumentTrashView.as_view()
),
url(
regex=r'^documents/multiple/trash/$', name='document_multiple_trash',
view=DocumentTrashManyView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/edit/$', name='document_edit',
regex=r'^documents/(?P<document_id>\d+)/edit/$', name='document_edit',
view=DocumentEditView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/print/$',
name='document_print', view=DocumentPrint.as_view()
regex=r'^documents/(?P<document_id>\d+)/print/$',
name='document_print', view=DocumentPrintView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/reset_page_count/$',
regex=r'^documents/(?P<document_id>\d+)/reset_page_count/$',
name='document_update_page_count',
view=DocumentUpdatePageCountView.as_view()
),
@@ -148,11 +165,11 @@ urlpatterns = [
view=DocumentUpdatePageCountView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/download/form/$',
regex=r'^documents/(?P<document_id>\d+)/download/form/$',
name='document_download_form', view=DocumentDownloadFormView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/download/$',
regex=r'^documents/(?P<document_id>\d+)/download/$',
name='document_download', view=DocumentDownloadView.as_view()
),
url(
@@ -165,46 +182,46 @@ urlpatterns = [
name='document_multiple_download', view=DocumentDownloadView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/clear_transformations/$',
regex=r'^documents/(?P<document_id>\d+)/transformations/clear/$',
name='document_clear_transformations',
view=DocumentTransformationsClearView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/clone_transformations/$',
regex=r'^documents/(?P<document_id>\d+)/transformations/clone/$',
name='document_clone_transformations',
view=DocumentTransformationsCloneView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/version/all/$',
regex=r'^documents/(?P<document_id>\d+)/versions/$',
name='document_version_list',
view=DocumentVersionListView.as_view()
),
url(
regex=r'^documents/versions/(?P<document_version_pk>\d+)/download/form/$',
regex=r'^documents/versions/(?P<document_version_id>\d+)/download/form/$',
name='document_version_download_form',
view=DocumentVersionDownloadFormView.as_view()
),
url(
regex=r'^documents/versions/(?P<document_version_pk>\d+)/$',
regex=r'^documents/versions/(?P<document_version_id>\d+)/$',
name='document_version_view', view=DocumentVersionView.as_view()
),
url(
regex=r'^documents/versions/(?P<document_version_pk>\d+)/download/$',
regex=r'^documents/versions/(?P<document_version_id>\d+)/download/$',
name='document_version_download',
view=DocumentVersionDownloadView.as_view()
),
url(
regex=r'^documents/versions/(?P<document_version_pk>\d+)/revert/$',
regex=r'^documents/versions/(?P<document_version_id>\d+)/revert/$',
name='document_version_revert',
view=DocumentVersionRevertView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/pages/$',
regex=r'^documents/(?P<document_id>\d+)/pages/$',
name='document_pages',
view=DocumentPageListView.as_view()
),
url(
regex=r'^documents/multiple/clear_transformations/$',
regex=r'^documents/multiple/transformations/clear/$',
name='document_multiple_clear_transformations',
view=DocumentTransformationsClearView.as_view()
),
@@ -213,96 +230,92 @@ urlpatterns = [
view=ClearImageCacheView.as_view()
),
url(
regex=r'^trash_can/empty/$', name='trash_can_empty',
view=EmptyTrashCanView.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/$',
name='document_page_view', view=DocumentPageView.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/navigation/next/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/navigation/next/$',
name='document_page_navigation_next',
view=DocumentPageNavigationNext.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/navigation/previous/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/navigation/previous/$',
name='document_page_navigation_previous',
view=DocumentPageNavigationPrevious.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/navigation/first/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/navigation/first/$',
name='document_page_navigation_first',
view=DocumentPageNavigationFirst.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/navigation/last/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/navigation/last/$',
name='document_page_navigation_last',
view=DocumentPageNavigationLast.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/zoom/in/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/zoom/in/$',
name='document_page_zoom_in', view=DocumentPageZoomInView.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/zoom/out/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/zoom/out/$',
name='document_page_zoom_out', view=DocumentPageZoomOutView.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/rotate/left/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/rotate/left/$',
name='document_page_rotate_left',
view=DocumentPageRotateLeftView.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/rotate/right/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/rotate/right/$',
name='document_page_rotate_right',
view=DocumentPageRotateRightView.as_view()
),
url(
regex=r'^pages/(?P<document_page_pk>\d+)/reset/$',
regex=r'^documents/pages/(?P<document_page_id>\d+)/reset/$',
name='document_page_view_reset',
view=DocumentPageViewResetView.as_view()
),
# Admin views
url(
regex=r'^types/$', name='document_type_list',
regex=r'^documents_types/$', name='document_type_list',
view=DocumentTypeListView.as_view()
),
url(
regex=r'^types/create/$', name='document_type_create',
regex=r'^documents_types/create/$', name='document_type_create',
view=DocumentTypeCreateView.as_view()
),
url(
regex=r'^types/(?P<document_type_pk>\d+)/edit/$', name='document_type_edit',
view=DocumentTypeEditView.as_view()
regex=r'^documents_types/(?P<document_type_id>\d+)/edit/$',
name='document_type_edit', view=DocumentTypeEditView.as_view()
),
url(
regex=r'^types/(?P<document_type_pk>\d+)/delete/$', name='document_type_delete',
view=DocumentTypeDeleteView.as_view()
regex=r'^documents_types/(?P<document_type_id>\d+)/delete/$',
name='document_type_delete', view=DocumentTypeDeleteView.as_view()
),
url(
regex=r'^types/(?P<document_type_pk>\d+)/documents/$',
regex=r'^documents_types/(?P<document_type_id>\d+)/documents/$',
name='document_type_document_list',
view=DocumentTypeDocumentListView.as_view()
),
url(
regex=r'^types/(?P<document_type_pk>\d+)/filenames/create/$',
name='document_type_filename_create',
view=DocumentTypeFilenameCreateView.as_view()
),
url(
regex=r'^types/(?P<document_type_pk>\d+)/filenames/$',
regex=r'^documents_types/(?P<document_type_id>\d+)/filenames/$',
name='document_type_filename_list',
view=DocumentTypeFilenameListView.as_view()
),
url(
regex=r'^types/filenames/(?P<filename_pk>\d+)/edit/$',
regex=r'^documents_types/(?P<document_type_id>\d+)/filenames/create/$',
name='document_type_filename_create',
view=DocumentTypeFilenameCreateView.as_view()
),
url(
regex=r'^documents_types/filenames/(?P<filename_id>\d+)/edit/$',
name='document_type_filename_edit',
view=DocumentTypeFilenameEditView.as_view()
),
url(
regex=r'^types/filenames/(?P<filename_pk>\d+)/delete/$',
regex=r'^documents_types/filenames/(?P<filename_id>\d+)/delete/$',
name='document_type_filename_delete',
view=DocumentTypeFilenameDeleteView.as_view()
),
@@ -316,17 +329,20 @@ urlpatterns = [
),
]
api_urls = [
urlpatterns.extend(urlpatterns_trashed_documents)
api_urls = []
"""
url(
regex=r'^document_types/$', name='documenttype-list',
view=APIDocumentTypeListView.as_view()
),
url(
regex=r'^document_types/(?P<document_type_pk>\d+)/$',
regex=r'^document_types/(?P<document_type_id>\d+)/$',
name='documenttype-detail', view=APIDocumentTypeView.as_view()
),
url(
regex=r'^document_types/(?P<document_type_pk>\d+)/documents/$',
regex=r'^document_types/(?P<document_type_id>\d+)/documents/$',
name='documenttype-document-list',
view=APIDocumentTypeDocumentListView.as_view()
),
@@ -335,30 +351,30 @@ api_urls = [
view=APIDocumentListView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/$', name='document-detail',
regex=r'^documents/(?P<document_id>\d+)/$', name='document-detail',
view=APIDocumentView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/download/$',
regex=r'^documents/(?P<document_id>\d+)/download/$',
name='document-download', view=APIDocumentDownloadView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/versions/$',
regex=r'^documents/(?P<document_id>\d+)/versions/$',
name='document-version-list',
view=APIDocumentVersionsListView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/versions/(?P<document_version_pk>\d+)/$',
regex=r'^documents/(?P<document_id>\d+)/versions/(?P<document_version_id>\d+)/$',
name='documentversion-detail',
view=APIDocumentVersionView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/versions/(?P<document_version_pk>\d+)/pages/$',
regex=r'^documents/(?P<document_id>\d+)/versions/(?P<document_version_id>\d+)/pages/$',
name='documentversion-page-list',
view=APIDocumentVersionPageListView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/versions/(?P<document_version_pk>\d+)/download/$',
regex=r'^documents/(?P<document_id>\d+)/versions/(?P<document_version_id>\d+)/download/$',
name='documentversion-download',
view=APIDocumentVersionDownloadView.as_view()
),
@@ -367,24 +383,45 @@ api_urls = [
view=APIRecentDocumentListView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/versions/(?P<document_version_pk>\d+)/pages/(?P<document_page_pk>\d+)$',
regex=r'^documents/(?P<document_id>\d+)/versions/(?P<document_version_id>\d+)/pages/(?P<document_page_id>\d+)$',
name='documentpage-detail', view=APIDocumentPageView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/versions/(?P<document_version_pk>\d+)/pages/(?P<document_page_pk>\d+)/image/$',
regex=r'^documents/(?P<document_id>\d+)/versions/(?P<document_version_id>\d+)/pages/(?P<document_page_id>\d+)/image/$',
name='documentpage-image', view=APIDocumentPageImageView.as_view()
),
url(
regex=r'^trashed_documents/$', name='trasheddocument-list',
view=APIDeletedDocumentListView.as_view()
view=APITrashedDocumentListView.as_view()
),
url(
regex=r'^trashed_documents/(?P<document_pk>\d+)/$',
name='trasheddocument-detail', view=APIDeletedDocumentView.as_view()
regex=r'^trashed_documents/(?P<document_id>\d+)/$',
name='trasheddocument-detail', view=APITrashedDocumentView.as_view()
),
url(
regex=r'^trashed_documents/(?P<document_pk>\d+)/restore/$',
regex=r'^trashed_documents/(?P<document_id>\d+)/restore/$',
name='trasheddocument-restore',
view=APIDeletedDocumentRestoreView.as_view()
view=APITrashedDocumentRestoreView.as_view()
),
]
"""
api_router_entries = (
{
'prefix': r'documents', 'viewset': DocumentViewSet,
'basename': 'document'
},
{
'prefix': r'document_types', 'viewset': DocumentTypeViewSet,
'basename': 'document_type'
},
{
'prefix': r'documents/(?P<document_id>\d+)/versions',
'viewset': DocumentVersionViewSet, 'basename': 'document_version'
},
{
'prefix': r'documents/(?P<document_id>\d+)/versions/(?P<document_version_id>\d+)/pages',
'viewset': DocumentPageViewSet, 'basename': 'document_page'
},
)

View File

@@ -3,3 +3,4 @@ from .document_type_views import * # NOQA
from .document_version_views import * # NOQA
from .document_views import * # NOQA
from .misc_views import * # NOQA
from .trashed_document_views import * # NOQA

View File

@@ -6,15 +6,14 @@ from furl import furl
from django.conf import settings
from django.contrib import messages
from django.shortcuts import get_object_or_404, resolve_url
from django.shortcuts import resolve_url
from django.urls import reverse
from django.utils.encoding import force_text
from django.utils.http import urlencode
from django.utils.translation import ugettext_lazy as _
from django.views.generic import RedirectView
from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.generics import SimpleView, SingleObjectListView
from mayan.apps.common.mixins import ExternalObjectMixin
from mayan.apps.common.utils import resolve
from mayan.apps.converter.literals import DEFAULT_ROTATION, DEFAULT_ZOOM_LEVEL
@@ -37,53 +36,40 @@ __all__ = (
logger = logging.getLogger(__name__)
class DocumentPageInteractiveTransformation(RedirectView):
def dispatch(self, request, *args, **kwargs):
obj = self.get_object()
AccessControlList.objects.check_access(
obj=obj, permissions=permission_document_view, user=request.user,
)
return super(DocumentPageInteractiveTransformation, self).dispatch(
request, *args, **kwargs
)
class DocumentPageInteractiveTransformation(ExternalObjectMixin, RedirectView):
external_object_class = DocumentPage
external_object_permission = permission_document_view
external_object_pk_url_kwarg = 'document_page_id'
def get_object(self):
return get_object_or_404(
klass=DocumentPage, pk=self.kwargs['document_page_pk']
)
return self.get_external_object()
def get_redirect_url(self, *args, **kwargs):
url = reverse(
viewname='documents:document_page_view',
kwargs={'document_page_pk': self.kwargs['document_page_pk']}
)
query_dict = {
'rotation': int(
self.request.GET.get('rotation', DEFAULT_ROTATION)
), 'zoom': int(self.request.GET.get('zoom', DEFAULT_ZOOM_LEVEL))
'rotation': self.request.GET.get('rotation', DEFAULT_ROTATION),
'zoom': self.request.GET.get('zoom', DEFAULT_ZOOM_LEVEL)
}
self.transformation_function(query_dict)
url = furl(
args=query_dict, path=reverse(
viewname='documents:document_page_view',
kwargs={'document_page_id': self.kwargs['document_page_id']}
)
return '{}?{}'.format(url, urlencode(query_dict))
class DocumentPageListView(SingleObjectListView):
def dispatch(self, request, *args, **kwargs):
AccessControlList.objects.check_access(
obj=self.get_document(), permissions=permission_document_view,
user=self.request.user,
)
return super(
DocumentPageListView, self
).dispatch(request, *args, **kwargs)
self.transformation_function(query_dict=query_dict)
return url.tostr()
class DocumentPageListView(ExternalObjectMixin, SingleObjectListView):
external_object_class = Document
external_object_permission = permission_document_view
external_object_pk_url_kwarg = 'document_id'
def get_document(self):
return get_object_or_404(klass=Document, pk=self.kwargs['document_pk'])
return self.get_external_object()
def get_extra_context(self):
return {
@@ -95,27 +81,17 @@ 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()
class DocumentPageNavigationBase(RedirectView):
def dispatch(self, request, *args, **kwargs):
document_page = self.get_object()
AccessControlList.objects.check_access(
permissions=permission_document_view, user=request.user,
obj=document_page.document
)
return super(DocumentPageNavigationBase, self).dispatch(
request, *args, **kwargs
)
class DocumentPageNavigationBase(ExternalObjectMixin, RedirectView):
external_object_class = DocumentPage
external_object_permission = permission_document_view
external_object_pk_url_kwarg = 'document_page_id'
def get_object(self):
return get_object_or_404(
klass=DocumentPage, pk=self.kwargs['document_page_pk']
)
return self.get_external_object()
def get_redirect_url(self, *args, **kwargs):
"""
@@ -158,14 +134,14 @@ class DocumentPageNavigationFirst(DocumentPageNavigationBase):
def get_new_kwargs(self):
document_page = self.get_object()
return {'document_page_pk': document_page.siblings.first().pk}
return {'document_page_id': document_page.siblings.first().pk}
class DocumentPageNavigationLast(DocumentPageNavigationBase):
def get_new_kwargs(self):
document_page = self.get_object()
return {'document_page_pk': document_page.siblings.last().pk}
return {'document_page_id': document_page.siblings.last().pk}
class DocumentPageNavigationNext(DocumentPageNavigationBase):
@@ -178,12 +154,12 @@ class DocumentPageNavigationNext(DocumentPageNavigationBase):
)
except DocumentPage.DoesNotExist:
messages.warning(
request=self.request, message=_(
message=_(
'There are no more pages in this document'
)
), request=self.request
)
finally:
return {'document_page_pk': document_page.pk}
return {'document_page_id': document_page.pk}
class DocumentPageNavigationPrevious(DocumentPageNavigationBase):
@@ -196,47 +172,40 @@ class DocumentPageNavigationPrevious(DocumentPageNavigationBase):
)
except DocumentPage.DoesNotExist:
messages.warning(
request=self.request, message=_(
message=_(
'You are already at the first page of this document'
)
), request=self.request
)
finally:
return {'document_page_pk': document_page.pk}
return {'document_page_id': document_page.pk}
class DocumentPageRotateLeftView(DocumentPageInteractiveTransformation):
def transformation_function(self, query_dict):
query_dict['rotation'] = (
query_dict['rotation'] - setting_rotation_step.value
int(query_dict['rotation']) - setting_rotation_step.value
) % 360
class DocumentPageRotateRightView(DocumentPageInteractiveTransformation):
def transformation_function(self, query_dict):
query_dict['rotation'] = (
query_dict['rotation'] + setting_rotation_step.value
int(query_dict['rotation']) + setting_rotation_step.value
) % 360
class DocumentPageView(SimpleView):
class DocumentPageView(ExternalObjectMixin, SimpleView):
external_object_class = DocumentPage
external_object_permission = permission_document_view
external_object_pk_url_kwarg = 'document_page_id'
template_name = 'appearance/generic_form.html'
def dispatch(self, request, *args, **kwargs):
AccessControlList.objects.check_access(
permissions=permission_document_view, user=request.user,
obj=self.get_object().document
)
return super(
DocumentPageView, self
).dispatch(request, *args, **kwargs)
def get_extra_context(self):
zoom = int(self.request.GET.get('zoom', DEFAULT_ZOOM_LEVEL))
rotation = int(self.request.GET.get('rotation', DEFAULT_ROTATION))
document_page_form = DocumentPageForm(
instance=self.get_object(), zoom=zoom, rotation=rotation
instance=self.get_object(), rotation=rotation, zoom=zoom
)
base_title = _('Image of: %s') % self.get_object()
@@ -252,15 +221,13 @@ class DocumentPageView(SimpleView):
'navigation_object_list': ('page',),
'page': self.get_object(),
'rotation': rotation,
'title': ' '.join((base_title, zoom_text,)),
'title': ' '.join((base_title, zoom_text)),
'read_only': True,
'zoom': zoom,
}
def get_object(self):
return get_object_or_404(
klass=DocumentPage, pk=self.kwargs['document_page_pk']
)
return self.get_external_object()
class DocumentPageViewResetView(RedirectView):
@@ -269,7 +236,7 @@ class DocumentPageViewResetView(RedirectView):
class DocumentPageZoomInView(DocumentPageInteractiveTransformation):
def transformation_function(self, query_dict):
zoom = query_dict['zoom'] + setting_zoom_percent_step.value
zoom = int(query_dict['zoom']) + setting_zoom_percent_step.value
if zoom > setting_zoom_max_level.value:
zoom = setting_zoom_max_level.value
@@ -279,7 +246,7 @@ class DocumentPageZoomInView(DocumentPageInteractiveTransformation):
class DocumentPageZoomOutView(DocumentPageInteractiveTransformation):
def transformation_function(self, query_dict):
zoom = query_dict['zoom'] - setting_zoom_percent_step.value
zoom = int(query_dict['zoom']) - setting_zoom_percent_step.value
if zoom < setting_zoom_min_level.value:
zoom = setting_zoom_min_level.value

View File

@@ -2,16 +2,15 @@ from __future__ import absolute_import, unicode_literals
import logging
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 (
SingleObjectCreateView, SingleObjectDeleteView, SingleObjectEditView,
SingleObjectListView
)
from mayan.apps.common.mixins import ExternalObjectMixin
from ..forms import DocumentTypeFilenameForm_create
from ..icons import icon_document_type_filename, icon_document_type_setup
@@ -60,7 +59,7 @@ class DocumentTypeDeleteView(SingleObjectDeleteView):
model = DocumentType
object_permission = permission_document_type_delete
post_action_redirect = reverse_lazy(viewname='documents:document_type_list')
pk_url_kwarg = 'document_type_pk'
pk_url_kwarg = 'document_type_id'
def get_extra_context(self):
return {
@@ -70,13 +69,17 @@ class DocumentTypeDeleteView(SingleObjectDeleteView):
}
class DocumentTypeDocumentListView(DocumentListView):
def get_document_type(self):
return get_object_or_404(klass=DocumentType, pk=self.kwargs['document_type_pk'])
class DocumentTypeDocumentListView(ExternalObjectMixin, DocumentListView):
external_object_class = DocumentType
external_object_permission = permission_document_type_view
external_object_pk_url_kwarg = 'document_type_id'
def get_document_queryset(self):
return self.get_document_type().documents.all()
def get_document_type(self):
return self.get_external_object()
def get_extra_context(self):
context = super(DocumentTypeDocumentListView, self).get_extra_context()
context.update(
@@ -95,7 +98,7 @@ class DocumentTypeEditView(SingleObjectEditView):
)
model = DocumentType
object_permission = permission_document_type_edit
pk_url_kwarg = 'document_type_pk'
pk_url_kwarg = 'document_type_id'
post_action_redirect = reverse_lazy(
viewname='documents:document_type_list'
)
@@ -136,21 +139,14 @@ class DocumentTypeListView(SingleObjectListView):
}
class DocumentTypeFilenameCreateView(SingleObjectCreateView):
class DocumentTypeFilenameCreateView(ExternalObjectMixin, SingleObjectCreateView):
external_object_class = DocumentType
external_object_permission = permission_document_type_edit
external_object_pk_url_kwarg = 'document_type_id'
form_class = DocumentTypeFilenameForm_create
def dispatch(self, request, *args, **kwargs):
AccessControlList.objects.check_access(
permissions=permission_document_type_edit, user=request.user,
obj=self.get_document_type()
)
return super(DocumentTypeFilenameCreateView, self).dispatch(
request, *args, **kwargs
)
def get_document_type(self):
return get_object_or_404(klass=DocumentType, pk=self.kwargs['document_type_pk'])
return self.get_external_object()
def get_extra_context(self):
return {
@@ -168,7 +164,7 @@ class DocumentTypeFilenameCreateView(SingleObjectCreateView):
class DocumentTypeFilenameDeleteView(SingleObjectDeleteView):
model = DocumentTypeFilename
object_permission = permission_document_type_edit
pk_url_kwarg = 'filename_pk'
pk_url_kwarg = 'filename_id'
def get_extra_context(self):
return {
@@ -187,7 +183,7 @@ class DocumentTypeFilenameDeleteView(SingleObjectDeleteView):
def get_post_action_redirect(self):
return reverse(
viewname='documents:document_type_filename_list',
kwargs={'document_type_pk': self.get_object().document_type.pk}
kwargs={'document_type_id': self.get_object().document_type.pk}
)
@@ -195,7 +191,7 @@ class DocumentTypeFilenameEditView(SingleObjectEditView):
fields = ('enabled', 'filename',)
model = DocumentTypeFilename
object_permission = permission_document_type_edit
pk_url_kwarg = 'filename_pk'
pk_url_kwarg = 'filename_id'
def get_extra_context(self):
document_type_filename = self.get_object()
@@ -216,16 +212,17 @@ class DocumentTypeFilenameEditView(SingleObjectEditView):
def get_post_action_redirect(self):
return reverse(
viewname='documents:document_type_filename_list',
kwargs={'document_type_pk': self.get_object().document_type.pk}
kwargs={'document_type_id': 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 = 'document_type_id'
def get_document_type(self):
return get_object_or_404(klass=DocumentType, pk=self.kwargs['document_type_pk'])
return self.get_external_object()
def get_extra_context(self):
return {
@@ -255,5 +252,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

@@ -3,15 +3,14 @@ from __future__ import absolute_import, unicode_literals
import logging
from django.contrib import messages
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _
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 ..events import event_document_download, event_document_view
from ..forms import DocumentVersionDownloadForm, DocumentVersionPreviewForm
from ..models import Document, DocumentVersion
from ..permissions import (
@@ -21,79 +20,22 @@ from ..permissions import (
from .document_views import DocumentDownloadFormView, DocumentDownloadView
__all__ = (
'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(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['document_pk'])
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_object_list(self):
return self.get_document().versions.order_by('-timestamp')
class DocumentVersionRevertView(ConfirmView):
object_permission = permission_document_version_revert
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['document_version_pk']
)
def view_action(self):
try:
self.get_object().revert(_user=self.request.user)
messages.success(
request=self.request, message=_(
'Document version reverted successfully'
)
)
except Exception as exception:
messages.error(
request=self.request,
message=_('Error reverting document version; %s') % exception
)
class DocumentVersionDownloadFormView(DocumentDownloadFormView):
form_class = DocumentVersionDownloadForm
model = DocumentVersion
multiple_download_view = None
pk_url_kwarg = 'document_version_pk'
pk_url_kwarg = 'document_version_id'
querystring_form_fields = (
'compressed', 'zip_filename', 'preserve_extension'
)
single_download_view = 'documents:document_version_download'
viewname = 'documents:document_version_download'
def get_extra_context(self):
result = super(
@@ -106,30 +48,26 @@ class DocumentVersionDownloadFormView(DocumentDownloadFormView):
return result
def get_document_queryset(self):
id_list = self.request.GET.get(
'id_list', self.request.POST.get('id_list', '')
)
if not id_list:
id_list = self.kwargs['document_version_pk']
return self.model.objects.filter(
pk__in=id_list.split(',')
)
class DocumentVersionDownloadView(DocumentDownloadView):
model = DocumentVersion
object_permission = permission_document_download
pk_url_kwarg = 'document_version_pk'
pk_url_kwarg = 'document_version_id'
@staticmethod
def commit_event(item, request):
# TODO: Improve by adding a document version download event
event_document_download.commit(
actor=request.user,
target=item.document
)
@staticmethod
def get_item_file(item):
return item.file
def get_encoding(self):
return self.get_object().encoding
return self.get_object_list().first().encoding
def get_item_label(self, item):
preserve_extension = self.request.GET.get(
@@ -143,13 +81,69 @@ class DocumentVersionDownloadView(DocumentDownloadView):
return item.get_rendered_string(preserve_extension=preserve_extension)
def get_mimetype(self):
return self.get_object().mimetype
return self.get_object_list().first().mimetype
class DocumentVersionListView(ExternalObjectMixin, SingleObjectListView):
external_object_class = Document
external_object_permission = permission_document_version_view
external_object_pk_url_kwarg = 'document_id'
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 = 'document_version_id'
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
object_permission = permission_document_version_view
pk_url_kwarg = 'document_version_id'
def dispatch(self, request, *args, **kwargs):
result = super(

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,8 @@ class ClearImageCacheView(ConfirmView):
def view_action(self):
task_clear_image_cache.apply_async()
messages.success(
self.request, _('Document cache clearing queued successfully.')
message=_('Document cache clearing queued successfully.'),
request=self.request
)
@@ -37,5 +38,6 @@ class ScanDuplicatedDocuments(ConfirmView):
def view_action(self):
task_scan_duplicates_all.apply_async()
messages.success(
self.request, _('Duplicated document scan queued successfully.')
message=_('Duplicated document scan queued successfully.'),
request=self.request
)

View File

@@ -0,0 +1,162 @@
from __future__ import absolute_import, unicode_literals
import logging
from django.contrib import messages
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext
from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.generics import (
ConfirmView, MultipleObjectConfirmActionView
)
from ..icons import icon_trashed_document_list
from ..models import Document, TrashedDocument
from ..permissions import (
permission_document_trash, permission_document_view, permission_empty_trash,
permission_trashed_document_delete, permission_trashed_document_restore
)
from ..tasks import task_delete_document
from .document_views import DocumentListView
__all__ = (
'DocumentTrashView', 'EmptyTrashCanView', 'TrashedDocumentDeleteView',
'TrashedDocumentListView', 'TrashedDocumentRestoreView',
)
logger = logging.getLogger(__name__)
class DocumentTrashView(MultipleObjectConfirmActionView):
model = Document
object_permission = permission_document_trash
pk_url_kwarg = 'document_id'
success_message = _(
'%(count)d document moved to the trash.'
)
success_message_plural = _(
'%(count)d documents moved to the trash.'
)
def get_extra_context(self):
queryset = self.get_object_list()
result = {
'title': ungettext(
single='Move the selected document to the trash?',
plural='Move the selected documents to the trash?',
number=queryset.count()
)
}
return result
def object_action(self, form, instance):
instance.delete()
class EmptyTrashCanView(ConfirmView):
extra_context = {
'title': _('Empty trash?')
}
view_permission = permission_empty_trash
action_cancel_redirect = post_action_redirect = reverse_lazy(
viewname='documents:trashed_document_list'
)
def view_action(self):
for trashed_document in TrashedDocument.objects.all():
task_delete_document.apply_async(
kwargs={'trashed_document_id': trashed_document.pk}
)
messages.success(
request=self.request, message=_('Trash emptied successfully')
)
class TrashedDocumentDeleteView(MultipleObjectConfirmActionView):
model = TrashedDocument
object_permission = permission_trashed_document_delete
pk_url_kwarg = 'trashed_document_id'
success_message = _(
'%(count)d trashed document deleted.'
)
success_message_plural = _(
'%(count)d trashed documents deleted.'
)
def get_extra_context(self):
queryset = self.get_object_list()
result = {
'title': ungettext(
single='Delete the selected trashed document?',
plural='Delete the selected trashed documents?',
number=queryset.count()
)
}
return result
def object_action(self, form, instance):
instance.delete()
class TrashedDocumentListView(DocumentListView):
object_permission = None
def get_document_queryset(self):
return AccessControlList.objects.restrict_queryset(
permission=permission_document_view,
queryset=TrashedDocument.trash.all(), user=self.request.user
)
def get_extra_context(self):
context = super(TrashedDocumentListView, self).get_extra_context()
context.update(
{
'hide_link': True,
'no_results_icon': icon_trashed_document_list,
'no_results_text': _(
'To avoid loss of data, documents are not deleted '
'instantly. First, they are placed in the trash can. '
'From here they can be then finally deleted or restored.'
),
'no_results_title': _(
'There are no documents in the trash can'
),
'title': _('Documents in trash'),
}
)
return context
class TrashedDocumentRestoreView(MultipleObjectConfirmActionView):
model = TrashedDocument
object_permission = permission_trashed_document_restore
pk_url_kwarg = 'trashed_document_id'
success_message = _(
'%(count)d trashed document restored.'
)
success_message_plural = _(
'%(count)d trashed documents restored.'
)
def get_extra_context(self):
queryset = self.get_object_list()
result = {
'title': ungettext(
single='Restore the selected trashed document?',
plural='Restore the selected trashed documents?',
number=queryset.count()
)
}
return result
def object_action(self, form, instance):
instance.restore()