File metadata: Add file metadata app

Add the file metadata app. This app uses binary wrappers called drivers
to extract properties from the file of documents. The default driver
uses the exiftool to extract the EXIF record from JPEG images.
The exiftool can also extra some properties from other files like
PDFs, office files and sound file.

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2018-12-14 02:16:38 -04:00
parent 1efec6bd41
commit 0a7908baca
33 changed files with 1309 additions and 22 deletions
@@ -0,0 +1,10 @@
from __future__ import unicode_literals
TEST_DRIVER_INTERNAL_NAME = 'exiftool'
TEST_FILE_METADATA_KEY = 'FileType'
TEST_FILE_METADATA_VALUE = 'PNG'
TEST_FILE_METADATA_INDEX_NODE_TEMPLATE = "{{{{ document.get_file_metadata('{}.{}')}}}}".format(
TEST_DRIVER_INTERNAL_NAME, TEST_FILE_METADATA_KEY
)
TEST_PDF_FILE_METADATA_DOTTED_NAME = 'exiftool.Producer'
TEST_PDF_FILE_METADATA_VALUE = 'pdfTeX-1.40.10'
@@ -0,0 +1,21 @@
from __future__ import unicode_literals
from mayan.apps.common.tests import BaseTestCase
from mayan.apps.documents.tests import (
TEST_PDF_DOCUMENT_FILENAME, DocumentTestMixin
)
from .literals import (
TEST_PDF_FILE_METADATA_DOTTED_NAME, TEST_PDF_FILE_METADATA_VALUE
)
class EXIFToolDriverTestCase(DocumentTestMixin, BaseTestCase):
test_document_filename = TEST_PDF_DOCUMENT_FILENAME
def test_driver_entries(self):
self.document.submit_for_file_metadata_processing()
value = self.document.get_file_metadata(
dotted_name=TEST_PDF_FILE_METADATA_DOTTED_NAME
)
self.assertEqual(value, TEST_PDF_FILE_METADATA_VALUE)
@@ -0,0 +1,40 @@
from __future__ import unicode_literals
from actstream.models import Action
from mayan.apps.documents.tests.test_models import GenericDocumentTestCase
from ..events import (
event_file_metadata_document_version_finish,
event_file_metadata_document_version_submit
)
class FileMetadataEventsTestCase(GenericDocumentTestCase):
def test_document_version_finish_event(self):
Action.objects.all().delete()
self.document.latest_version.submit_for_file_metadata_processing()
# Get the most recent action
action = Action.objects.order_by('-timestamp').first()
self.assertEqual(
action.target, self.document.latest_version
)
self.assertEqual(
action.verb, event_file_metadata_document_version_finish.id
)
def test_document_version_submit_event(self):
Action.objects.all().delete()
self.document.latest_version.submit_for_file_metadata_processing()
# Get the oldest action
action = Action.objects.order_by('-timestamp').last()
self.assertEqual(
action.target, self.document.latest_version
)
self.assertEqual(
action.verb, event_file_metadata_document_version_submit.id
)
@@ -0,0 +1,32 @@
from __future__ import unicode_literals
from mayan.apps.common.tests import BaseTestCase
from mayan.apps.document_indexing.models import Index, IndexInstanceNode
from mayan.apps.document_indexing.tests.literals import TEST_INDEX_LABEL
from mayan.apps.documents.tests import DocumentTestMixin
from .literals import (
TEST_FILE_METADATA_INDEX_NODE_TEMPLATE, TEST_FILE_METADATA_VALUE
)
class IndexingTestCase(DocumentTestMixin, BaseTestCase):
auto_upload_document = False
def test_indexing(self):
index = Index.objects.create(label=TEST_INDEX_LABEL)
index.document_types.add(self.document_type)
root = index.template_root
index.node_templates.create(
parent=root, expression=TEST_FILE_METADATA_INDEX_NODE_TEMPLATE,
link_documents=True
)
self.document = self.upload_document()
self.document.submit_for_file_metadata_processing()
self.assertTrue(
self.document in IndexInstanceNode.objects.get(
value=TEST_FILE_METADATA_VALUE
).documents.all()
)
@@ -0,0 +1,137 @@
from __future__ import unicode_literals
from django.test import override_settings
from mayan.apps.documents.tests import GenericDocumentViewTestCase
from ..permissions import (
permission_document_type_file_metadata_setup,
permission_file_metadata_submit, permission_file_metadata_view
)
from .literals import TEST_FILE_METADATA_KEY
@override_settings(FILE_METADATA_AUTO_PROCESS=True)
class FileMetadataViewsTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(FileMetadataViewsTestCase, self).setUp()
self.login_user()
def _request_document_version_driver_list_view(self):
return self.get(
args=(self.document.pk,),
viewname='file_metadata:document_driver_list',
)
def test_document_version_driver_list_view_no_permission(self):
response = self._request_document_version_driver_list_view()
self.assertEqual(response.status_code, 403)
def test_document_version_driver_list_view_with_access(self):
self.grant_access(
permission=permission_file_metadata_view, obj=self.document
)
response = self._request_document_version_driver_list_view()
self.assertContains(
response=response, text=self.document.label, status_code=200
)
def _request_document_version_file_metadata_list_view(self):
return self.get(
args=(
self.document.latest_version.file_metadata_drivers.first().pk,
),
viewname='file_metadata:document_version_driver_file_metadata_list',
)
def test_document_version_file_metadata_list_view_no_permission(self):
response = self._request_document_version_file_metadata_list_view()
self.assertNotContains(
response=response, text=TEST_FILE_METADATA_KEY, status_code=403
)
def test_document_version_file_metadata_list_view_with_access(self):
self.grant_access(
permission=permission_file_metadata_view, obj=self.document
)
response = self._request_document_version_file_metadata_list_view()
self.assertContains(
response=response, text=TEST_FILE_METADATA_KEY, status_code=200
)
def _request_document_submit_view(self):
return self.post(
viewname='file_metadata:document_submit', args=(self.document.pk,)
)
def test_document_submit_view_no_permission(self):
self.document.latest_version.file_metadata_drivers.all().delete()
response = self._request_document_submit_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(
self.document.latest_version.file_metadata_drivers.count(), 0
)
def test_document_submit_view_with_access(self):
self.document.latest_version.file_metadata_drivers.all().delete()
self.grant_access(
permission=permission_file_metadata_submit, obj=self.document
)
response = self._request_document_submit_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(
self.document.latest_version.file_metadata_drivers.count(), 1
)
def _request_multiple_document_submit_view(self):
return self.post(
viewname='file_metadata:document_submit_multiple',
data={
'id_list': self.document.pk,
}
)
def test_multiple_document_submit_view_no_permission(self):
self.document.latest_version.file_metadata_drivers.all().delete()
response = self._request_multiple_document_submit_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(
self.document.latest_version.file_metadata_drivers.count(), 0
)
def test_multiple_document_submit_view_with_access(self):
self.document.latest_version.file_metadata_drivers.all().delete()
self.grant_access(
permission=permission_file_metadata_submit, obj=self.document
)
response = self._request_multiple_document_submit_view()
self.assertEqual(response.status_code, 302)
self.assertEqual(
self.document.latest_version.file_metadata_drivers.count(), 1
)
class DocumentTypeViewsTestCase(GenericDocumentViewTestCase):
def setUp(self):
super(DocumentTypeViewsTestCase, self).setUp()
self.login_user()
def _request_document_type_settings_view(self):
return self.get(
viewname='file_metadata:document_type_settings',
args=(self.document.document_type.pk,)
)
def test_document_type_settings_view_no_permission(self):
response = self._request_document_type_settings_view()
self.assertEqual(response.status_code, 403)
def test_document_type_settings_view_with_access(self):
self.grant_access(
permission=permission_document_type_file_metadata_setup,
obj=self.document.document_type
)
response = self._request_document_type_settings_view()
self.assertEqual(response.status_code, 200)