diff --git a/.travis.yml b/.travis.yml index b014915..20bc9a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: python env: - TOX_ENV=django18 - TOX_ENV=django19 + - TOX_ENV=django110 + - TOX_ENV=django111 - TOX_ENV=py33 - TOX_ENV=py34 - TOX_ENV=flake8 diff --git a/README.upgrading.rst b/README.upgrading.rst index 4aeae85..a521390 100644 --- a/README.upgrading.rst +++ b/README.upgrading.rst @@ -20,6 +20,8 @@ The following table maps django-sshkey version to migration labels: +---------+---------------+-------+------------------------------------------+ | 2.4 | django_sshkey | 0001 | Django native migrations started. | +---------+---------------+-------+------------------------------------------+ +| 2.5 | django_sshkey | 0002 | | ++---------+---------------+-------+------------------------------------------+ To upgrade, install the new version of django-sshkey and then migrate your project to its corresponding label from the table above using the following diff --git a/RELEASE-NOTES.rst b/RELEASE-NOTES.rst index 2d5db3e..2239059 100644 --- a/RELEASE-NOTES.rst +++ b/RELEASE-NOTES.rst @@ -2,6 +2,20 @@ Release Notes for django-sshkey =============================== +2.5.0 (2016-06-16) +------------------ + +Migration label: 0002 + +* Stop testing against Django 1.4 through 1.7. +* Start testing against Django 1.9. +* Support for Python 3.3 and 3.4 (issue #6). +* Support OpenSSH 6.8+ MD5 and SHA256 fingerprints (issue #5). Also makes + django-sshkey compatible with fingerprints of unpatched OpenSSH 6.9+ + ``AuthorizedKeysCommand`` (issue #3). Add ``SSHKEY_DEFAULT_HASH`` setting. +* Add ``import_sshkey`` and ``normalize_sshkeys`` management commands. +* Code formatting cleanup. + 2.4.0 (2015-09-21) ------------------ diff --git a/django_sshkey/__init__.py b/django_sshkey/__init__.py index 39cd305..7afd9d7 100644 --- a/django_sshkey/__init__.py +++ b/django_sshkey/__init__.py @@ -27,4 +27,4 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -__version__ = '2.4.0' +__version__ = '2.5.0' diff --git a/django_sshkey/models.py b/django_sshkey/models.py index e2ca36b..245cd80 100644 --- a/django_sshkey/models.py +++ b/django_sshkey/models.py @@ -28,7 +28,7 @@ # POSSIBILITY OF SUCH DAMAGE. from django.db import models -from django.contrib.auth.models import User +from django.conf import settings as django_settings from django.core.exceptions import ValidationError from django.db.models.signals import pre_save from django.dispatch import receiver @@ -42,7 +42,8 @@ class UserKey(models.Model): - user = models.ForeignKey(User, db_index=True) + user = models.ForeignKey(django_settings.AUTH_USER_MODEL, db_index=True, + on_delete=models.CASCADE) name = models.CharField(max_length=50, blank=True) key = models.TextField(max_length=2000) fingerprint = models.CharField(max_length=128, blank=True, db_index=True) @@ -134,7 +135,7 @@ def send_email_add_key(sender, instance, **kwargs): if request: context_dict['request'] = request context_dict['userkey_list_uri'] = request.build_absolute_uri( - reverse('django_sshkey.views.userkey_list')) + reverse('django_sshkey:userkey_list')) text_content = render_to_string('sshkey/add_key.txt', context_dict) msg = EmailMultiAlternatives( settings.SSHKEY_EMAIL_ADD_KEY_SUBJECT, diff --git a/django_sshkey/templates.example/sshkey/userkey_list.html b/django_sshkey/templates.example/sshkey/userkey_list.html index dd5898a..7f84775 100644 --- a/django_sshkey/templates.example/sshkey/userkey_list.html +++ b/django_sshkey/templates.example/sshkey/userkey_list.html @@ -1,4 +1,3 @@ -{% load url from future %}

My Keys

{% if messages %} {% endif %} -

Add Key

+

Add Key

@@ -30,9 +29,9 @@

My Keys

{% endfor %} diff --git a/django_sshkey/tests.py b/django_sshkey/tests.py index 91a2302..2d20c0e 100644 --- a/django_sshkey/tests.py +++ b/django_sshkey/tests.py @@ -524,7 +524,7 @@ def assertHasKeys(self, response, keys): self.assertEqual(actual, expected) def test_lookup_all(self): - url = reverse('django_sshkey.views.lookup') + url = reverse('django_sshkey:lookup') response = self.client.get(url) self.assertHasKeys(response, [ 'command="user1 %s" %s' % ( @@ -542,7 +542,7 @@ def test_lookup_all(self): ]) def test_lookup_by_fingerprint(self): - url = reverse('django_sshkey.views.lookup') + url = reverse('django_sshkey:lookup') fingerprint = ssh_fingerprint(self.key1_path + '.pub', hash='legacy') response = self.client.get(url, {'fingerprint': fingerprint}) self.assertHasKeys(response, [ @@ -553,7 +553,7 @@ def test_lookup_by_fingerprint(self): ]) def test_lookup_by_username_single_result(self): - url = reverse('django_sshkey.views.lookup') + url = reverse('django_sshkey:lookup') username = self.user2.username response = self.client.get(url, {'username': username}) self.assertHasKeys(response, [ @@ -564,7 +564,7 @@ def test_lookup_by_username_single_result(self): ]) def test_lookup_by_username_multiple_results(self): - url = reverse('django_sshkey.views.lookup') + url = reverse('django_sshkey:lookup') response = self.client.get(url, {'username': self.user1.username}) self.assertHasKeys(response, [ 'command="user1 %s" %s' % ( @@ -578,13 +578,13 @@ def test_lookup_by_username_multiple_results(self): ]) def test_lookup_nonexist_fingerprint(self): - url = reverse('django_sshkey.views.lookup') + url = reverse('django_sshkey:lookup') fingerprint = ':'.join(['ff'] * 16) response = self.client.get(url, {'fingerprint': fingerprint}) self.assertHasKeys(response, []) def test_lookup_nonexist_username(self): - url = reverse('django_sshkey.views.lookup') + url = reverse('django_sshkey:lookup') response = self.client.get(url, {'username': 'batman'}) self.assertHasKeys(response, []) diff --git a/django_sshkey/urls.py b/django_sshkey/urls.py index 26d0dfa..95c4186 100644 --- a/django_sshkey/urls.py +++ b/django_sshkey/urls.py @@ -1,4 +1,5 @@ # Copyright (c) 2014-2016, Clemson University +# Copyright (c) 2017, Baptiste Jonglez # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,15 +28,15 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -try: - from django.conf.urls.defaults import patterns, url -except ImportError: - from django.conf.urls import patterns, url +from django.conf.urls import url -urlpatterns = patterns('django_sshkey.views', - url(r'^lookup$', 'lookup'), # noqa - url(r'^$', 'userkey_list'), - url(r'^add$', 'userkey_add'), - url(r'^(?P\d+)$', 'userkey_edit'), - url(r'^(?P\d+)/delete$', 'userkey_delete'), -) +from . import views + +app_name = "django_sshkey" +urlpatterns = [ + url(r'^lookup$', views.lookup, name='lookup'), # noqa + url(r'^$', views.userkey_list, name='userkey_list'), + url(r'^add$', views.userkey_add, name='userkey_add'), + url(r'^(?P\d+)$', views.userkey_edit, name='userkey_edit'), + url(r'^(?P\d+)/delete$', views.userkey_delete, name='userkey_delete'), +] diff --git a/django_sshkey/views.py b/django_sshkey/views.py index fa0b2ac..42b8345 100644 --- a/django_sshkey/views.py +++ b/django_sshkey/views.py @@ -30,7 +30,7 @@ from django.http import HttpResponse, HttpResponseRedirect from django.views.decorators.http import require_http_methods, require_GET from django.views.decorators.csrf import csrf_exempt -from django.shortcuts import get_object_or_404, render_to_response +from django.shortcuts import get_object_or_404, render from django.template import RequestContext from django.contrib import messages from django.contrib.auth.decorators import login_required @@ -76,10 +76,8 @@ def lookup(request): @require_GET def userkey_list(request): userkey_list = UserKey.objects.filter(user=request.user) - return render_to_response( - 'sshkey/userkey_list.html', - {'userkey_list': userkey_list, 'allow_edit': settings.SSHKEY_ALLOW_EDIT}, - context_instance=RequestContext(request), + return render(request, 'sshkey/userkey_list.html', + context={'userkey_list': userkey_list, 'allow_edit': settings.SSHKEY_ALLOW_EDIT} ) @@ -92,7 +90,7 @@ def userkey_add(request): form = UserKeyForm(request.POST, instance=userkey) if form.is_valid(): form.save() - default_redirect = reverse('django_sshkey.views.userkey_list') + default_redirect = reverse('django_sshkey:userkey_list') url = request.GET.get('next', default_redirect) if not is_safe_url(url=url, host=request.get_host()): url = default_redirect @@ -101,11 +99,8 @@ def userkey_add(request): return HttpResponseRedirect(url) else: form = UserKeyForm() - return render_to_response( - 'sshkey/userkey_detail.html', - {'form': form, 'action': 'add'}, - context_instance=RequestContext(request), - ) + return render(request, 'sshkey/userkey_detail.html', + context={'form': form, 'action': 'add'}) @login_required @@ -120,7 +115,7 @@ def userkey_edit(request, pk): form = UserKeyForm(request.POST, instance=userkey) if form.is_valid(): form.save() - default_redirect = reverse('django_sshkey.views.userkey_list') + default_redirect = reverse('django_sshkey:userkey_list') url = request.GET.get('next', default_redirect) if not is_safe_url(url=url, host=request.get_host()): url = default_redirect @@ -129,11 +124,8 @@ def userkey_edit(request, pk): return HttpResponseRedirect(url) else: form = UserKeyForm(instance=userkey) - return render_to_response( - 'sshkey/userkey_detail.html', - {'form': form, 'action': 'edit'}, - context_instance=RequestContext(request), - ) + return render(request, 'sshkey/userkey_detail.html', + context={'form': form, 'action': 'edit'}) @login_required @@ -145,4 +137,4 @@ def userkey_delete(request, pk): userkey.delete() message = 'SSH public key %s was deleted.' % userkey.name messages.success(request, message, fail_silently=True) - return HttpResponseRedirect(reverse('django_sshkey.views.userkey_list')) + return HttpResponseRedirect(reverse('django_sshkey:userkey_list')) diff --git a/setup.py b/setup.py index 493bb64..dc41303 100644 --- a/setup.py +++ b/setup.py @@ -59,6 +59,8 @@ 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', ], diff --git a/testproject/settings.py b/testproject/settings.py index f27545d..4bf6348 100644 --- a/testproject/settings.py +++ b/testproject/settings.py @@ -23,8 +23,6 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -TEMPLATE_DEBUG = True - ALLOWED_HOSTS = [] @@ -85,9 +83,26 @@ STATIC_URL = '/static/' -TEMPLATE_DIRS = ( - os.path.join(BASE_DIR, 'testproject', 'templates'), -) +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(BASE_DIR, 'testproject', 'templates'), + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.debug', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] import getpass import socket diff --git a/testproject/urls.py b/testproject/urls.py index d697339..a197779 100644 --- a/testproject/urls.py +++ b/testproject/urls.py @@ -1,12 +1,9 @@ -try: - from django.conf.urls import patterns, include, url -except ImportError: - from django.conf.urls.defaults import patterns, include, url +from django.conf.urls import include, url from django.contrib import admin admin.autodiscover() -urlpatterns = patterns('', - url(r'^', include('django_sshkey.urls')), +urlpatterns = [ + url(r'^', include('django_sshkey.urls', namespace='django_sshkey')), url(r'^admin/', include(admin.site.urls)), -) +] diff --git a/tox.ini b/tox.ini index 5b88777..a65f48e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = django16,django18,django19,flake8 +envlist = django18,django19,django110,django111,flake8 [testenv] commands = {envpython} manage.py test django_sshkey.tests [] @@ -12,7 +12,15 @@ deps = [testenv:django19] deps = - Django < 2.0 + Django < 1.10 + +[testenv:django110] +deps = + Django < 1.11 + +[testenv:django111] +deps = + Django < 1.12 [testenv:flake8] commands = flake8 lookup.py manage.py setup.py django_sshkey
Key {{ userkey.last_used|default:"never" }} {% if allow_edit %} - Edit + Edit {% endif %} - Delete + Delete