From 4937d8b776dca9fa5774a98ff3e3a4c380d79a2d Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 25 Jan 2019 01:32:05 -0400 Subject: [PATCH] Update document signatures app Add keyword arguments. Remove source column functions and move their code to the model. Use the FilteredSelectionForm for the key selection in the document version signing view. Update the field definition of the DetailForm subclasses to use the new internface. Update URL parameters to use the "_id" form. Update views filtering to comply with MERC 6. Move repeated test code to its own test mixin. Update links to work with the new Link class interface. Modernize tests. Signed-off-by: Roberto Rosario --- mayan/apps/document_signatures/apps.py | 29 +- mayan/apps/document_signatures/forms.py | 94 ++--- mayan/apps/document_signatures/icons.py | 3 + mayan/apps/document_signatures/literals.py | 9 +- mayan/apps/document_signatures/models.py | 53 ++- mayan/apps/document_signatures/storages.py | 2 - .../apps/document_signatures/tests/mixins.py | 22 ++ .../document_signatures/tests/test_links.py | 83 ++--- .../document_signatures/tests/test_models.py | 223 ++++------- .../document_signatures/tests/test_views.py | 349 ++++++------------ mayan/apps/document_signatures/urls.py | 50 +-- mayan/apps/document_signatures/views.py | 174 ++++----- 12 files changed, 450 insertions(+), 641 deletions(-) create mode 100644 mayan/apps/document_signatures/tests/mixins.py diff --git a/mayan/apps/document_signatures/apps.py b/mayan/apps/document_signatures/apps.py index ae6feff669..55dd1dfd57 100644 --- a/mayan/apps/document_signatures/apps.py +++ b/mayan/apps/document_signatures/apps.py @@ -63,15 +63,15 @@ class DocumentSignaturesApp(MayanAppConfig): app_label='django_gpg', model_name='Key' ) - EmbeddedSignature = self.get_model('EmbeddedSignature') + EmbeddedSignature = self.get_model(model_name='EmbeddedSignature') - SignatureBaseModel = self.get_model('SignatureBaseModel') + SignatureBaseModel = self.get_model(model_name='SignatureBaseModel') DocumentVersion.register_post_save_hook( - order=1, func=EmbeddedSignature.objects.create + func=EmbeddedSignature.objects.create, order=1 ) DocumentVersion.register_pre_open_hook( - order=1, func=EmbeddedSignature.objects.open_signed + func=EmbeddedSignature.objects.open_signed, order=1 ) ModelPermission.register( @@ -85,22 +85,15 @@ class DocumentSignaturesApp(MayanAppConfig): ) ) - SourceColumn( - source=SignatureBaseModel, label=_('Date'), attribute='date' + ModelPermission.register_inheritance( + model=SignatureBaseModel, related='document_version' ) + + SourceColumn(attribute='date', source=SignatureBaseModel) + SourceColumn(attribute='get_key_id', source=SignatureBaseModel) + SourceColumn(attribute='get_signature_id', source=SignatureBaseModel) SourceColumn( - source=SignatureBaseModel, label=_('Key ID'), - attribute='get_key_id' - ) - SourceColumn( - source=SignatureBaseModel, label=_('Signature ID'), - func=lambda context: context['object'].signature_id or _('None') - ) - SourceColumn( - source=SignatureBaseModel, label=_('Type'), - func=lambda context: SignatureBaseModel.objects.get_subclass( - pk=context['object'].pk - ).get_signature_type_display() + attribute='get_signature_type_display', source=SignatureBaseModel ) app.conf.task_queues.append( diff --git a/mayan/apps/document_signatures/forms.py b/mayan/apps/document_signatures/forms.py index e0403a23c9..dfcfb08858 100644 --- a/mayan/apps/document_signatures/forms.py +++ b/mayan/apps/document_signatures/forms.py @@ -5,8 +5,7 @@ import logging from django import forms from django.utils.translation import ugettext_lazy as _ -from mayan.apps.acls.models import AccessControlList -from mayan.apps.common.forms import DetailForm +from mayan.apps.common.forms import DetailForm, FilteredSelectionForm from mayan.apps.django_gpg.models import Key from mayan.apps.django_gpg.permissions import permission_key_sign @@ -15,44 +14,39 @@ from .models import SignatureBaseModel logger = logging.getLogger(__name__) -class DocumentVersionSignatureCreateForm(forms.Form): +class DocumentVersionSignatureCreateForm(FilteredSelectionForm): key = forms.ModelChoiceField( label=_('Key'), queryset=Key.objects.none() ) passphrase = forms.CharField( - label=_('Passphrase'), required=False, + help_text=_( + 'The passphrase to unlock the key and allow it to be used to ' + 'sign the document version.' + ), label=_('Passphrase'), required=False, widget=forms.widgets.PasswordInput ) - def __init__(self, *args, **kwargs): - user = kwargs.pop('user', None) - logger.debug('user: %s', user) - super( - DocumentVersionSignatureCreateForm, self - ).__init__(*args, **kwargs) - - queryset = AccessControlList.objects.filter_by_access( - permission_key_sign, user, queryset=Key.objects.private_keys() + class Meta: + allow_multiple = False + field_name = 'key' + label = _('Key') + help_text = _( + 'Private key that will be used to sign this document version.' ) - - self.fields['key'].queryset = queryset + permission = permission_key_sign + queryset = Key.objects.private_keys() + required = True + widget_attributes = {'class': 'select2'} class DocumentVersionSignatureDetailForm(DetailForm): def __init__(self, *args, **kwargs): - extra_fields = ( - {'label': _('Signature is embedded?'), 'field': 'is_embedded'}, - { - 'label': _('Signature date'), 'field': 'date', - 'widget': forms.widgets.DateInput - }, - {'label': _('Signature key ID'), 'field': 'key_id'}, - { - 'label': _('Signature key present?'), - 'field': lambda x: x.public_key_fingerprint is not None - }, - ) + super( + DocumentVersionSignatureDetailForm, self + ).__init__(*args, **kwargs) + + extra_fields = self.Meta.extra_fields if kwargs['instance'].public_key_fingerprint: key = Key.objects.get( @@ -60,44 +54,52 @@ class DocumentVersionSignatureDetailForm(DetailForm): ) extra_fields += ( - {'label': _('Signature ID'), 'field': 'signature_id'}, + {'field': 'signature_id'}, { - 'label': _('Key fingerprint'), - 'field': lambda x: key.fingerprint + 'field': 'fingerprint', + 'object': key }, { - 'label': _('Key creation date'), - 'field': lambda x: key.creation_date, + 'field': 'creation_date', + 'object': key, 'widget': forms.widgets.DateInput }, { - 'label': _('Key expiration date'), - 'field': lambda x: key.expiration_date or _('None'), + 'field': 'get_expiration_date_display', + 'object': key, 'widget': forms.widgets.DateInput }, { - 'label': _('Key length'), - 'field': lambda x: key.length + 'field': 'length', + 'object': key }, { - 'label': _('Key algorithm'), - 'field': lambda x: key.algorithm + 'field': 'algorithm', + 'object': key }, { - 'label': _('Key user ID'), - 'field': lambda x: key.user_id + 'field': 'get_escaped_user_id', + 'object': key }, { - 'label': _('Key type'), - 'field': lambda x: key.get_key_type_display() + 'field': 'get_key_type_display', + 'object': key }, ) - kwargs['extra_fields'] = extra_fields - super( - DocumentVersionSignatureDetailForm, self - ).__init__(*args, **kwargs) + self.Meta.extra_fields = extra_fields class Meta: + extra_fields = ( + {'field': 'get_signature_type_display'}, + { + 'field': 'date', + 'widget': forms.widgets.DateInput + }, + {'field': 'key_id'}, + { + 'field': 'get_key_available_display' + }, + ) fields = () model = SignatureBaseModel diff --git a/mayan/apps/document_signatures/icons.py b/mayan/apps/document_signatures/icons.py index cb7ea37e33..63803faeb6 100644 --- a/mayan/apps/document_signatures/icons.py +++ b/mayan/apps/document_signatures/icons.py @@ -17,3 +17,6 @@ icon_document_version_signature_embedded_create = Icon( icon_document_version_signature_list = Icon( driver_name='fontawesome', symbol='certificate' ) +icon_document_version_signature_upload = Icon( + driver_name='fontawesome', symbol='upload' +) diff --git a/mayan/apps/document_signatures/literals.py b/mayan/apps/document_signatures/literals.py index f27ca1f9d8..d8d11c4694 100644 --- a/mayan/apps/document_signatures/literals.py +++ b/mayan/apps/document_signatures/literals.py @@ -1,3 +1,10 @@ from __future__ import unicode_literals -RETRY_DELAY = 10 +from django.utils.translation import ugettext_lazy as _ + +SIGNATURE_TYPE_DETACHED = 1 +SIGNATURE_TYPE_EMBEDDED = 2 +SIGNATURE_TYPE_CHOICES = ( + (SIGNATURE_TYPE_DETACHED, _('Detached')), + (SIGNATURE_TYPE_EMBEDDED, _('Embedded')), +) diff --git a/mayan/apps/document_signatures/models.py b/mayan/apps/document_signatures/models.py index 47e226f5ed..17ea367035 100644 --- a/mayan/apps/document_signatures/models.py +++ b/mayan/apps/document_signatures/models.py @@ -14,12 +14,16 @@ from mayan.apps.django_gpg.exceptions import VerificationError from mayan.apps.django_gpg.models import Key from mayan.apps.documents.models import DocumentVersion +from .literals import ( + SIGNATURE_TYPE_CHOICES, SIGNATURE_TYPE_DETACHED, SIGNATURE_TYPE_EMBEDDED +) from .managers import EmbeddedSignatureManager from .storages import storage_detachedsignature logger = logging.getLogger(__name__) +# TODO: Move to an utils module or as a static class of DetachedSignature def upload_to(*args, **kwargs): return force_text(uuid.uuid4()) @@ -65,8 +69,8 @@ class SignatureBaseModel(models.Model): def get_absolute_url(self): return reverse( - 'document_signatures:document_version_signature_detail', - args=(self.pk,) + viewname='document_signatures:document_version_signature_detail', + kwargs={'document_version_id': self.pk} ) def get_key_id(self): @@ -74,20 +78,41 @@ class SignatureBaseModel(models.Model): return self.public_key_fingerprint[-16:] else: return self.key_id + get_key_id.short_description = _('Key ID') + + def get_signature_id(self): + return self.signature_id or _('None') + get_signature_id.short_description = _('Signature ID') def get_signature_type_display(self): - if self.is_detached: - return _('Detached') + if hasattr(self, 'signaturebasemodel_ptr'): + model = self else: - return _('Embedded') + model = self._meta.default_manager.get_subclass(pk=self.pk) + + return dict(SIGNATURE_TYPE_CHOICES).get( + model.signature_type, _('Unknown') + ) + get_signature_type_display.short_description = _('Type') + + def is_key_available(self): + return self.public_key_fingerprint is not None + + def get_key_available_display(self): + if self.is_key_available(): + return _('Yes') + else: + return _('No') + get_key_available_display.short_description = _('Signature key present?') @property - def is_detached(self): - return hasattr(self, 'signature_file') + def signature_type(self): + if hasattr(self, 'signaturebasemodel_ptr'): + model = self + else: + model = self._meta.default_manager.get_subclass(pk=self.pk) - @property - def is_embedded(self): - return not hasattr(self, 'signature_file') + return model._signature_type class EmbeddedSignature(SignatureBaseModel): @@ -97,6 +122,10 @@ class EmbeddedSignature(SignatureBaseModel): verbose_name = _('Document version embedded signature') verbose_name_plural = _('Document version embedded signatures') + @property + def _signature_type(self): + return SIGNATURE_TYPE_EMBEDDED + def save(self, *args, **kwargs): logger.debug('checking for embedded signature') @@ -141,6 +170,10 @@ class DetachedSignature(SignatureBaseModel): def __str__(self): return '{}-{}'.format(self.document_version, _('signature')) + @property + def _signature_type(self): + return SIGNATURE_TYPE_DETACHED + def delete(self, *args, **kwargs): if self.signature_file.name: self.signature_file.storage.delete(name=self.signature_file.name) diff --git a/mayan/apps/document_signatures/storages.py b/mayan/apps/document_signatures/storages.py index 03c959df5a..1b88c818ca 100644 --- a/mayan/apps/document_signatures/storages.py +++ b/mayan/apps/document_signatures/storages.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -from django.utils.module_loading import import_string - from mayan.apps.common.utils import get_storage_subclass from .settings import ( diff --git a/mayan/apps/document_signatures/tests/mixins.py b/mayan/apps/document_signatures/tests/mixins.py new file mode 100644 index 0000000000..4b057c395c --- /dev/null +++ b/mayan/apps/document_signatures/tests/mixins.py @@ -0,0 +1,22 @@ +from __future__ import absolute_import, unicode_literals + +from django.core.files import File + +from mayan.apps.django_gpg.models import Key + +from ..models import DetachedSignature + +from .literals import TEST_KEY_FILE, TEST_SIGNATURE_FILE_PATH + + +class SignaturesTestMixin(object): + def _create_test_key(self): + with open(TEST_KEY_FILE, mode='rb') as file_object: + self.test_key = Key.objects.create(key_data=file_object.read()) + + def _upload_test_signature(self): + with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: + self.test_signature = DetachedSignature.objects.create( + document_version=self.test_document.latest_version, + signature_file=File(file_object) + ) diff --git a/mayan/apps/document_signatures/tests/test_links.py b/mayan/apps/document_signatures/tests/test_links.py index e11e5fe157..13a659b6e6 100644 --- a/mayan/apps/document_signatures/tests/test_links.py +++ b/mayan/apps/document_signatures/tests/test_links.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -from django.core.files import File from django.urls import reverse from mayan.apps.documents.tests import ( @@ -11,28 +10,24 @@ from ..links import ( link_document_version_signature_delete, link_document_version_signature_details ) -from ..models import DetachedSignature from ..permissions import ( permission_document_version_signature_delete, permission_document_version_signature_view ) -from .literals import TEST_SIGNATURE_FILE_PATH, TEST_SIGNED_DOCUMENT_PATH +from .literals import TEST_SIGNED_DOCUMENT_PATH +from .mixins import SignaturesTestMixin -class DocumentSignatureLinksTestCase(GenericDocumentViewTestCase): - def setUp(self): - super(DocumentSignatureLinksTestCase, self).setUp() - self.login_user() +class DocumentSignatureLinksTestCase(SignaturesTestMixin, GenericDocumentViewTestCase): + auto_upload_document = False def test_document_version_signature_detail_link_no_permission(self): - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.test_document = self.upload_document() self.add_test_view( - test_object=document.latest_version.signatures.first() + test_object=self.test_document.latest_version.signatures.first() ) context = self.get_test_view() resolved_link = link_document_version_signature_details.resolve( @@ -41,18 +36,17 @@ class DocumentSignatureLinksTestCase(GenericDocumentViewTestCase): self.assertEqual(resolved_link, None) - def test_document_version_signature_detail_link_with_permission(self): - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + def test_document_version_signature_detail_link_with_access(self): + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.test_document = self.upload_document() - self.role.permissions.add( - permission_document_version_signature_view.stored_permission + self.grant_access( + obj=self.test_document, + permission=permission_document_version_signature_view ) self.add_test_view( - test_object=document.latest_version.signatures.first() + test_object=self.test_document.latest_version.signatures.first() ) context = self.get_test_view() resolved_link = link_document_version_signature_details.resolve( @@ -63,25 +57,20 @@ class DocumentSignatureLinksTestCase(GenericDocumentViewTestCase): self.assertEqual( resolved_link.url, reverse( - 'signatures:document_version_signature_details', - args=(document.latest_version.signatures.first().pk,) + viewname='signatures:document_version_signature_details', + kwargs={ + 'signature_id': self.test_document.latest_version.signatures.first().pk + } ) ) def test_document_version_signature_delete_link_no_permission(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() self.add_test_view( - test_object=document.latest_version.signatures.first() + test_object=self.test_document.latest_version.signatures.first() ) context = self.get_test_view() resolved_link = link_document_version_signature_delete.resolve( @@ -90,24 +79,18 @@ class DocumentSignatureLinksTestCase(GenericDocumentViewTestCase): self.assertEqual(resolved_link, None) - def test_document_version_signature_delete_link_with_permission(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + def test_document_version_signature_delete_link_with_access(self): + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) - - self.role.permissions.add( - permission_document_version_signature_delete.stored_permission + self.grant_access( + obj=self.test_document, + permission=permission_document_version_signature_delete ) self.add_test_view( - test_object=document.latest_version.signatures.first() + test_object=self.test_document.latest_version.signatures.first() ) context = self.get_test_view() resolved_link = link_document_version_signature_delete.resolve( @@ -118,7 +101,9 @@ class DocumentSignatureLinksTestCase(GenericDocumentViewTestCase): self.assertEqual( resolved_link.url, reverse( - 'signatures:document_version_signature_delete', - args=(document.latest_version.signatures.first().pk,) + viewname='signatures:document_version_signature_delete', + kwargs={ + 'signature_id': self.test_document.latest_version.signatures.first().pk + } ) ) diff --git a/mayan/apps/document_signatures/tests/test_models.py b/mayan/apps/document_signatures/tests/test_models.py index 87bce78057..09a287297e 100644 --- a/mayan/apps/document_signatures/tests/test_models.py +++ b/mayan/apps/document_signatures/tests/test_models.py @@ -4,110 +4,86 @@ import hashlib import logging import time -from django.core.files import File - -from mayan.apps.common.tests import BaseTestCase from mayan.apps.django_gpg.models import Key from mayan.apps.django_gpg.tests.literals import ( TEST_KEY_DATA, TEST_KEY_PASSPHRASE ) -from mayan.apps.documents.models import DocumentType, DocumentVersion +from mayan.apps.documents.models import DocumentVersion from mayan.apps.documents.tests import ( - TEST_DOCUMENT_PATH, TEST_DOCUMENT_TYPE_LABEL + GenericDocumentTestCase, TEST_DOCUMENT_PATH, ) from ..models import DetachedSignature, EmbeddedSignature from ..tasks import task_verify_missing_embedded_signature -from .literals import ( - TEST_KEY_FILE, TEST_KEY_ID, TEST_SIGNATURE_FILE_PATH, TEST_SIGNATURE_ID, - TEST_SIGNED_DOCUMENT_PATH -) +from .literals import TEST_KEY_ID, TEST_SIGNATURE_ID, TEST_SIGNED_DOCUMENT_PATH +from .mixins import SignaturesTestMixin -class DocumentSignaturesTestCase(BaseTestCase): - def setUp(self): - super(DocumentSignaturesTestCase, self).setUp() - self.document_type = DocumentType.objects.create( - label=TEST_DOCUMENT_TYPE_LABEL - ) - - def tearDown(self): - self.document_type.delete() - super(DocumentSignaturesTestCase, self).tearDown() +class DocumentSignaturesTestCase(SignaturesTestMixin, GenericDocumentTestCase): + auto_upload_document = False def test_embedded_signature_no_key(self): - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - signed_document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.test_signed_document = self.upload_document() self.assertEqual(EmbeddedSignature.objects.count(), 1) signature = EmbeddedSignature.objects.first() self.assertEqual( - signature.document_version, signed_document.latest_version + signature.document_version, self.test_signed_document.latest_version ) self.assertEqual(signature.key_id, TEST_KEY_ID) self.assertEqual(signature.signature_id, None) def test_embedded_signature_post_key_verify(self): - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - signed_document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.test_signed_document = self.upload_document() self.assertEqual(EmbeddedSignature.objects.count(), 1) signature = EmbeddedSignature.objects.first() self.assertEqual( - signature.document_version, signed_document.latest_version + signature.document_version, self.test_signed_document.latest_version ) self.assertEqual(signature.key_id, TEST_KEY_ID) self.assertEqual(signature.signature_id, None) - with open(TEST_KEY_FILE, mode='rb') as file_object: - Key.objects.create(key_data=file_object.read()) + self._create_test_key() signature = EmbeddedSignature.objects.first() self.assertEqual(signature.signature_id, TEST_SIGNATURE_ID) def test_embedded_signature_post_no_key_verify(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - key = Key.objects.create(key_data=file_object.read()) + self._create_test_key() - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - signed_document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.test_signed_document = self.upload_document() self.assertEqual(EmbeddedSignature.objects.count(), 1) signature = EmbeddedSignature.objects.first() self.assertEqual( - signature.document_version, signed_document.latest_version + signature.document_version, self.test_signed_document.latest_version ) self.assertEqual(signature.key_id, TEST_KEY_ID) self.assertEqual(signature.signature_id, TEST_SIGNATURE_ID) - key.delete() + self.test_key.delete() signature = EmbeddedSignature.objects.first() self.assertEqual(signature.signature_id, None) def test_embedded_signature_with_key(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - key = Key.objects.create(key_data=file_object.read()) + self._create_test_key() - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - self.signed_document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.test_signed_document = self.upload_document() self.assertEqual(EmbeddedSignature.objects.count(), 1) @@ -115,127 +91,109 @@ class DocumentSignaturesTestCase(BaseTestCase): self.assertEqual( signature.document_version, - self.signed_document.latest_version + self.test_signed_document.latest_version ) self.assertEqual(signature.key_id, TEST_KEY_ID) - self.assertEqual(signature.public_key_fingerprint, key.fingerprint) + self.assertEqual( + signature.public_key_fingerprint, self.test_key.fingerprint + ) self.assertEqual(signature.signature_id, TEST_SIGNATURE_ID) def test_detached_signature_no_key(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) + self._upload_test_signature() self.assertEqual(DetachedSignature.objects.count(), 1) signature = DetachedSignature.objects.first() - self.assertEqual(signature.document_version, document.latest_version) + self.assertEqual( + signature.document_version, self.test_document.latest_version + ) self.assertEqual(signature.key_id, TEST_KEY_ID) self.assertEqual(signature.public_key_fingerprint, None) def test_detached_signature_with_key(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - key = Key.objects.create(key_data=file_object.read()) + self._create_test_key() - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() self.assertEqual(DetachedSignature.objects.count(), 1) signature = DetachedSignature.objects.first() - self.assertEqual(signature.document_version, document.latest_version) + self.assertEqual( + signature.document_version, self.test_document.latest_version + ) self.assertEqual(signature.key_id, TEST_KEY_ID) - self.assertEqual(signature.public_key_fingerprint, key.fingerprint) + self.assertEqual( + signature.public_key_fingerprint, self.test_key.fingerprint + ) def test_detached_signature_post_key_verify(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() self.assertEqual(DetachedSignature.objects.count(), 1) signature = DetachedSignature.objects.first() - self.assertEqual(signature.document_version, document.latest_version) + self.assertEqual( + signature.document_version, self.test_document.latest_version + ) self.assertEqual(signature.key_id, TEST_KEY_ID) self.assertEqual(signature.public_key_fingerprint, None) - with open(TEST_KEY_FILE, mode='rb') as file_object: - key = Key.objects.create(key_data=file_object.read()) + self._create_test_key() signature = DetachedSignature.objects.first() - self.assertEqual(signature.public_key_fingerprint, key.fingerprint) + self.assertEqual( + signature.public_key_fingerprint, self.test_key.fingerprint + ) def test_detached_signature_post_no_key_verify(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - key = Key.objects.create(key_data=file_object.read()) + self._create_test_key() - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() self.assertEqual(DetachedSignature.objects.count(), 1) signature = DetachedSignature.objects.first() - self.assertEqual(signature.document_version, document.latest_version) + self.assertEqual( + signature.document_version, self.test_document.latest_version + ) self.assertEqual(signature.key_id, TEST_KEY_ID) - self.assertEqual(signature.public_key_fingerprint, key.fingerprint) + self.assertEqual( + signature.public_key_fingerprint, self.test_key.fingerprint + ) - key.delete() + self.test_key.delete() signature = DetachedSignature.objects.first() self.assertEqual(signature.public_key_fingerprint, None) def test_document_no_signature(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.upload_document() self.assertEqual(EmbeddedSignature.objects.count(), 0) def test_new_signed_version(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - signed_version = document.new_version( + signed_version = self.test_document.new_version( file_object=file_object, comment='test comment 1' ) @@ -252,33 +210,20 @@ class DocumentSignaturesTestCase(BaseTestCase): self.assertEqual(signature.key_id, TEST_KEY_ID) -class EmbeddedSignaturesTestCase(BaseTestCase): - def setUp(self): - super(EmbeddedSignaturesTestCase, self).setUp() - - self.document_type = DocumentType.objects.create( - label=TEST_DOCUMENT_TYPE_LABEL - ) - - def tearDown(self): - self.document_type.delete() - super(EmbeddedSignaturesTestCase, self).tearDown() +class EmbeddedSignaturesTestCase(GenericDocumentTestCase): + auto_upload_document = False def test_unsigned_document_version_method(self): TEST_UNSIGNED_DOCUMENT_COUNT = 2 TEST_SIGNED_DOCUMENT_COUNT = 2 for count in range(TEST_UNSIGNED_DOCUMENT_COUNT): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.upload_document() for count in range(TEST_SIGNED_DOCUMENT_COUNT): - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.upload_document() self.assertEqual( EmbeddedSignature.objects.unsigned_document_versions().count(), @@ -299,16 +244,12 @@ class EmbeddedSignaturesTestCase(BaseTestCase): TEST_SIGNED_DOCUMENT_COUNT = 2 for count in range(TEST_UNSIGNED_DOCUMENT_COUNT): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.upload_document() for count in range(TEST_SIGNED_DOCUMENT_COUNT): - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.upload_document() self.assertEqual( EmbeddedSignature.objects.unsigned_document_versions().count(), @@ -327,19 +268,17 @@ class EmbeddedSignaturesTestCase(BaseTestCase): def test_signing(self): key = Key.objects.create(key_data=TEST_KEY_DATA) - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() - with document.latest_version.open() as file_object: + with self.test_document.latest_version.open() as file_object: file_object.seek(0, 2) original_size = file_object.tell() file_object.seek(0) original_hash = hashlib.sha256(file_object.read()).hexdigest() new_version = EmbeddedSignature.objects.sign_document_version( - document_version=document.latest_version, key=key, + document_version=self.test_document.latest_version, key=key, passphrase=TEST_KEY_PASSPHRASE ) diff --git a/mayan/apps/document_signatures/tests/test_views.py b/mayan/apps/document_signatures/tests/test_views.py index 630f12f906..b60d2aa06a 100644 --- a/mayan/apps/document_signatures/tests/test_views.py +++ b/mayan/apps/document_signatures/tests/test_views.py @@ -2,11 +2,8 @@ from __future__ import absolute_import, unicode_literals import logging -from django.core.files import File - from django_downloadview.test import assert_download_response -from mayan.apps.django_gpg.models import Key from mayan.apps.documents.models import DocumentVersion from mayan.apps.documents.tests import ( TEST_DOCUMENT_PATH, GenericDocumentViewTestCase @@ -21,290 +18,172 @@ from ..permissions import ( permission_document_version_signature_view ) -from .literals import ( - TEST_KEY_FILE, TEST_SIGNATURE_FILE_PATH, TEST_SIGNED_DOCUMENT_PATH -) +from .literals import TEST_SIGNATURE_FILE_PATH, TEST_SIGNED_DOCUMENT_PATH +from .mixins import SignaturesTestMixin TEST_UNSIGNED_DOCUMENT_COUNT = 4 TEST_SIGNED_DOCUMENT_COUNT = 2 -class SignaturesViewTestCase(GenericDocumentViewTestCase): - def _request_document_version_signature_list_view(self, document): - return self.get( - viewname='signatures:document_version_signature_list', - args=(document.latest_version.pk,) +class SignaturesViewTestCase(SignaturesTestMixin, GenericDocumentViewTestCase): + def _request_document_version_signature_delete_view(self): + return self.post( + viewname='signatures:document_version_signature_delete', + kwargs={'signature_id': self.test_signature.pk} ) - def test_signature_list_view_no_permission(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - Key.objects.create(key_data=file_object.read()) + def test_signature_delete_view_no_permission(self): + self._create_test_key() + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + response = self._request_document_version_signature_delete_view() + self.assertEqual(response.status_code, 404) + self.assertEqual(DetachedSignature.objects.count(), 1) - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) - - self.login_user() - - response = self._request_document_version_signature_list_view( - document=document - ) - self.assertEqual(response.status_code, 403) - - def test_signature_list_view_with_access(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - Key.objects.create(key_data=file_object.read()) - - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) - - self.login_user() + def test_signature_delete_view_with_access(self): + self._create_test_key() + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() self.grant_access( - obj=document, - permission=permission_document_version_signature_view + obj=self.test_document, + permission=permission_document_version_signature_delete ) + response = self._request_document_version_signature_delete_view() + self.assertEqual(response.status_code, 302) + self.assertEqual(DetachedSignature.objects.count(), 0) - response = self._request_document_version_signature_list_view( - document=document - ) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['object_list'].count(), 1) - - def _request_document_version_signature_details_view(self, signature): + def _request_document_version_signature_details_view(self): return self.get( viewname='signatures:document_version_signature_details', - args=(signature.pk,) + kwargs={'signature_id': self.test_signature.pk} ) def test_signature_detail_view_no_permission(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - Key.objects.create(key_data=file_object.read()) + self._create_test_key() + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - signature = DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) - - self.login_user() - - response = self._request_document_version_signature_details_view( - signature=signature - ) - self.assertEqual(response.status_code, 403) + response = self._request_document_version_signature_details_view() + self.assertEqual(response.status_code, 404) def test_signature_detail_view_with_access(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - Key.objects.create(key_data=file_object.read()) - - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - signature = DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) - - self.login_user() - + self._create_test_key() + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() self.grant_access( - obj=document, + obj=self.test_document, permission=permission_document_version_signature_view ) - response = self._request_document_version_signature_details_view( - signature=signature - ) + response = self._request_document_version_signature_details_view() self.assertContains( - response=response, text=signature.signature_id, status_code=200 + response=response, text=self.test_signature.signature_id, + status_code=200 ) - def _request_document_version_signature_upload_view(self, document_version): - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - return self.post( - viewname='signatures:document_version_signature_upload', - args=(document_version.pk,), - data={'signature_file': file_object} - ) - - def test_signature_upload_view_no_permission(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - self.login_user() - - response = self._request_document_version_signature_upload_view( - document_version=document.latest_version - ) - self.assertEqual(response.status_code, 403) - self.assertEqual(DetachedSignature.objects.count(), 0) - - def test_signature_upload_view_with_access(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) - - self.login_user() - - self.grant_access( - obj=document, - permission=permission_document_version_signature_upload - ) - - response = self._request_document_version_signature_upload_view( - document_version=document.latest_version - ) - self.assertEqual(response.status_code, 302) - self.assertEqual(DetachedSignature.objects.count(), 1) - - def _request_document_version_signature_download_view(self, signature): + def _request_document_version_signature_download_view(self): return self.get( viewname='signatures:document_version_signature_download', - args=(signature.pk,), + kwargs={'signature_id': self.test_signature.pk} ) def test_signature_download_view_no_permission(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + self._upload_test_signature() - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - signature = DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) - - self.login_user() - - response = self._request_document_version_signature_download_view( - signature=signature - ) - self.assertEqual(response.status_code, 403) + response = self._request_document_version_signature_download_view() + self.assertEqual(response.status_code, 404) def test_signature_download_view_with_access(self): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - signature = DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) - - self.login_user() + self._upload_test_signature() self.grant_access( - obj=document, + obj=self.test_document, permission=permission_document_version_signature_download ) self.expected_content_type = 'application/octet-stream; charset=utf-8' - response = self._request_document_version_signature_download_view( - signature=signature - ) + response = self._request_document_version_signature_download_view() - with signature.signature_file as file_object: + with self.test_signature.signature_file as file_object: assert_download_response( self, response=response, content=file_object.read(), ) - def _request_document_version_signature_delete_view(self, signature): - return self.post( - viewname='signatures:document_version_signature_delete', - args=(signature.pk,) + def _request_document_version_signature_list_view(self): + return self.get( + viewname='signatures:document_version_signature_list', + kwargs={'document_version_id': self.test_document.latest_version.pk} ) - def test_signature_delete_view_no_permission(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - Key.objects.create(key_data=file_object.read()) + def test_signature_list_view_no_permission(self): + self._create_test_key() - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() - with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - signature = DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) - ) + self._upload_test_signature() - self.login_user() + response = self._request_document_version_signature_list_view() + self.assertEqual(response.status_code, 404) + + def test_signature_list_view_with_access(self): + self._create_test_key() + + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + + self._upload_test_signature() self.grant_access( - obj=document, + obj=self.test_document, permission=permission_document_version_signature_view ) - response = self._request_document_version_signature_delete_view( - signature=signature - ) - self.assertEqual(response.status_code, 403) - self.assertEqual(DetachedSignature.objects.count(), 1) - - def test_signature_delete_view_with_access(self): - with open(TEST_KEY_FILE, mode='rb') as file_object: - Key.objects.create(key_data=file_object.read()) - - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - document = self.document_type.new_document( - file_object=file_object - ) + response = self._request_document_version_signature_list_view() + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['object_list'].count(), 1) + def _request_document_version_signature_upload_view(self): with open(TEST_SIGNATURE_FILE_PATH, mode='rb') as file_object: - signature = DetachedSignature.objects.create( - document_version=document.latest_version, - signature_file=File(file_object) + return self.post( + viewname='signatures:document_version_signature_upload', + kwargs={'document_version_id': self.test_document.latest_version.pk}, + data={'signature_file': file_object} ) - self.login_user() + def test_signature_upload_view_no_permission(self): + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() - self.grant_access( - obj=document, - permission=permission_document_version_signature_delete - ) - self.grant_access( - obj=document, - permission=permission_document_version_signature_view - ) - - response = self._request_document_version_signature_delete_view( - signature=signature - ) - self.assertEqual(response.status_code, 302) + response = self._request_document_version_signature_upload_view() + self.assertEqual(response.status_code, 404) self.assertEqual(DetachedSignature.objects.count(), 0) + def test_signature_upload_view_with_access(self): + self.test_document_path = TEST_DOCUMENT_PATH + self.test_document = self.upload_document() + + self.grant_access( + obj=self.test_document, + permission=permission_document_version_signature_upload + ) + + response = self._request_document_version_signature_upload_view() + self.assertEqual(response.status_code, 302) + self.assertEqual(DetachedSignature.objects.count(), 1) + def _request_all_document_version_signature_verify_view(self): return self.post( viewname='signatures:all_document_version_signature_verify' @@ -322,16 +201,12 @@ class SignaturesViewTestCase(GenericDocumentViewTestCase): old_hooks = DocumentVersion._post_save_hooks DocumentVersion._post_save_hooks = {} for count in range(TEST_UNSIGNED_DOCUMENT_COUNT): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.upload_document() for count in range(TEST_SIGNED_DOCUMENT_COUNT): - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.upload_document() self.assertEqual( EmbeddedSignature.objects.unsigned_document_versions().count(), @@ -340,8 +215,6 @@ class SignaturesViewTestCase(GenericDocumentViewTestCase): DocumentVersion._post_save_hooks = old_hooks - self.login_user() - response = self._request_all_document_version_signature_verify_view() self.assertEqual(response.status_code, 403) @@ -362,16 +235,12 @@ class SignaturesViewTestCase(GenericDocumentViewTestCase): old_hooks = DocumentVersion._post_save_hooks DocumentVersion._post_save_hooks = {} for count in range(TEST_UNSIGNED_DOCUMENT_COUNT): - with open(TEST_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_DOCUMENT_PATH + self.upload_document() for count in range(TEST_SIGNED_DOCUMENT_COUNT): - with open(TEST_SIGNED_DOCUMENT_PATH, mode='rb') as file_object: - self.document_type.new_document( - file_object=file_object - ) + self.test_document_path = TEST_SIGNED_DOCUMENT_PATH + self.upload_document() self.assertEqual( EmbeddedSignature.objects.unsigned_document_versions().count(), @@ -380,8 +249,6 @@ class SignaturesViewTestCase(GenericDocumentViewTestCase): DocumentVersion._post_save_hooks = old_hooks - self.login_user() - self.grant_permission( permission=permission_document_version_signature_verify ) diff --git a/mayan/apps/document_signatures/urls.py b/mayan/apps/document_signatures/urls.py index 0756750877..5f2383ca70 100644 --- a/mayan/apps/document_signatures/urls.py +++ b/mayan/apps/document_signatures/urls.py @@ -12,43 +12,43 @@ from .views import ( urlpatterns = [ url( - r'^(?P\d+)/details/$', - DocumentVersionSignatureDetailView.as_view(), - name='document_version_signature_details' + regex=r'^signatures/(?P\d+)/$', + name='document_version_signature_details', + view=DocumentVersionSignatureDetailView.as_view() ), url( - r'^signature/(?P\d+)/download/$', - DocumentVersionSignatureDownloadView.as_view(), - name='document_version_signature_download' + regex=r'^signatures/(?P\d+)/download/$', + name='document_version_signature_download', + view=DocumentVersionSignatureDownloadView.as_view() ), url( - r'^document/version/(?P\d+)/signatures/list/$', - DocumentVersionSignatureListView.as_view(), - name='document_version_signature_list' + regex=r'^signatures/(?P\d+)/delete/$', + name='document_version_signature_delete', + view=DocumentVersionSignatureDeleteView.as_view() ), url( - r'^documents/version/(?P\d+)/signature/detached/upload/$', - DocumentVersionSignatureUploadView.as_view(), - name='document_version_signature_upload' + regex=r'^documents/versions/(?P\d+)/signatures/$', + name='document_version_signature_list', + view=DocumentVersionSignatureListView.as_view() ), url( - r'^documents/version/(?P\d+)/signature/detached/create/$', - DocumentVersionDetachedSignatureCreateView.as_view(), - name='document_version_signature_detached_create' + regex=r'^documents/versions/(?P\d+)/signatures/detached/create/$', + name='document_version_signature_detached_create', + view=DocumentVersionDetachedSignatureCreateView.as_view() ), url( - r'^documents/version/(?P\d+)/signature/embedded/create/$', - DocumentVersionEmbeddedSignatureCreateView.as_view(), - name='document_version_signature_embedded_create' + regex=r'^documents/versions/(?P\d+)/signatures/detached/upload/$', + name='document_version_signature_upload', + view=DocumentVersionSignatureUploadView.as_view() ), url( - r'^signature/(?P\d+)/delete/$', - DocumentVersionSignatureDeleteView.as_view(), - name='document_version_signature_delete' + regex=r'^documents/versions/(?P\d+)/signatures/embedded/create/$', + name='document_version_signature_embedded_create', + view=DocumentVersionEmbeddedSignatureCreateView.as_view() ), url( - r'^tools/all/document/version/signature/verify/$', - AllDocumentSignatureVerifyView.as_view(), - name='all_document_version_signature_verify' - ), + regex=r'^tools/documents/versions/signatures/verify/$', + name='all_document_version_signature_verify', + view=AllDocumentSignatureVerifyView.as_view() + ) ] diff --git a/mayan/apps/document_signatures/views.py b/mayan/apps/document_signatures/views.py index 4be6427c45..e77f4aa261 100644 --- a/mayan/apps/document_signatures/views.py +++ b/mayan/apps/document_signatures/views.py @@ -5,20 +5,18 @@ import logging from django.contrib import messages from django.core.files import File from django.http import HttpResponseRedirect -from django.shortcuts import get_object_or_404 from django.template import RequestContext from django.urls import reverse from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ -from mayan.apps.acls.models import AccessControlList from mayan.apps.common.generics import ( ConfirmView, FormView, SingleObjectCreateView, SingleObjectDeleteView, SingleObjectDetailView, SingleObjectDownloadView, SingleObjectListView ) +from mayan.apps.common.mixins import ExternalObjectMixin from mayan.apps.common.utils import TemporaryFile from mayan.apps.django_gpg.exceptions import NeedPassphrase, PassphraseError -from mayan.apps.django_gpg.permissions import permission_key_sign from mayan.apps.documents.models import DocumentVersion from .forms import ( @@ -45,17 +43,16 @@ from .tasks import task_verify_missing_embedded_signature logger = logging.getLogger(__name__) -class DocumentVersionDetachedSignatureCreateView(FormView): +class DocumentVersionDetachedSignatureCreateView(ExternalObjectMixin, FormView): + external_object_class = DocumentVersion + external_object_permission = permission_document_version_sign_detached + external_object_pk_url_kwarg = 'document_version_id' form_class = DocumentVersionSignatureCreateForm def form_valid(self, form): key = form.cleaned_data['key'] passphrase = form.cleaned_data['passphrase'] or None - AccessControlList.objects.check_access( - permissions=permission_key_sign, user=self.request.user, obj=key - ) - try: with self.get_document_version().open() as file_object: detached_signature = key.sign_file( @@ -64,22 +61,23 @@ class DocumentVersionDetachedSignatureCreateView(FormView): ) except NeedPassphrase: messages.error( - self.request, _('Passphrase is needed to unlock this key.') + message=_('Passphrase is needed to unlock this key.'), + request=self.request ) return HttpResponseRedirect( - reverse( - 'signatures:document_version_signature_detached_create', - args=(self.get_document_version().pk,) + redirect_to=reverse( + viewname='signatures:document_version_signature_detached_create', + kwargs={'document_version_id': self.get_document_version().pk} ) ) except PassphraseError: messages.error( - self.request, _('Passphrase is incorrect.') + message=_('Passphrase is incorrect.'), request=self.request ) return HttpResponseRedirect( - reverse( - 'signatures:document_version_signature_detached_create', - args=(self.get_document_version().pk,) + redirect_to=reverse( + viewname='signatures:document_version_signature_detached_create', + kwargs={'document_version_id': self.get_document_version().pk} ) ) else: @@ -95,25 +93,16 @@ class DocumentVersionDetachedSignatureCreateView(FormView): temporary_file_object.close() messages.success( - self.request, _('Document version signed successfully.') + message=_('Document version signed successfully.'), + request=self.request ) return super( DocumentVersionDetachedSignatureCreateView, self ).form_valid(form) - def dispatch(self, request, *args, **kwargs): - AccessControlList.objects.check_access( - permissions=permission_document_version_sign_detached, - user=request.user, obj=self.get_document_version().document - ) - - return super( - DocumentVersionDetachedSignatureCreateView, self - ).dispatch(request, *args, **kwargs) - def get_document_version(self): - return get_object_or_404(klass=DocumentVersion, pk=self.kwargs['pk']) + return self.get_external_object() def get_extra_context(self): return { @@ -123,33 +112,26 @@ class DocumentVersionDetachedSignatureCreateView(FormView): ) % self.get_document_version(), } - def get_form_kwargs(self): - result = super( - DocumentVersionDetachedSignatureCreateView, self - ).get_form_kwargs() - - result.update({'user': self.request.user}) - - return result + def get_form_extra_kwargs(self): + return {'user': self.request.user} def get_post_action_redirect(self): return reverse( - 'signatures:document_version_signature_list', - args=(self.get_document_version().pk,) + viewname='signatures:document_version_signature_list', + kwargs={'document_version_id': self.get_document_version().pk} ) class DocumentVersionEmbeddedSignatureCreateView(FormView): + external_object_class = DocumentVersion + external_object_permission = permission_document_version_sign_embedded + external_object_pk_url_kwarg = 'document_version_id' form_class = DocumentVersionSignatureCreateForm def form_valid(self, form): key = form.cleaned_data['key'] passphrase = form.cleaned_data['passphrase'] or None - AccessControlList.objects.check_access( - permissions=permission_key_sign, user=self.request.user, obj=key - ) - try: with self.get_document_version().open() as file_object: signature_result = key.sign_file( @@ -157,22 +139,23 @@ class DocumentVersionEmbeddedSignatureCreateView(FormView): ) except NeedPassphrase: messages.error( - self.request, _('Passphrase is needed to unlock this key.') + message=_('Passphrase is needed to unlock this key.'), + request=self.request ) return HttpResponseRedirect( - reverse( - 'signatures:document_version_signature_embedded_create', - args=(self.get_document_version().pk,) + redirect_to=reverse( + viewname='signatures:document_version_signature_embedded_create', + kwargs={'document_version_id': self.get_document_version().pk} ) ) except PassphraseError: messages.error( - self.request, _('Passphrase is incorrect.') + message=_('Passphrase is incorrect.'), request=self.request ) return HttpResponseRedirect( - reverse( - 'signatures:document_version_signature_embedded_create', - args=(self.get_document_version().pk,) + redirect_to=reverse( + viewname='signatures:document_version_signature_embedded_create', + kwargs={'document_version_id': self.get_document_version().pk} ) ) else: @@ -187,13 +170,14 @@ class DocumentVersionEmbeddedSignatureCreateView(FormView): temporary_file_object.close() messages.success( - self.request, _('Document version signed successfully.') + message=_('Document version signed successfully.'), + request=self.request ) return HttpResponseRedirect( - reverse( - 'signatures:document_version_signature_list', - args=(new_version.pk,) + redirect_to=reverse( + viewname='signatures:document_version_signature_list', + kwargs={'document_version_id': new_version.pk} ) ) @@ -201,18 +185,8 @@ class DocumentVersionEmbeddedSignatureCreateView(FormView): DocumentVersionEmbeddedSignatureCreateView, self ).form_valid(form) - def dispatch(self, request, *args, **kwargs): - AccessControlList.objects.check_access( - permissions=permission_document_version_sign_embedded, - user=request.user, obj=self.get_document_version().document - ) - - return super( - DocumentVersionEmbeddedSignatureCreateView, self - ).dispatch(request, *args, **kwargs) - def get_document_version(self): - return get_object_or_404(klass=DocumentVersion, pk=self.kwargs['pk']) + return self.get_external_object() def get_extra_context(self): return { @@ -222,20 +196,13 @@ class DocumentVersionEmbeddedSignatureCreateView(FormView): ) % self.get_document_version(), } - def get_form_kwargs(self): - result = super( - DocumentVersionEmbeddedSignatureCreateView, self - ).get_form_kwargs() - - result.update({'user': self.request.user}) - - return result + def get_form_extra_kwargs(self): + return {'user': self.request.user} class DocumentVersionSignatureDeleteView(SingleObjectDeleteView): - model = DetachedSignature object_permission = permission_document_version_signature_delete - object_permission_related = 'document_version.document' + pk_url_kwarg = 'signature_id' def get_extra_context(self): return { @@ -246,15 +213,18 @@ class DocumentVersionSignatureDeleteView(SingleObjectDeleteView): def get_post_action_redirect(self): return reverse( - 'signatures:document_version_signature_list', - args=(self.get_object().document_version.pk,) + viewname='signatures:document_version_signature_list', + kwargs={'document_version_id': self.get_object().document_version.pk} ) + def get_object_list(self): + return SignatureBaseModel.objects.select_subclasses() + class DocumentVersionSignatureDetailView(SingleObjectDetailView): form_class = DocumentVersionSignatureDetailForm object_permission = permission_document_version_signature_view - object_permission_related = 'document_version.document' + pk_url_kwarg = 'signature_id' def get_extra_context(self): return { @@ -266,14 +236,13 @@ class DocumentVersionSignatureDetailView(SingleObjectDetailView): ) % self.get_object(), } - def get_queryset(self): + def get_object_list(self): return SignatureBaseModel.objects.select_subclasses() class DocumentVersionSignatureDownloadView(SingleObjectDownloadView): - model = DetachedSignature object_permission = permission_document_version_signature_download - object_permission_related = 'document_version.document' + pk_url_kwarg = 'signature_id' def get_file(self): signature = self.get_object() @@ -282,20 +251,17 @@ class DocumentVersionSignatureDownloadView(SingleObjectDownloadView): signature.signature_file, name=force_text(signature) ) + def get_object_list(self): + return SignatureBaseModel.objects.select_subclasses() -class DocumentVersionSignatureListView(SingleObjectListView): - def dispatch(self, request, *args, **kwargs): - AccessControlList.objects.check_access( - permissions=permission_document_version_signature_view, - user=request.user, obj=self.get_document_version() - ) - return super( - DocumentVersionSignatureListView, self - ).dispatch(request, *args, **kwargs) +class DocumentVersionSignatureListView(ExternalObjectMixin, SingleObjectListView): + external_object_class = DocumentVersion + external_object_permission = permission_document_version_signature_view + external_object_pk_url_kwarg = 'document_version_id' def get_document_version(self): - return get_object_or_404(klass=DocumentVersion, pk=self.kwargs['pk']) + return self.get_external_object() def get_extra_context(self): return { @@ -335,22 +301,15 @@ class DocumentVersionSignatureListView(SingleObjectListView): return self.get_document_version().signatures.all() -class DocumentVersionSignatureUploadView(SingleObjectCreateView): +class DocumentVersionSignatureUploadView(ExternalObjectMixin, SingleObjectCreateView): + external_object_class = DocumentVersion + external_object_permission = permission_document_version_signature_upload + external_object_pk_url_kwarg = 'document_version_id' fields = ('signature_file',) model = DetachedSignature - def dispatch(self, request, *args, **kwargs): - AccessControlList.objects.check_access( - permissions=permission_document_version_signature_upload, - user=request.user, obj=self.get_document_version() - ) - - return super( - DocumentVersionSignatureUploadView, self - ).dispatch(request, *args, **kwargs) - def get_document_version(self): - return get_object_or_404(klass=DocumentVersion, pk=self.kwargs['pk']) + return self.get_external_object() def get_extra_context(self): return { @@ -365,8 +324,8 @@ class DocumentVersionSignatureUploadView(SingleObjectCreateView): def get_post_action_redirect(self): return reverse( - 'signatures:document_version_signature_list', - args=(self.get_document_version().pk,) + viewname='signatures:document_version_signature_list', + kwargs={'document_version_id': self.get_document_version().pk} ) @@ -379,10 +338,11 @@ class AllDocumentSignatureVerifyView(ConfirmView): view_permission = permission_document_version_signature_verify def get_post_action_redirect(self): - return reverse('common:tools_list') + return reverse(viewname='common:tools_list') def view_action(self): task_verify_missing_embedded_signature.delay() messages.success( - self.request, _('Signature verification queued successfully.') + message=_('Signature verification queued successfully.'), + request=self.request )