From d83a80c65be0054e840b1bec12a9c9b337770dc3 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Tue, 29 Mar 2016 16:28:24 -0400 Subject: [PATCH] Add document signature app link tests. --- mayan/apps/document_signatures/links.py | 32 ++--- .../migrations/0003_auto_20160325_0052.py | 76 +++++++++-- .../migrations/0004_auto_20160325_0418.py | 25 +++- .../migrations/0006_auto_20160326_0616.py | 5 +- mayan/apps/document_signatures/permissions.py | 8 +- .../document_signatures/tests/test_links.py | 129 ++++++++++++++++++ .../document_signatures/tests/test_views.py | 5 +- mayan/apps/document_signatures/views.py | 32 ++--- 8 files changed, 253 insertions(+), 59 deletions(-) create mode 100644 mayan/apps/document_signatures/tests/test_links.py diff --git a/mayan/apps/document_signatures/links.py b/mayan/apps/document_signatures/links.py index b5bb879275..66a93d8317 100644 --- a/mayan/apps/document_signatures/links.py +++ b/mayan/apps/document_signatures/links.py @@ -9,6 +9,7 @@ from .permissions import ( permission_document_version_signature_delete, permission_document_version_signature_download, permission_document_version_signature_upload, + permission_document_version_signature_view ) @@ -23,33 +24,32 @@ def is_detached_signature(context): link_document_version_signature_delete = Link( - condition=is_detached_signature, - #permissions=(permission_document_version_signature_delete,), - tags='dangerous', text=_('Delete'), - view='signatures:document_version_signature_delete', - args='resolved_object.pk' + args='resolved_object.pk', condition=is_detached_signature, + permissions=(permission_document_version_signature_delete,), + permissions_related='document_version.document', tags='dangerous', + text=_('Delete'), view='signatures:document_version_signature_delete', ) link_document_version_signature_details = Link( - #permissions=(permission_document_version_signature_view,), - text=_('Details'), + args='resolved_object.pk', + permissions=(permission_document_version_signature_view,), + permissions_related='document_version.document', text=_('Details'), view='signatures:document_version_signature_details', - args='resolved_object.pk' ) link_document_version_signature_list = Link( - #permissions=(permission_document_version_signature_view,), + args='resolved_object.pk', + permissions=(permission_document_version_signature_view,), text=_('Signature list'), view='signatures:document_version_signature_list', - args='resolved_object.pk' ) link_document_version_signature_download = Link( - condition=is_detached_signature, - text=_('Download'), - view='signatures:document_version_signature_download', args='resolved_object.pk', - #permissions=(permission_document_version_signature_download,) + args='resolved_object.pk', condition=is_detached_signature, + permissions=(permission_document_version_signature_download,), + permissions_related='document_version.document', text=_('Download'), + view='signatures:document_version_signature_download', ) link_document_version_signature_upload = Link( - #permissions=(permission_document_version_signature_upload,), + args='resolved_object.pk', + permissions=(permission_document_version_signature_upload,), text=_('Upload signature'), view='signatures:document_version_signature_upload', - args='resolved_object.pk' ) diff --git a/mayan/apps/document_signatures/migrations/0003_auto_20160325_0052.py b/mayan/apps/document_signatures/migrations/0003_auto_20160325_0052.py index 76fa8f097f..044e6f5a35 100644 --- a/mayan/apps/document_signatures/migrations/0003_auto_20160325_0052.py +++ b/mayan/apps/document_signatures/migrations/0003_auto_20160325_0052.py @@ -17,11 +17,34 @@ class Migration(migrations.Migration): migrations.CreateModel( name='SignatureBaseModel', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('date', models.DateField(null=True, verbose_name='Date signed', blank=True)), - ('key_id', models.CharField(max_length=40, verbose_name='Key ID')), - ('signature_id', models.CharField(max_length=64, null=True, verbose_name='Signature ID', blank=True)), - ('public_key_fingerprint', models.CharField(verbose_name='Public key fingerprint', unique=True, max_length=40, editable=False)), + ( + 'id', models.AutoField( + verbose_name='ID', serialize=False, auto_created=True, + primary_key=True + ) + ), + ( + 'date', models.DateField( + null=True, verbose_name='Date signed', blank=True + ) + ), + ( + 'key_id', models.CharField( + max_length=40, verbose_name='Key ID' + ) + ), + ( + 'signature_id', models.CharField( + max_length=64, null=True, verbose_name='Signature ID', + blank=True + ) + ), + ( + 'public_key_fingerprint', models.CharField( + verbose_name='Public key fingerprint', unique=True, + max_length=40, editable=False + ) + ), ], options={ 'verbose_name': 'Document version signature', @@ -35,23 +58,43 @@ class Migration(migrations.Migration): migrations.AddField( model_name='documentversionsignature', name='date', - field=models.DateField(null=True, verbose_name='Date signed', blank=True), + field=models.DateField( + null=True, verbose_name='Date signed', blank=True + ), ), migrations.AddField( model_name='documentversionsignature', name='signature_id', - field=models.CharField(max_length=64, null=True, verbose_name='Signature ID', blank=True), + field=models.CharField( + max_length=64, null=True, verbose_name='Signature ID', + blank=True + ), ), migrations.AlterField( model_name='documentversionsignature', name='document_version', - field=models.ForeignKey(related_name='signature', editable=False, to='documents.DocumentVersion', verbose_name='Document version'), + field=models.ForeignKey( + related_name='signature', editable=False, + to='documents.DocumentVersion', verbose_name='Document version' + ), ), migrations.CreateModel( name='DetachedSignature', fields=[ - ('signaturebasemodel_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='document_signatures.SignatureBaseModel')), - ('signature_file', models.FileField(storage=storage.backends.filebasedstorage.FileBasedStorage(), upload_to=document_signatures.models.upload_to, null=True, verbose_name='Signature file', blank=True)), + ( + 'signaturebasemodel_ptr', models.OneToOneField( + parent_link=True, auto_created=True, primary_key=True, + serialize=False, + to='document_signatures.SignatureBaseModel' + ) + ), + ( + 'signature_file', models.FileField( + storage=storage.backends.filebasedstorage.FileBasedStorage(), + upload_to=document_signatures.models.upload_to, + null=True, verbose_name='Signature file', blank=True + ) + ), ], options={ 'verbose_name': 'Document version detached signature', @@ -62,7 +105,13 @@ class Migration(migrations.Migration): migrations.CreateModel( name='EmbeddedSignature', fields=[ - ('signaturebasemodel_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='document_signatures.SignatureBaseModel')), + ( + 'signaturebasemodel_ptr', models.OneToOneField( + parent_link=True, auto_created=True, primary_key=True, + serialize=False, + to='document_signatures.SignatureBaseModel' + ) + ), ], options={ 'verbose_name': 'Document version embedded signature', @@ -73,6 +122,9 @@ class Migration(migrations.Migration): migrations.AddField( model_name='signaturebasemodel', name='document_version', - field=models.ForeignKey(related_name='signaturebasemodel', editable=False, to='documents.DocumentVersion', verbose_name='Document version'), + field=models.ForeignKey( + related_name='signaturebasemodel', editable=False, + to='documents.DocumentVersion', verbose_name='Document version' + ), ), ] diff --git a/mayan/apps/document_signatures/migrations/0004_auto_20160325_0418.py b/mayan/apps/document_signatures/migrations/0004_auto_20160325_0418.py index 469cf232b9..8cbbd1c419 100644 --- a/mayan/apps/document_signatures/migrations/0004_auto_20160325_0418.py +++ b/mayan/apps/document_signatures/migrations/0004_auto_20160325_0418.py @@ -14,26 +14,41 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='documentversionsignature', name='document_version', - field=models.ForeignKey(editable=False, to='documents.DocumentVersion', verbose_name='Document version'), + field=models.ForeignKey( + editable=False, to='documents.DocumentVersion', + verbose_name='Document version' + ), ), migrations.AlterField( model_name='signaturebasemodel', name='date', - field=models.DateField(verbose_name='Date signed', null=True, editable=False, blank=True), + field=models.DateField( + verbose_name='Date signed', null=True, editable=False, + blank=True + ), ), migrations.AlterField( model_name='signaturebasemodel', name='document_version', - field=models.ForeignKey(related_name='signatures', editable=False, to='documents.DocumentVersion', verbose_name='Document version'), + field=models.ForeignKey( + related_name='signatures', editable=False, + to='documents.DocumentVersion', verbose_name='Document version' + ), ), migrations.AlterField( model_name='signaturebasemodel', name='public_key_fingerprint', - field=models.CharField(null=True, editable=False, max_length=40, blank=True, unique=True, verbose_name='Public key fingerprint'), + field=models.CharField( + null=True, editable=False, max_length=40, blank=True, + unique=True, verbose_name='Public key fingerprint' + ), ), migrations.AlterField( model_name='signaturebasemodel', name='signature_id', - field=models.CharField(verbose_name='Signature ID', max_length=64, null=True, editable=False, blank=True), + field=models.CharField( + verbose_name='Signature ID', max_length=64, null=True, + editable=False, blank=True + ), ), ] diff --git a/mayan/apps/document_signatures/migrations/0006_auto_20160326_0616.py b/mayan/apps/document_signatures/migrations/0006_auto_20160326_0616.py index e5db17f576..adb06aeea3 100644 --- a/mayan/apps/document_signatures/migrations/0006_auto_20160326_0616.py +++ b/mayan/apps/document_signatures/migrations/0006_auto_20160326_0616.py @@ -14,6 +14,9 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='signaturebasemodel', name='public_key_fingerprint', - field=models.CharField(verbose_name='Public key fingerprint', max_length=40, null=True, editable=False, blank=True), + field=models.CharField( + verbose_name='Public key fingerprint', max_length=40, + null=True, editable=False, blank=True + ), ), ] diff --git a/mayan/apps/document_signatures/permissions.py b/mayan/apps/document_signatures/permissions.py index f81ad66806..8db3806b60 100644 --- a/mayan/apps/document_signatures/permissions.py +++ b/mayan/apps/document_signatures/permissions.py @@ -8,10 +8,6 @@ namespace = PermissionNamespace( 'document_signatures', _('Document signatures') ) -permission_document_version_signature_view = namespace.add_permission( - name='document_version_signature_view', - label=_('View details of document signatures') -) permission_document_version_signature_delete = namespace.add_permission( name='document_version_signature_delete', label=_('Delete detached signatures') @@ -24,3 +20,7 @@ permission_document_version_signature_upload = namespace.add_permission( name='document_version_signature_upload', label=_('Upload detached document signatures') ) +permission_document_version_signature_view = namespace.add_permission( + name='document_version_signature_view', + label=_('View details of document signatures') +) diff --git a/mayan/apps/document_signatures/tests/test_links.py b/mayan/apps/document_signatures/tests/test_links.py new file mode 100644 index 0000000000..169af19344 --- /dev/null +++ b/mayan/apps/document_signatures/tests/test_links.py @@ -0,0 +1,129 @@ +from __future__ import unicode_literals + +from django.core.files import File +from django.core.urlresolvers import reverse + +from documents.tests.literals import TEST_DOCUMENT_PATH +from documents.tests.test_views import GenericDocumentViewTestCase +from user_management.tests.literals import ( + TEST_USER_PASSWORD, TEST_USER_USERNAME +) + +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 + + +class DocumentSignatureLinksTestCase(GenericDocumentViewTestCase): + def test_document_version_signature_detail_link_no_permission(self): + with open(TEST_SIGNED_DOCUMENT_PATH) as file_object: + document = self.document_type.new_document( + file_object=file_object + ) + + self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) + + self.add_test_view( + test_object=document.latest_version.signatures.first() + ) + context = self.get_test_view() + resolved_link = link_document_version_signature_details.resolve( + context=context + ) + + self.assertEqual(resolved_link, None) + + def test_document_version_signature_detail_link_with_permission(self): + with open(TEST_SIGNED_DOCUMENT_PATH) as file_object: + document = self.document_type.new_document( + file_object=file_object + ) + + self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) + + self.role.permissions.add( + permission_document_version_signature_view.stored_permission + ) + + self.add_test_view( + test_object=document.latest_version.signatures.first() + ) + context = self.get_test_view() + resolved_link = link_document_version_signature_details.resolve( + context=context + ) + + self.assertNotEqual(resolved_link, None) + self.assertEqual( + resolved_link.url, + reverse( + 'signatures:document_version_signature_details', + args=(document.latest_version.signatures.first().pk,) + ) + ) + + def test_document_version_signature_delete_link_no_permission(self): + with open(TEST_DOCUMENT_PATH) as file_object: + document = self.document_type.new_document( + file_object=file_object + ) + + with open(TEST_SIGNATURE_FILE_PATH) as file_object: + DetachedSignature.objects.create( + document_version=document.latest_version, + signature_file=File(file_object) + ) + + self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) + + self.add_test_view( + test_object=document.latest_version.signatures.first() + ) + context = self.get_test_view() + resolved_link = link_document_version_signature_delete.resolve( + context=context + ) + + self.assertEqual(resolved_link, None) + + def test_document_version_signature_delete_link_with_permission(self): + with open(TEST_DOCUMENT_PATH) as file_object: + document = self.document_type.new_document( + file_object=file_object + ) + + with open(TEST_SIGNATURE_FILE_PATH) as file_object: + DetachedSignature.objects.create( + document_version=document.latest_version, + signature_file=File(file_object) + ) + + self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) + + self.role.permissions.add( + permission_document_version_signature_delete.stored_permission + ) + + self.add_test_view( + test_object=document.latest_version.signatures.first() + ) + context = self.get_test_view() + resolved_link = link_document_version_signature_delete.resolve( + context=context + ) + + self.assertNotEqual(resolved_link, None) + self.assertEqual( + resolved_link.url, + reverse( + 'signatures:document_version_signature_delete', + args=(document.latest_version.signatures.first().pk,) + ) + ) diff --git a/mayan/apps/document_signatures/tests/test_views.py b/mayan/apps/document_signatures/tests/test_views.py index 3565604c22..8bacb24f82 100644 --- a/mayan/apps/document_signatures/tests/test_views.py +++ b/mayan/apps/document_signatures/tests/test_views.py @@ -19,10 +19,7 @@ from ..permissions import ( permission_document_version_signature_upload, ) -from .literals import ( - TEST_SIGNED_DOCUMENT_PATH, TEST_SIGNATURE_FILE_PATH, TEST_KEY_FILE, - TEST_KEY_ID, TEST_SIGNATURE_ID -) +from .literals import TEST_SIGNATURE_FILE_PATH, TEST_KEY_FILE class SignaturesViewTestCase(GenericDocumentViewTestCase): diff --git a/mayan/apps/document_signatures/views.py b/mayan/apps/document_signatures/views.py index 848f946e84..083ae02c22 100644 --- a/mayan/apps/document_signatures/views.py +++ b/mayan/apps/document_signatures/views.py @@ -87,8 +87,20 @@ class DocumentVersionSignatureDownloadView(SingleObjectDownloadView): class DocumentVersionSignatureListView(SingleObjectListView): - object_permission = permission_document_version_signature_view - object_permission_related = 'document_version.document' + def dispatch(self, request, *args, **kwargs): + try: + Permission.check_permissions( + request.user, (permission_document_version_signature_view,) + ) + except PermissionDenied: + AccessControlList.objects.check_access( + permission_document_version_signature_view, request.user, + self.get_document_version() + ) + + return super( + DocumentVersionSignatureListView, self + ).dispatch(request, *args, **kwargs) def get_document_version(self): return get_object_or_404(DocumentVersion, pk=self.kwargs['pk']) @@ -105,21 +117,7 @@ class DocumentVersionSignatureListView(SingleObjectListView): } def get_queryset(self): - queryset = self.get_document_version().signatures.all() - - try: - Permission.check_permissions( - self.request.user, ( - permission_document_version_signature_view, - ) - ) - except PermissionDenied: - return AccessControlList.objects.filter_by_access( - permission_document_version_signature_view, self.request.user, - queryset - ) - else: - return queryset + return self.get_document_version().signatures.all() class DocumentVersionSignatureUploadView(SingleObjectCreateView):