Add document trashed event
Closes GitLab issue #608. Thanks to Vikas Kedia (@vikaskedia) for the report. Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
This commit is contained in:
@@ -131,6 +131,8 @@
|
||||
- Add the document template sandbox feature.
|
||||
- Use the generic TemplateField for the expression field
|
||||
of index tree templates.
|
||||
- Add document trashed event. Closes GitLab issue #608
|
||||
Thanks to Vikas Kedia (@vikaskedia) for the report.
|
||||
|
||||
3.2.10 (2019-XX-XX)
|
||||
===================
|
||||
|
||||
@@ -216,6 +216,7 @@ Bugs fixed or issues closed
|
||||
- :gitlab-issue:`532` Workflow preview isn't updated right after transitions are modified
|
||||
- :gitlab-issue:`540` hint-outdated/update documentation
|
||||
- :gitlab-issue:`594` 3.2b1: Unable to install/run under Python 3.5/3.6/3.7
|
||||
- :gitlab-issue:`608` How to know who put a document in trash can? [Video]
|
||||
- :gitlab-issue:`634` Failing docker entrypoint when using secret config
|
||||
- :gitlab-issue:`635` Build a docker image for Python3
|
||||
- :gitlab-issue:`640` UX: "Toast" Popup position prevents access to actions
|
||||
|
||||
@@ -18,6 +18,9 @@ event_document_new_version = namespace.add_event_type(
|
||||
event_document_properties_edit = namespace.add_event_type(
|
||||
label=_('Document properties edited'), name='document_edit'
|
||||
)
|
||||
event_document_trashed = namespace.add_event_type(
|
||||
label=_('Document trashed'), name='document_trashed'
|
||||
)
|
||||
# The type of an existing document is changed to another type
|
||||
event_document_type_change = namespace.add_event_type(
|
||||
label=_('Document type changed'), name='document_type_change'
|
||||
|
||||
@@ -5,7 +5,7 @@ import uuid
|
||||
|
||||
from django.apps import apps
|
||||
from django.core.files import File
|
||||
from django.db import models
|
||||
from django.db import models, transaction
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.utils.timezone import now
|
||||
@@ -13,7 +13,7 @@ from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from ..events import (
|
||||
event_document_create, event_document_properties_edit,
|
||||
event_document_type_change,
|
||||
event_document_trashed, event_document_type_change,
|
||||
)
|
||||
from ..managers import DocumentManager, PassthroughManager, TrashCanManager
|
||||
from ..settings import setting_language
|
||||
@@ -112,11 +112,14 @@ class Document(models.Model):
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
to_trash = kwargs.pop('to_trash', True)
|
||||
_user = kwargs.pop('_user', True)
|
||||
|
||||
if not self.in_trash and to_trash:
|
||||
self.in_trash = True
|
||||
self.deleted_date_time = now()
|
||||
self.save()
|
||||
with transaction.atomic():
|
||||
self.save(_commit_events=False)
|
||||
event_document_trashed.commit(actor=_user, target=self)
|
||||
else:
|
||||
for version in self.versions.all():
|
||||
version.delete()
|
||||
|
||||
@@ -268,3 +268,50 @@ class DocumentViewTestMixin(object):
|
||||
|
||||
def _request_empty_trash_view(self):
|
||||
return self.post(viewname='documents:trash_can_empty')
|
||||
|
||||
|
||||
class TrashedDocumentViewTestMixin(object):
|
||||
def _request_document_trash_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_trash', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_document_trash_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_trash', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_restore_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_restore', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_restore_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_restore', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_delete_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_delete', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_delete_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_delete', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_list_view(self):
|
||||
return self.get(viewname='documents:document_list_deleted')
|
||||
|
||||
@@ -3,13 +3,16 @@ from __future__ import unicode_literals
|
||||
from actstream.models import Action
|
||||
from django_downloadview import assert_download_response
|
||||
|
||||
from ..events import event_document_download, event_document_view
|
||||
from ..events import (
|
||||
event_document_download, event_document_trashed, event_document_view
|
||||
)
|
||||
from ..permissions import (
|
||||
permission_document_download, permission_document_view
|
||||
permission_document_download, permission_document_trash,
|
||||
permission_document_view
|
||||
)
|
||||
|
||||
from .base import GenericDocumentViewTestCase
|
||||
|
||||
from .mixins import TrashedDocumentViewTestMixin
|
||||
|
||||
TEST_DOCUMENT_TYPE_EDITED_LABEL = 'test document type edited label'
|
||||
TEST_DOCUMENT_TYPE_2_LABEL = 'test document type 2 label'
|
||||
@@ -32,21 +35,22 @@ class DocumentEventsTestMixin(object):
|
||||
|
||||
|
||||
class DocumentEventsTestCase(
|
||||
DocumentEventsTestMixin, GenericDocumentViewTestCase
|
||||
DocumentEventsTestMixin, TrashedDocumentViewTestMixin,
|
||||
GenericDocumentViewTestCase
|
||||
):
|
||||
def test_document_download_event_no_permissions(self):
|
||||
def setUp(self):
|
||||
super(DocumentEventsTestCase, self).setUp()
|
||||
Action.objects.all().delete()
|
||||
|
||||
def test_document_download_event_no_permission(self):
|
||||
response = self._request_test_document_download_view()
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertEqual(list(Action.objects.any(obj=self.test_document)), [])
|
||||
|
||||
def test_document_download_event_with_permissions(self):
|
||||
def test_document_download_event_with_access(self):
|
||||
self.expected_content_types = ('image/png; charset=utf-8',)
|
||||
|
||||
Action.objects.all().delete()
|
||||
|
||||
self.grant_access(
|
||||
obj=self.test_document, permission=permission_document_download
|
||||
)
|
||||
@@ -66,17 +70,13 @@ class DocumentEventsTestCase(
|
||||
self.assertEqual(event.target, self.test_document)
|
||||
self.assertEqual(event.verb, event_document_download.id)
|
||||
|
||||
def test_document_view_event_no_permissions(self):
|
||||
Action.objects.all().delete()
|
||||
|
||||
def test_document_view_event_no_permission(self):
|
||||
response = self._request_test_document_preview_view()
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
self.assertEqual(list(Action.objects.any(obj=self.test_document)), [])
|
||||
|
||||
def test_document_view_event_with_permissions(self):
|
||||
Action.objects.all().delete()
|
||||
|
||||
def test_document_view_event_with_access(self):
|
||||
self.grant_access(
|
||||
obj=self.test_document, permission=permission_document_view
|
||||
)
|
||||
@@ -88,3 +88,22 @@ class DocumentEventsTestCase(
|
||||
self.assertEqual(event.actor, self._test_case_user)
|
||||
self.assertEqual(event.target, self.test_document)
|
||||
self.assertEqual(event.verb, event_document_view.id)
|
||||
|
||||
def test_document_trashed_view_event_no_permission(self):
|
||||
response = self._request_document_trash_post_view()
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
self.assertEqual(list(Action.objects.any(obj=self.test_document)), [])
|
||||
|
||||
def test_document_trashed_view_event_with_access(self):
|
||||
self.grant_access(
|
||||
obj=self.test_document, permission=permission_document_trash
|
||||
)
|
||||
|
||||
response = self._request_document_trash_post_view()
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
event = Action.objects.any(obj=self.test_document).first()
|
||||
self.assertEqual(event.actor, self._test_case_user)
|
||||
self.assertEqual(event.target, self.test_document)
|
||||
self.assertEqual(event.verb, event_document_trashed.id)
|
||||
|
||||
@@ -7,57 +7,11 @@ from ..permissions import (
|
||||
)
|
||||
|
||||
from .base import GenericDocumentViewTestCase
|
||||
from .mixins import TrashedDocumentViewTestMixin
|
||||
|
||||
|
||||
class TrashedDocumentTestMixin(object):
|
||||
def _request_document_trash_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_trash', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_document_trash_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_trash', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_restore_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_restore', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_restore_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_restore', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_delete_get_view(self):
|
||||
return self.get(
|
||||
viewname='documents:document_delete', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_delete_post_view(self):
|
||||
return self.post(
|
||||
viewname='documents:document_delete', kwargs={
|
||||
'pk': self.test_document.pk
|
||||
}
|
||||
)
|
||||
|
||||
def _request_trashed_document_list_view(self):
|
||||
return self.get(viewname='documents:document_list_deleted')
|
||||
|
||||
|
||||
class TrashedDocumentTestCase(
|
||||
TrashedDocumentTestMixin, GenericDocumentViewTestCase
|
||||
class TrashedDocumentViewTestCase(
|
||||
TrashedDocumentViewTestMixin, GenericDocumentViewTestCase
|
||||
):
|
||||
def test_document_trash_get_view_no_permissions(self):
|
||||
document_count = Document.objects.count()
|
||||
|
||||
@@ -56,7 +56,7 @@ class DocumentTrashView(MultipleObjectConfirmActionView):
|
||||
return result
|
||||
|
||||
def object_action(self, form, instance):
|
||||
instance.delete()
|
||||
instance.delete(_user=self.request.user)
|
||||
|
||||
|
||||
class EmptyTrashCanView(ConfirmView):
|
||||
|
||||
Reference in New Issue
Block a user