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 %}
@@ -7,7 +6,7 @@ My Keys
{% endfor %}
{% endif %}
-Add Key
+Add Key
| Key |
@@ -30,9 +29,9 @@ My Keys
{{ userkey.last_used|default:"never" }} |
{% if allow_edit %}
- Edit
+ Edit
{% endif %}
- Delete
+ Delete
|
{% 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