From fc29309f68e7b2f0297a95fbee10f5ce4ba84018 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 20 Jan 2019 18:08:47 -0400 Subject: [PATCH] Update Django GPG app Add keyword arguments to all calls. Rename URL parameters to be explicit ("key_id"). Add key delete view test. Update tests to use a mixin for repeated key creation code. Grant permissions and access the proper way using self.grant_permission and self.grant_access. Signed-off-by: Roberto Rosario --- mayan/apps/django_gpg/api_views.py | 2 + mayan/apps/django_gpg/classes.py | 36 +++++----- mayan/apps/django_gpg/forms.py | 4 +- mayan/apps/django_gpg/links.py | 16 +++-- mayan/apps/django_gpg/literals.py | 1 + mayan/apps/django_gpg/models.py | 4 +- mayan/apps/django_gpg/permissions.py | 14 ++-- mayan/apps/django_gpg/serializers.py | 1 + mayan/apps/django_gpg/settings.py | 6 +- mayan/apps/django_gpg/tests/literals.py | 12 ++++ mayan/apps/django_gpg/tests/mixins.py | 9 +++ mayan/apps/django_gpg/tests/test_api.py | 6 +- mayan/apps/django_gpg/tests/test_models.py | 49 +++++-------- mayan/apps/django_gpg/tests/test_views.py | 81 +++++++++++++--------- mayan/apps/django_gpg/urls.py | 37 +++++----- mayan/apps/django_gpg/views.py | 13 ++-- 16 files changed, 168 insertions(+), 123 deletions(-) create mode 100644 mayan/apps/django_gpg/tests/mixins.py diff --git a/mayan/apps/django_gpg/api_views.py b/mayan/apps/django_gpg/api_views.py index 47014873da..dc7fcfa4f7 100644 --- a/mayan/apps/django_gpg/api_views.py +++ b/mayan/apps/django_gpg/api_views.py @@ -31,6 +31,8 @@ class APIKeyView(generics.RetrieveDestroyAPIView): get: Return the details of the selected key. """ filter_backends = (MayanObjectPermissionsFilter,) + lookup_field = 'pk' + lookup_url_kwarg = 'key_id' mayan_object_permissions = { 'DELETE': (permission_key_delete,), 'GET': (permission_key_view,), diff --git a/mayan/apps/django_gpg/classes.py b/mayan/apps/django_gpg/classes.py index 510cc2892d..7243b63744 100644 --- a/mayan/apps/django_gpg/classes.py +++ b/mayan/apps/django_gpg/classes.py @@ -17,6 +17,24 @@ class GPGBackend(object): self.kwargs = kwargs +class KeyStub(object): + def __init__(self, raw): + self.fingerprint = raw['keyid'] + self.key_type = raw['type'] + self.date = date.fromtimestamp(int(raw['date'])) + if raw['expires']: + self.expires = date.fromtimestamp(int(raw['expires'])) + else: + self.expires = None + self.length = raw['length'] + self.user_id = raw['uids'] + + @property + def key_id(self): + return self.fingerprint[-8:] + key_id.fget.short_description = _('Key ID') + + class PythonGNUPGBackend(GPGBackend): @staticmethod def _import_key(gpg, **kwargs): @@ -136,24 +154,6 @@ class PythonGNUPGBackend(GPGBackend): ) -class KeyStub(object): - def __init__(self, raw): - self.fingerprint = raw['keyid'] - self.key_type = raw['type'] - self.date = date.fromtimestamp(int(raw['date'])) - if raw['expires']: - self.expires = date.fromtimestamp(int(raw['expires'])) - else: - self.expires = None - self.length = raw['length'] - self.user_id = raw['uids'] - - @property - def key_id(self): - return self.fingerprint[-8:] - key_id.fget.short_description = _('Key ID') - - class SignatureVerification(object): def __init__(self, raw): self.user_id = raw['username'] diff --git a/mayan/apps/django_gpg/forms.py b/mayan/apps/django_gpg/forms.py index 1d72806e93..8d7795b2d9 100644 --- a/mayan/apps/django_gpg/forms.py +++ b/mayan/apps/django_gpg/forms.py @@ -44,6 +44,6 @@ class KeyDetailForm(DetailForm): class KeySearchForm(forms.Form): term = forms.CharField( - label=_('Term'), - help_text=_('Name, e-mail, key ID or key fingerprint to look for.') + help_text=_('Name, e-mail, key ID or key fingerprint to look for.'), + label=_('Term') ) diff --git a/mayan/apps/django_gpg/links.py b/mayan/apps/django_gpg/links.py index 32eb85ff78..08264795d3 100644 --- a/mayan/apps/django_gpg/links.py +++ b/mayan/apps/django_gpg/links.py @@ -11,16 +11,18 @@ from .permissions import ( ) link_key_delete = Link( - args=('resolved_object.pk',), permissions=(permission_key_delete,), - tags='dangerous', text=_('Delete'), view='django_gpg:key_delete', + kwargs={'key_id': 'resolved_object.pk'}, + permissions=(permission_key_delete,), tags='dangerous', text=_('Delete'), + view='django_gpg:key_delete' ) link_key_detail = Link( - args=('resolved_object.pk',), permissions=(permission_key_view,), - text=_('Details'), view='django_gpg:key_detail', + kwargs={'key_id': 'resolved_object.pk'}, permissions=(permission_key_view,), + text=_('Details'), view='django_gpg:key_detail' ) link_key_download = Link( - args=('resolved_object.pk',), permissions=(permission_key_download,), - text=_('Download'), view='django_gpg:key_download', + kwargs={'key_id': 'resolved_object.pk'}, + permissions=(permission_key_download,), text=_('Download'), + view='django_gpg:key_download' ) link_key_query = Link( icon_class=icon_keyserver_search, @@ -28,7 +30,7 @@ link_key_query = Link( view='django_gpg:key_query' ) link_key_receive = Link( - args='object.key_id', keep_query=True, + keep_query=True, kwargs={'key_id': 'object.key_id'}, permissions=(permission_key_receive,), text=_('Import'), view='django_gpg:key_receive', ) diff --git a/mayan/apps/django_gpg/literals.py b/mayan/apps/django_gpg/literals.py index ea85b945ab..ed97da11c6 100644 --- a/mayan/apps/django_gpg/literals.py +++ b/mayan/apps/django_gpg/literals.py @@ -9,6 +9,7 @@ if platform.system() == 'OpenBSD': else: DEFAULT_GPG_PATH = '/usr/bin/gpg1' +DEFAULT_KEYSERVER = 'pool.sks-keyservers.net' DEFAULT_SETTING_GPG_BACKEND = 'mayan.apps.django_gpg.classes.PythonGNUPGBackend' ERROR_MSG_BAD_PASSPHRASE = 'BAD_PASSPHRASE' diff --git a/mayan/apps/django_gpg/models.py b/mayan/apps/django_gpg/models.py index 6ab1aab7f2..c59748b63d 100644 --- a/mayan/apps/django_gpg/models.py +++ b/mayan/apps/django_gpg/models.py @@ -77,7 +77,9 @@ class Key(models.Model): raise ValidationError(_('Key already exists.')) def get_absolute_url(self): - return reverse('django_gpg:key_detail', args=(self.pk,)) + return reverse( + viewname='django_gpg:key_detail', kwargs={'key_pk': self.pk} + ) @property def key_id(self): diff --git a/mayan/apps/django_gpg/permissions.py b/mayan/apps/django_gpg/permissions.py index ee129ab114..c2a2ab2cb9 100644 --- a/mayan/apps/django_gpg/permissions.py +++ b/mayan/apps/django_gpg/permissions.py @@ -7,23 +7,23 @@ from mayan.apps.permissions import PermissionNamespace namespace = PermissionNamespace(label=_('Key management'), name='django_gpg') permission_key_delete = namespace.add_permission( - name='key_delete', label=_('Delete keys') + label=_('Delete keys'), name='key_delete' ) permission_key_download = namespace.add_permission( - name='key_download', label=_('Download keys') + label=_('Download keys'), name='key_download' ) permission_key_receive = namespace.add_permission( - name='key_receive', label=_('Import keys from keyservers') + label=_('Import keys from keyservers'), name='key_receive' ) permission_key_sign = namespace.add_permission( - name='key_sign', label=_('Use keys to sign content') + label=_('Use keys to sign content'), name='key_sign' ) permission_key_upload = namespace.add_permission( - name='key_upload', label=_('Upload keys') + label=_('Upload keys'), name='key_upload' ) permission_key_view = namespace.add_permission( - name='key_view', label=_('View keys') + label=_('View keys'), name='key_view' ) permission_keyserver_query = namespace.add_permission( - name='keyserver_query', label=_('Query keyservers') + label=_('Query keyservers'), name='keyserver_query' ) diff --git a/mayan/apps/django_gpg/serializers.py b/mayan/apps/django_gpg/serializers.py index df3c965690..6191ea6f24 100644 --- a/mayan/apps/django_gpg/serializers.py +++ b/mayan/apps/django_gpg/serializers.py @@ -8,6 +8,7 @@ from .models import Key class KeySerializer(serializers.ModelSerializer): class Meta: extra_kwargs = { + 'lookup_url_kwarg': 'key_id', 'url': {'view_name': 'rest_api:key-detail'}, } fields = ( diff --git a/mayan/apps/django_gpg/settings.py b/mayan/apps/django_gpg/settings.py index 87171619db..0559a1504f 100644 --- a/mayan/apps/django_gpg/settings.py +++ b/mayan/apps/django_gpg/settings.py @@ -4,7 +4,9 @@ from django.utils.translation import ugettext_lazy as _ from mayan.apps.smart_settings import Namespace -from .literals import DEFAULT_GPG_PATH, DEFAULT_SETTING_GPG_BACKEND +from .literals import ( + DEFAULT_GPG_PATH, DEFAULT_KEYSERVER, DEFAULT_SETTING_GPG_BACKEND +) namespace = Namespace(name='django_gpg', label=_('Signatures')) @@ -23,6 +25,6 @@ setting_gpg_backend_arguments = namespace.add_setting( ) ) setting_keyserver = namespace.add_setting( - global_name='SIGNATURES_KEYSERVER', default='pool.sks-keyservers.net', + global_name='SIGNATURES_KEYSERVER', default=DEFAULT_KEYSERVER, help_text=_('Keyserver used to query for keys.') ) diff --git a/mayan/apps/django_gpg/tests/literals.py b/mayan/apps/django_gpg/tests/literals.py index 3bcbe01ab3..c7dca32a6a 100644 --- a/mayan/apps/django_gpg/tests/literals.py +++ b/mayan/apps/django_gpg/tests/literals.py @@ -4,6 +4,18 @@ import os from django.conf import settings +MOCK_SEARCH_KEYS_RESPONSE = [ + { + 'algo': u'1', + 'date': u'1311475606', + 'expires': u'1643601600', + 'keyid': u'607138F1AECC5A5CA31CB7715F3F7F75D210724D', + 'length': u'2048', + 'type': u'pub', + 'uids': [u'Roberto Rosario '] + } +] + TEST_DETACHED_SIGNATURE = os.path.join( settings.BASE_DIR, 'apps', 'django_gpg', 'tests', 'contrib', 'test_files', 'test_file.txt.asc' diff --git a/mayan/apps/django_gpg/tests/mixins.py b/mayan/apps/django_gpg/tests/mixins.py new file mode 100644 index 0000000000..01294af113 --- /dev/null +++ b/mayan/apps/django_gpg/tests/mixins.py @@ -0,0 +1,9 @@ +from ..models import Key + +from .literals import TEST_KEY_DATA + + +class KeyTestMixin(object): + def _create_test_key(self): + # Creating a Key instance is analogous to importing a key + self.test_key = Key.objects.create(key_data=TEST_KEY_DATA) diff --git a/mayan/apps/django_gpg/tests/test_api.py b/mayan/apps/django_gpg/tests/test_api.py index f46c7034eb..14abdd85f3 100644 --- a/mayan/apps/django_gpg/tests/test_api.py +++ b/mayan/apps/django_gpg/tests/test_api.py @@ -32,7 +32,7 @@ class KeyAPITestCase(BaseAPITestCase): def test_key_create_view_no_permission(self): response = self._request_key_create_view() self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - self.assertEqual(Key.objects.all().count(), 0) + self.assertEqual(Key.objects.count(), 0) def test_key_create_view_with_permission(self): self.grant_permission(permission=permission_key_upload) @@ -50,7 +50,7 @@ class KeyAPITestCase(BaseAPITestCase): def _request_key_delete_view(self): return self.delete( - viewname='rest_api:key-detail', args=(self.key.pk,) + viewname='rest_api:key-detail', kwargs={'key_id': self.key.pk} ) def test_key_delete_view_no_access(self): @@ -72,7 +72,7 @@ class KeyAPITestCase(BaseAPITestCase): def _request_key_detail_view(self): return self.get( - viewname='rest_api:key-detail', args=(self.key.pk,) + viewname='rest_api:key-detail', kwargs={'key_id': self.key.pk} ) def test_key_detail_view_no_access(self): diff --git a/mayan/apps/django_gpg/tests/test_models.py b/mayan/apps/django_gpg/tests/test_models.py index 763166f905..9273cfd065 100644 --- a/mayan/apps/django_gpg/tests/test_models.py +++ b/mayan/apps/django_gpg/tests/test_models.py @@ -17,22 +17,12 @@ from ..exceptions import ( from ..models import Key from .literals import ( - TEST_DETACHED_SIGNATURE, TEST_FILE, TEST_KEY_DATA, TEST_KEY_FINGERPRINT, - TEST_KEY_PASSPHRASE, TEST_RECEIVE_KEY, TEST_SEARCH_FINGERPRINT, - TEST_SEARCH_UID, TEST_SIGNED_FILE, TEST_SIGNED_FILE_CONTENT + MOCK_SEARCH_KEYS_RESPONSE, TEST_DETACHED_SIGNATURE, TEST_FILE, + TEST_KEY_FINGERPRINT, TEST_KEY_PASSPHRASE, TEST_RECEIVE_KEY, + TEST_SEARCH_FINGERPRINT, TEST_SEARCH_UID, TEST_SIGNED_FILE, + TEST_SIGNED_FILE_CONTENT ) - -MOCK_SEARCH_KEYS_RESPONSE = [ - { - 'algo': u'1', - 'date': u'1311475606', - 'expires': u'1643601600', - 'keyid': u'607138F1AECC5A5CA31CB7715F3F7F75D210724D', - 'length': u'2048', - 'type': u'pub', - 'uids': [u'Roberto Rosario '] - } -] +from .mixins import KeyTestMixin def mock_recv_keys(self, keyserver, *keyids): @@ -45,12 +35,11 @@ def mock_recv_keys(self, keyserver, *keyids): return ImportResult() -class KeyTestCase(BaseTestCase): +class KeyTestCase(KeyTestMixin, BaseTestCase): def test_key_instance_creation(self): - # Creating a Key instance is analogous to importing a key - key = Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() - self.assertEqual(key.fingerprint, TEST_KEY_FINGERPRINT) + self.assertEqual(self.test_key.fingerprint, TEST_KEY_FINGERPRINT) @mock.patch.object(gnupg.GPG, 'search_keys', autospec=True) def test_key_search(self, search_keys): @@ -92,7 +81,7 @@ class KeyTestCase(BaseTestCase): self.assertTrue(result.key_id in TEST_KEY_FINGERPRINT) def test_embedded_verification_with_key(self): - Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() with open(TEST_SIGNED_FILE, mode='rb') as signed_file: result = Key.objects.verify_file(signed_file) @@ -100,7 +89,7 @@ class KeyTestCase(BaseTestCase): self.assertEqual(result.fingerprint, TEST_KEY_FINGERPRINT) def test_embedded_verification_with_correct_fingerprint(self): - Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() with open(TEST_SIGNED_FILE, mode='rb') as signed_file: result = Key.objects.verify_file( @@ -111,14 +100,14 @@ class KeyTestCase(BaseTestCase): self.assertEqual(result.fingerprint, TEST_KEY_FINGERPRINT) def test_embedded_verification_with_incorrect_fingerprint(self): - Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() with open(TEST_SIGNED_FILE, mode='rb') as signed_file: with self.assertRaises(KeyDoesNotExist): Key.objects.verify_file(signed_file, key_fingerprint='999') def test_signed_file_decryption(self): - Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() with open(TEST_SIGNED_FILE, mode='rb') as signed_file: result = Key.objects.decrypt_file(file_object=signed_file) @@ -145,7 +134,7 @@ class KeyTestCase(BaseTestCase): self.assertTrue(result.key_id in TEST_KEY_FINGERPRINT) def test_detached_verification_with_key(self): - Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() with open(TEST_DETACHED_SIGNATURE, mode='rb') as signature_file: with open(TEST_FILE, mode='rb') as test_file: @@ -157,29 +146,29 @@ class KeyTestCase(BaseTestCase): self.assertEqual(result.fingerprint, TEST_KEY_FINGERPRINT) def test_detached_signing_no_passphrase(self): - key = Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() with self.assertRaises(NeedPassphrase): with open(TEST_FILE, mode='rb') as test_file: - key.sign_file( + self.test_key.sign_file( file_object=test_file, detached=True, ) def test_detached_signing_bad_passphrase(self): - key = Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() with self.assertRaises(PassphraseError): with open(TEST_FILE, mode='rb') as test_file: - key.sign_file( + self.test_key.sign_file( file_object=test_file, detached=True, passphrase='bad passphrase' ) def test_detached_signing_with_passphrase(self): - key = Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() with open(TEST_FILE, mode='rb') as test_file: - detached_signature = key.sign_file( + detached_signature = self.test_key.sign_file( file_object=test_file, detached=True, passphrase=TEST_KEY_PASSPHRASE ) diff --git a/mayan/apps/django_gpg/tests/test_views.py b/mayan/apps/django_gpg/tests/test_views.py index 39cb0164be..39c29ea516 100644 --- a/mayan/apps/django_gpg/tests/test_views.py +++ b/mayan/apps/django_gpg/tests/test_views.py @@ -5,62 +5,79 @@ from django_downloadview.test import assert_download_response from mayan.apps.common.tests import GenericViewTestCase from ..models import Key -from ..permissions import permission_key_download, permission_key_upload +from ..permissions import ( + permission_key_delete, permission_key_download, permission_key_upload +) from .literals import TEST_KEY_DATA, TEST_KEY_FINGERPRINT +from .mixins import KeyTestMixin -class KeyViewTestCase(GenericViewTestCase): - def test_key_download_view_no_permission(self): - key = Key.objects.create(key_data=TEST_KEY_DATA) - - self.login_user() - - response = self.get( - viewname='django_gpg:key_download', args=(key.pk,) +class KeyViewTestCase(KeyTestMixin, GenericViewTestCase): + def _request_key_delete_view(self): + return self.post( + viewname='django_gpg:key_delete', + kwargs={'key_id': self.test_key.pk} ) - self.assertEqual(response.status_code, 403) + def test_key_delete_view_no_permission(self): + self._create_test_key() + + response = self._request_key_delete_view() + self.assertEqual(response.status_code, 404) + + def test_key_delete_view_with_access(self): + self._create_test_key() + + self.grant_access(obj=self.test_key, permission=permission_key_delete) + + response = self._request_key_delete_view() + self.assertEqual(response.status_code, 302) + + self.assertEqual(Key.objects.count(), 0) + + def _request_key_download_view(self): + return self.get( + viewname='django_gpg:key_download', + kwargs={'key_id': self.test_key.pk} + ) + + def test_key_download_view_no_permission(self): + self._create_test_key() + + response = self._request_key_download_view() + self.assertEqual(response.status_code, 404) def test_key_download_view_with_permission(self): - key = Key.objects.create(key_data=TEST_KEY_DATA) + self._create_test_key() - self.login_user() - - self.role.permissions.add(permission_key_download.stored_permission) + self.grant_access(obj=self.test_key, permission=permission_key_download) self.expected_content_type = 'application/octet-stream; charset=utf-8' - response = self.get( - viewname='django_gpg:key_download', args=(key.pk,) - ) + response = self._request_key_download_view() assert_download_response( - self, response=response, content=key.key_data, - basename=key.key_id, + test_case=self, response=response, content=self.test_key.key_data, + basename=self.test_key.key_id, ) - def test_key_upload_view_no_permission(self): - self.login_user() - - response = self.post( + def _request_key_upload_view(self): + return self.post( viewname='django_gpg:key_upload', data={'key_data': TEST_KEY_DATA} ) + def test_key_upload_view_no_permission(self): + response = self._request_key_upload_view() self.assertEqual(response.status_code, 403) + self.assertEqual(Key.objects.count(), 0) def test_key_upload_view_with_permission(self): - self.login_user() + self.grant_permission(permission=permission_key_upload) - self.role.permissions.add(permission_key_upload.stored_permission) - - response = self.post( - viewname='django_gpg:key_upload', data={'key_data': TEST_KEY_DATA}, - follow=True - ) - - self.assertContains(response, 'created', status_code=200) + response = self._request_key_upload_view() + self.assertEqual(response.status_code, 302) self.assertEqual(Key.objects.count(), 1) self.assertEqual(Key.objects.first().fingerprint, TEST_KEY_FINGERPRINT) diff --git a/mayan/apps/django_gpg/urls.py b/mayan/apps/django_gpg/urls.py index ac21c86d2d..eaad4a617b 100644 --- a/mayan/apps/django_gpg/urls.py +++ b/mayan/apps/django_gpg/urls.py @@ -11,39 +11,44 @@ from .views import ( urlpatterns = [ url( - r'^(?P\d+)/$', KeyDetailView.as_view(), name='key_detail' + regex=r'^keys/(?P\d+)/$', name='key_detail', + view=KeyDetailView.as_view() ), url( - r'^(?P\d+)/delete/$', KeyDeleteView.as_view(), name='key_delete' + regex=r'^keys/(?P\d+)/delete/$', name='key_delete', + view=KeyDeleteView.as_view() ), url( - r'^(?P\d+)/download/$', KeyDownloadView.as_view(), - name='key_download' + regex=r'^keys/(?P\d+)/download/$', name='key_download', + view=KeyDownloadView.as_view() ), url( - r'^list/private/$', PrivateKeyListView.as_view(), - name='key_private_list' + regex=r'^keys/private/$', name='key_private_list', + view=PrivateKeyListView.as_view() ), url( - r'^list/public/$', PublicKeyListView.as_view(), name='key_public_list' + regex=r'^keys/public/$', name='key_public_list', + view=PublicKeyListView.as_view() ), url( - r'^upload/$', KeyUploadView.as_view(), name='key_upload' + regex=r'^keys/upload/$', name='key_upload', + view=KeyUploadView.as_view() ), - url(r'^query/$', KeyQueryView.as_view(), name='key_query'), + url(regex=r'^keys/query/$', name='key_query', view=KeyQueryView.as_view()), url( - r'^query/results/$', KeyQueryResultView.as_view(), - name='key_query_results' + regex=r'^keys/query/results/$', name='key_query_results', + view=KeyQueryResultView.as_view() ), url( - r'^receive/(?P.+)/$', KeyReceive.as_view(), name='key_receive' - ), + regex=r'^keys/receive/(?P.+)/$', name='key_receive', + view=KeyReceive.as_view() + ) ] api_urls = [ url( - r'^keys/(?P[0-9]+)/$', APIKeyView.as_view(), - name='key-detail' + regex=r'^keys/(?P\d+)/$', name='key-detail', + view=APIKeyView.as_view() ), - url(r'^keys/$', APIKeyListView.as_view(), name='key-list'), + url(regex=r'^keys/$', name='key-list', view=APIKeyListView.as_view()) ] diff --git a/mayan/apps/django_gpg/views.py b/mayan/apps/django_gpg/views.py index 54842cd3b1..5c22ec9d4d 100644 --- a/mayan/apps/django_gpg/views.py +++ b/mayan/apps/django_gpg/views.py @@ -30,12 +30,13 @@ logger = logging.getLogger(__name__) class KeyDeleteView(SingleObjectDeleteView): model = Key object_permission = permission_key_delete + pk_url_kwarg = 'key_id' def get_post_action_redirect(self): if self.get_object().key_type == KEY_TYPE_PUBLIC: - return reverse_lazy('django_gpg:key_public_list') + return reverse_lazy(viewname='django_gpg:key_public_list') else: - return reverse_lazy('django_gpg:key_private_list') + return reverse_lazy(viewname='django_gpg:key_private_list') def get_extra_context(self): return {'title': _('Delete key: %s') % self.get_object()} @@ -45,6 +46,7 @@ class KeyDetailView(SingleObjectDetailView): form_class = KeyDetailForm model = Key object_permission = permission_key_view + pk_url_kwarg = 'key_id' def get_extra_context(self): return { @@ -55,6 +57,7 @@ class KeyDetailView(SingleObjectDetailView): class KeyDownloadView(SingleObjectDownloadView): model = Key object_permission = permission_key_download + pk_url_kwarg = 'key_id' def get_file(self): key = self.get_object() @@ -63,7 +66,7 @@ class KeyDownloadView(SingleObjectDownloadView): class KeyReceive(ConfirmView): - post_action_redirect = reverse_lazy('django_gpg:key_public_list') + post_action_redirect = reverse_lazy(viewname='django_gpg:key_public_list') view_permission = permission_key_receive def get_extra_context(self): @@ -105,7 +108,7 @@ class KeyQueryView(SimpleView): def get_extra_context(self): return { 'form': self.get_form(), - 'form_action': reverse('django_gpg:key_query_results'), + 'form_action': reverse(viewname='django_gpg:key_query_results'), 'submit_icon_class': icon_keyserver_search, 'submit_label': _('Search'), 'submit_method': 'GET', @@ -144,7 +147,7 @@ class KeyQueryResultView(SingleObjectListView): class KeyUploadView(SingleObjectCreateView): fields = ('key_data',) model = Key - post_action_redirect = reverse_lazy('django_gpg:key_public_list') + post_action_redirect = reverse_lazy(viewname='django_gpg:key_public_list') view_permission = permission_key_upload def get_extra_context(self):