[Python-modules-commits] [python-django-otp] 01/01: New upstream version 0.4.1.1
Michael Fladischer
fladi at moszumanska.debian.org
Wed Nov 1 19:42:49 UTC 2017
This is an automated email from the git hooks/post-receive script.
fladi pushed a commit to branch upstream
in repository python-django-otp.
commit bffb898f169b6a6472907713482d7d99361aaf6b
Author: Michael Fladischer <FladischerMichael at fladi.at>
Date: Wed Nov 1 20:23:03 2017 +0100
New upstream version 0.4.1.1
---
CHANGES | 10 ++++++++++
PKG-INFO | 10 ++++++----
README.rst | 6 ++++--
django_otp.egg-info/PKG-INFO | 10 ++++++----
django_otp/__init__.py | 16 +--------------
django_otp/middleware.py | 17 ++++++++++++++--
django_otp/models.py | 34 ++++++++++++++++++++------------
django_otp/plugins/otp_email/models.py | 3 ++-
django_otp/plugins/otp_email/tests.py | 2 +-
django_otp/plugins/otp_hotp/models.py | 3 ++-
django_otp/plugins/otp_static/tests.py | 6 +++---
django_otp/tests.py | 36 ++++++++++++++++++++++++++++++++++
docs/source/conf.py | 2 +-
docs/source/overview.rst | 2 +-
setup.py | 2 +-
15 files changed, 111 insertions(+), 48 deletions(-)
diff --git a/CHANGES b/CHANGES
index a0a1b43..bc491e9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,13 @@
+v0.4.1 - August 29, 2017 - Misc fixes
+-------------------------------------
+
+- Improved handling of device persistent identifiers.
+
+- Fix `#25`_: make sure default keys are unicode values.
+
+.. _#25: https://bitbucket.org/psagers/django-otp/issues/25/attributeerror-bytes-object-has-no
+
+
v0.4.0 - July 19, 2017 - Update support matrix
----------------------------------------------
diff --git a/PKG-INFO b/PKG-INFO
index 006144f..1e55e7d 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,14 +1,12 @@
Metadata-Version: 1.1
Name: django-otp
-Version: 0.4.0.1
+Version: 0.4.1.1
Summary: A pluggable framework for adding two-factor authentication to Django using one-time passwords.
Home-page: https://bitbucket.org/psagers/django-otp
Author: Peter Sagerson
Author-email: psagers at ignorare.net
License: BSD
-Description: `Package Documentation <http://django-otp-official.readthedocs.io/>`_
-
- This project makes it easy to add support for `one-time passwords
+Description: This project makes it easy to add support for `one-time passwords
<http://en.wikipedia.org/wiki/One-time_password>`_ (OTPs) to Django. It can be
integrated at various levels, depending on how much customization is required.
It integrates with ``django.contrib.auth``, although it is not a Django
@@ -22,6 +20,10 @@ Description: `Package Documentation <http://django-otp-official.readthedocs.io/>
<http://tools.ietf.org/html/rfc6238>`_ for convenience, as these are standard
OTP algorithms used by multiple plugins.
+ * Repository: https://bitbucket.org/psagers/django-otp
+ * Documentation: https://django-otp-official.readthedocs.io/
+ * Mailing list: https://groups.google.com/forum/#!forum/django-otp
+
This version is supported on Python 2.7 and 3.4+; and Django 1.8 and 1.10+.
.. _upgrade notes: https://pythonhosted.org/django-otp/overview.html#upgrading
diff --git a/README.rst b/README.rst
index 1883575..9c41ca3 100644
--- a/README.rst
+++ b/README.rst
@@ -1,5 +1,3 @@
-`Package Documentation <http://django-otp-official.readthedocs.io/>`_
-
This project makes it easy to add support for `one-time passwords
<http://en.wikipedia.org/wiki/One-time_password>`_ (OTPs) to Django. It can be
integrated at various levels, depending on how much customization is required.
@@ -14,6 +12,10 @@ separately. This package also includes an implementation of OATH `HOTP
<http://tools.ietf.org/html/rfc6238>`_ for convenience, as these are standard
OTP algorithms used by multiple plugins.
+* Repository: https://bitbucket.org/psagers/django-otp
+* Documentation: https://django-otp-official.readthedocs.io/
+* Mailing list: https://groups.google.com/forum/#!forum/django-otp
+
This version is supported on Python 2.7 and 3.4+; and Django 1.8 and 1.10+.
.. _upgrade notes: https://pythonhosted.org/django-otp/overview.html#upgrading
diff --git a/django_otp.egg-info/PKG-INFO b/django_otp.egg-info/PKG-INFO
index 006144f..1e55e7d 100644
--- a/django_otp.egg-info/PKG-INFO
+++ b/django_otp.egg-info/PKG-INFO
@@ -1,14 +1,12 @@
Metadata-Version: 1.1
Name: django-otp
-Version: 0.4.0.1
+Version: 0.4.1.1
Summary: A pluggable framework for adding two-factor authentication to Django using one-time passwords.
Home-page: https://bitbucket.org/psagers/django-otp
Author: Peter Sagerson
Author-email: psagers at ignorare.net
License: BSD
-Description: `Package Documentation <http://django-otp-official.readthedocs.io/>`_
-
- This project makes it easy to add support for `one-time passwords
+Description: This project makes it easy to add support for `one-time passwords
<http://en.wikipedia.org/wiki/One-time_password>`_ (OTPs) to Django. It can be
integrated at various levels, depending on how much customization is required.
It integrates with ``django.contrib.auth``, although it is not a Django
@@ -22,6 +20,10 @@ Description: `Package Documentation <http://django-otp-official.readthedocs.io/>
<http://tools.ietf.org/html/rfc6238>`_ for convenience, as these are standard
OTP algorithms used by multiple plugins.
+ * Repository: https://bitbucket.org/psagers/django-otp
+ * Documentation: https://django-otp-official.readthedocs.io/
+ * Mailing list: https://groups.google.com/forum/#!forum/django-otp
+
This version is supported on Python 2.7 and 3.4+; and Django 1.8 and 1.10+.
.. _upgrade notes: https://pythonhosted.org/django-otp/overview.html#upgrading
diff --git a/django_otp/__init__.py b/django_otp/__init__.py
index 7ba03d8..1808218 100644
--- a/django_otp/__init__.py
+++ b/django_otp/__init__.py
@@ -1,5 +1,3 @@
-import sys
-
import django
from django.contrib.auth.signals import user_logged_in
@@ -38,6 +36,7 @@ def _handle_auth_login(sender, request, user, **kwargs):
if hasattr(user, 'otp_device'):
login(request, user.otp_device)
+
user_logged_in.connect(_handle_auth_login)
@@ -137,19 +136,6 @@ def _device_classes_legacy():
yield model
-def import_class(path):
- """
- Imports a class based on a full Python path ('pkg.pkg.mod.Class'). This
- does not trap any exceptions if the path is not valid.
- """
- module, name = path.rsplit('.', 1)
- __import__(module)
- mod = sys.modules[module]
- cls = getattr(mod, name)
-
- return cls
-
-
def _user_is_authenticated(user):
"""
Wraps django's user.is_authenticated to support both Django 2 and pre-1.10.
diff --git a/django_otp/middleware.py b/django_otp/middleware.py
index 30609fd..294571a 100644
--- a/django_otp/middleware.py
+++ b/django_otp/middleware.py
@@ -43,8 +43,8 @@ class OTPMiddleware(MiddlewareMixin):
user.is_verified = functools.partial(is_verified, user)
if _user_is_authenticated(user):
- device_id = request.session.get(DEVICE_ID_SESSION_KEY)
- device = Device.from_persistent_id(device_id) if device_id else None
+ persistent_id = request.session.get(DEVICE_ID_SESSION_KEY)
+ device = self._device_from_persistent_id(persistent_id) if persistent_id else None
if (device is not None) and (device.user_id != user.id):
device = None
@@ -55,3 +55,16 @@ class OTPMiddleware(MiddlewareMixin):
user.otp_device = device
return user
+
+ def _device_from_persistent_id(self, persistent_id):
+ # Convert legacy persistent_id values (these used to be full import
+ # paths). This won't work for apps with models in sub-modules, but that
+ # should be pretty rare. And the worst that happens is the user has to
+ # log in again.
+ if persistent_id.count('.') > 1:
+ parts = persistent_id.split('.')
+ persistent_id = '.'.join((parts[-3], parts[-1]))
+
+ device = Device.from_persistent_id(persistent_id)
+
+ return device
diff --git a/django_otp/models.py b/django_otp/models.py
index 48fbddb..6751e3b 100644
--- a/django_otp/models.py
+++ b/django_otp/models.py
@@ -1,5 +1,6 @@
from __future__ import absolute_import, division, print_function, unicode_literals
+from django.apps import apps
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
@@ -92,28 +93,37 @@ class Device(models.Model):
@property
def persistent_id(self):
- return '{0}/{1}'.format(self.import_path, self.id)
+ return '{0}/{1}'.format(self.model_label(), self.id)
- @property
- def import_path(self):
- return '{0}.{1}'.format(self.__module__, self.__class__.__name__)
+ @classmethod
+ def model_label(cls):
+ """
+ Returns an identifier for this Django model class.
+
+ This is just the standard "<app_label>.<model_name>" form.
+
+ """
+ return '{0}.{1}'.format(cls._meta.app_label, cls._meta.model_name)
@classmethod
- def from_persistent_id(cls, path):
+ def from_persistent_id(cls, persistent_id):
"""
Loads a device from its persistent id::
device == Device.from_persistent_id(device.persistent_id)
+
"""
- from . import import_class
+ device = None
try:
- device_type, device_id = path.rsplit('/', 1)
-
- device_cls = import_class(device_type)
- device = device_cls.objects.get(id=device_id)
- except Exception:
- device = None
+ model_label, device_id = persistent_id.rsplit('/', 1)
+ app_label, model_name = model_label.split('.')
+
+ device_cls = apps.get_model(app_label, model_name)
+ if issubclass(device_cls, Device):
+ device = device_cls.objects.filter(id=int(device_id)).first()
+ except (ValueError, LookupError):
+ pass
return device
diff --git a/django_otp/plugins/otp_email/models.py b/django_otp/plugins/otp_email/models.py
index 4ef2a6f..afa0aa6 100644
--- a/django_otp/plugins/otp_email/models.py
+++ b/django_otp/plugins/otp_email/models.py
@@ -5,6 +5,7 @@ from binascii import unhexlify
from django.core.mail import send_mail
from django.db import models
from django.template.loader import render_to_string
+from django.utils.encoding import force_text
from django_otp.models import Device
from django_otp.oath import totp
@@ -14,7 +15,7 @@ from .conf import settings
def default_key():
- return random_hex(20)
+ return force_text(random_hex(20))
def key_validator(value):
diff --git a/django_otp/plugins/otp_email/tests.py b/django_otp/plugins/otp_email/tests.py
index eecb73e..7cb6b45 100644
--- a/django_otp/plugins/otp_email/tests.py
+++ b/django_otp/plugins/otp_email/tests.py
@@ -29,7 +29,7 @@ class AuthFormTest(TestCase):
data = {
'username': 'alice',
'password': 'password',
- 'otp_device': 'django_otp.plugins.otp_email.models.EmailDevice/1',
+ 'otp_device': 'otp_email.emaildevice/1',
'otp_token': '',
'otp_challenge': '1',
}
diff --git a/django_otp/plugins/otp_hotp/models.py b/django_otp/plugins/otp_hotp/models.py
index ff8b49e..3aa375a 100644
--- a/django_otp/plugins/otp_hotp/models.py
+++ b/django_otp/plugins/otp_hotp/models.py
@@ -5,6 +5,7 @@ from binascii import unhexlify
from django.conf import settings
from django.db import models
+from django.utils.encoding import force_text
from django.utils.six import string_types
from django.utils.six.moves.urllib.parse import quote, urlencode
@@ -14,7 +15,7 @@ from django_otp.util import random_hex, hex_validator
def default_key():
- return random_hex(20)
+ return force_text(random_hex(20))
def key_validator(value):
diff --git a/django_otp/plugins/otp_static/tests.py b/django_otp/plugins/otp_static/tests.py
index 9f20edb..4ff5cf8 100644
--- a/django_otp/plugins/otp_static/tests.py
+++ b/django_otp/plugins/otp_static/tests.py
@@ -127,7 +127,7 @@ class AuthFormTest(TestCase):
data = {
'username': 'alice',
'password': 'password',
- 'otp_device': 'django_otp.plugins.otp_static.models.StaticDevice/2',
+ 'otp_device': 'otp_static.staticdevice/2',
'otp_token': 'bob1',
}
form = OTPAuthenticationForm(None, data)
@@ -141,7 +141,7 @@ class AuthFormTest(TestCase):
data = {
'username': 'alice',
'password': 'password',
- 'otp_device': 'django_otp.plugins.otp_email.models.StaticDevice/1',
+ 'otp_device': 'otp_email.staticdevice/1',
'otp_token': 'bogus',
}
form = OTPAuthenticationForm(None, data)
@@ -155,7 +155,7 @@ class AuthFormTest(TestCase):
data = {
'username': 'alice',
'password': 'password',
- 'otp_device': 'django_otp.plugins.otp_static.models.StaticDevice/1',
+ 'otp_device': 'otp_static.staticdevice/1',
'otp_token': 'alice1',
}
form = OTPAuthenticationForm(None, data)
diff --git a/django_otp/tests.py b/django_otp/tests.py
index 0cdd515..61eaad4 100644
--- a/django_otp/tests.py
+++ b/django_otp/tests.py
@@ -84,6 +84,20 @@ class OTPMiddlewareTestCase(TestCase):
self.assertTrue(request.user.is_verified())
+ def test_verified_legacy_device_id(self):
+ request = self.factory.get('/')
+ request.user = self.alice
+ device = self.alice.staticdevice_set.get()
+ request.session = {
+ DEVICE_ID_SESSION_KEY: '{}.{}/{}'.format(
+ device.__module__, device.__class__.__name__, device.id
+ )
+ }
+
+ self.middleware.process_request(request)
+
+ self.assertTrue(request.user.is_verified())
+
def test_unverified(self):
request = self.factory.get('/')
request.user = self.alice
@@ -93,6 +107,28 @@ class OTPMiddlewareTestCase(TestCase):
self.assertFalse(request.user.is_verified())
+ def test_no_device(self):
+ request = self.factory.get('/')
+ request.user = self.alice
+ request.session = {
+ DEVICE_ID_SESSION_KEY: 'otp_static.staticdevice/0',
+ }
+
+ self.middleware.process_request(request)
+
+ self.assertFalse(request.user.is_verified())
+
+ def test_no_model(self):
+ request = self.factory.get('/')
+ request.user = self.alice
+ request.session = {
+ DEVICE_ID_SESSION_KEY: 'otp_bogus.bogusdevice/0',
+ }
+
+ self.middleware.process_request(request)
+
+ self.assertFalse(request.user.is_verified())
+
def test_wrong_user(self):
request = self.factory.get('/')
request.user = self.alice
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 73d0c10..5107de5 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -89,7 +89,7 @@ copyright = u'2012, Peter Sagerson'
# The short X.Y version.
version = '0.4'
# The full version, including alpha/beta/rc tags.
-release = '0.4.0'
+release = '0.4.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/source/overview.rst b/docs/source/overview.rst
index 96b26a0..de3b028 100644
--- a/docs/source/overview.rst
+++ b/docs/source/overview.rst
@@ -80,7 +80,7 @@ The recommended procedure is:
2. Upgrade Django to 1.7 or later.
3. Upgrade django-otp to the latest version.
-django-otp 0.4 will drop support for Django < 1.7.
+django-otp 0.4 dropped support for Django < 1.7.
Upgrading from 0.2.3 or Earlier
diff --git a/setup.py b/setup.py
index b1e41b2..5fccd0e 100755
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ from setuptools import setup, find_packages
setup(
name='django-otp',
- version='0.4.0.1',
+ version='0.4.1.1',
description='A pluggable framework for adding two-factor authentication to Django using one-time passwords.',
long_description=open('README.rst').read(),
author='Peter Sagerson',
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-django-otp.git
More information about the Python-modules-commits
mailing list