[Python-modules-commits] [python-django-otp] 02/13: importing python-django-otp_0.3.8.orig.tar.gz

Michael Fladischer fladi at moszumanska.debian.org
Wed Mar 1 08:40:43 UTC 2017


This is an automated email from the git hooks/post-receive script.

fladi pushed a commit to branch master
in repository python-django-otp.

commit 005ed8efc70304aec1ed83ead75ebe646e4528f2
Author: Michael Fladischer <FladischerMichael at fladi.at>
Date:   Sun Feb 26 16:40:31 2017 +0100

    importing python-django-otp_0.3.8.orig.tar.gz
---
 CHANGES                                            | 185 +++++++++++
 LICENSE                                            |  23 ++
 MANIFEST.in                                        |   7 +
 PKG-INFO                                           |  48 +++
 README.rst                                         |  25 ++
 django_otp.egg-info/PKG-INFO                       |  48 +++
 django_otp.egg-info/SOURCES.txt                    |  78 +++++
 django_otp.egg-info/dependency_links.txt           |   1 +
 django_otp.egg-info/not-zip-safe                   |   1 +
 django_otp.egg-info/requires.txt                   |   1 +
 django_otp.egg-info/top_level.txt                  |   1 +
 django_otp/__init__.py                             | 164 +++++++++
 django_otp/admin.py                                |  85 +++++
 django_otp/conf.py                                 |  27 ++
 django_otp/decorators.py                           |  27 ++
 django_otp/forms.py                                | 250 ++++++++++++++
 django_otp/middleware.py                           |  51 +++
 django_otp/models.py                               | 159 +++++++++
 django_otp/oath.py                                 | 205 ++++++++++++
 django_otp/plugins/__init__.py                     |   0
 django_otp/plugins/otp_email/__init__.py           |   0
 django_otp/plugins/otp_email/admin.py              |  29 ++
 django_otp/plugins/otp_email/conf.py               |  28 ++
 .../plugins/otp_email/migrations/0001_initial.py   |  30 ++
 .../plugins/otp_email/migrations/__init__.py       |   0
 django_otp/plugins/otp_email/models.py             |  66 ++++
 .../otp_email/south_migrations/0001_initial.py     |  74 +++++
 .../plugins/otp_email/south_migrations/__init__.py |   0
 .../otp_email/templates/otp/email/token.txt        |   1 +
 django_otp/plugins/otp_email/tests.py              |  44 +++
 django_otp/plugins/otp_hotp/__init__.py            |   0
 django_otp/plugins/otp_hotp/admin.py               |  33 ++
 .../plugins/otp_hotp/migrations/0001_initial.py    |  34 ++
 django_otp/plugins/otp_hotp/migrations/__init__.py |   0
 django_otp/plugins/otp_hotp/models.py              |  78 +++++
 .../otp_hotp/south_migrations/0001_initial.py      |  80 +++++
 .../plugins/otp_hotp/south_migrations/__init__.py  |   0
 django_otp/plugins/otp_hotp/tests.py               |  45 +++
 django_otp/plugins/otp_static/__init__.py          |   0
 django_otp/plugins/otp_static/admin.py             |  35 ++
 django_otp/plugins/otp_static/lib.py               |  29 ++
 .../plugins/otp_static/management/__init__.py      |   0
 .../otp_static/management/commands/__init__.py     |   0
 .../management/commands/addstatictoken.py          |  31 ++
 .../plugins/otp_static/migrations/0001_initial.py  |  39 +++
 .../plugins/otp_static/migrations/__init__.py      |   0
 django_otp/plugins/otp_static/models.py            |  58 ++++
 .../otp_static/south_migrations/0001_initial.py    | 100 ++++++
 .../otp_static/south_migrations/__init__.py        |   0
 django_otp/plugins/otp_static/tests.py             | 166 +++++++++
 django_otp/plugins/otp_totp/__init__.py            |   0
 django_otp/plugins/otp_totp/admin.py               |  33 ++
 .../plugins/otp_totp/migrations/0001_initial.py    |  37 +++
 django_otp/plugins/otp_totp/migrations/__init__.py |   0
 django_otp/plugins/otp_totp/models.py              | 108 ++++++
 .../otp_totp/south_migrations/0001_initial.py      |  91 +++++
 .../otp_totp/south_migrations/0002_last_t.py       |  82 +++++
 .../plugins/otp_totp/south_migrations/__init__.py  |   0
 django_otp/plugins/otp_totp/tests.py               |  77 +++++
 django_otp/templates/otp/.DS_Store                 | Bin 0 -> 6148 bytes
 django_otp/templates/otp/admin14/login.html        |  69 ++++
 django_otp/templates/otp/admin15/login.html        |  68 ++++
 django_otp/templates/otp/admin16/login.html        |  84 +++++
 django_otp/templates/otp/admin17/login.html        |  83 +++++
 django_otp/templates/otp/admin18/login.html        |  85 +++++
 django_otp/templates/otp/admin19/login.html        |  96 ++++++
 django_otp/tests.py                                |  57 ++++
 django_otp/util.py                                 |  62 ++++
 django_otp/views.py                                |  39 +++
 docs/Makefile                                      | 157 +++++++++
 docs/ext/otpdocs.py                                |  10 +
 docs/source/auth.rst                               | 181 ++++++++++
 docs/source/changes.rst                            |   4 +
 docs/source/conf.py                                | 267 +++++++++++++++
 docs/source/extend.rst                             |  86 +++++
 docs/source/index.rst                              |  40 +++
 docs/source/overview.rst                           | 370 +++++++++++++++++++++
 setup.cfg                                          |  11 +
 setup.py                                           |  36 ++
 79 files changed, 4619 insertions(+)

diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..de303ef
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,185 @@
+v0.3.8 - November 27, 2016 - Forward compatbility for Django 2.0
+----------------------------------------------------------------
+
+- Treat :attr:`~django.contrib.auth.models.User.is_authenticated` and
+  :attr:`~django.contrib.auth.models.User.is_anonymous` as properties in Django
+  1.10 and later.
+
+- Add explict on_delete behavior for all foreign keys.
+
+
+v0.3.7 - September 24, 2016 - Convenience API
+---------------------------------------------
+
+- Added a convenience API for verifying TOTP tokens:
+  :meth:`django_otp.oath.TOTP.verify`.
+
+
+v0.3.6 - September 4, 2016 - Django 1.10
+----------------------------------------
+
+- `#11`_: Don't break the laziness of ``request.user``.
+
+- `#16`_: Improved error message for invalid tokens.
+
+- `#17`_: Support the new middleware API in Django 1.10.
+
+.. _#11: https://bitbucket.org/psagers/django-otp/issues/11/wasteful-queries-on-every-request
+.. _#16: https://bitbucket.org/psagers/django-otp/issues/16/inappropriate-error-when-_verify_token
+.. _#17: https://bitbucket.org/psagers/django-otp/issues/17/django-110-new-style-middleware
+
+
+v0.3.5 - April 13, 2016 - Fix default TOTP key
+----------------------------------------------
+
+- The default (random) key for a new TOTP device is now forced to a unicode
+  string.
+
+
+v0.3.4 - January 10, 2016 - Python 3 cleanup
+--------------------------------------------
+
+- All modules include all four Python 3 __future__ imports for consistency.
+
+- Migrations no longer have byte strings in them.
+
+
+v0.3.3 - October 15, 2015 - Django 1.9
+--------------------------------------
+
+- Fix the addstatictoken management command under Django 1.9.
+
+
+v0.3.2 - October 11, 2015 - Django 1.8
+--------------------------------------
+
+- Stop importing models into the root of the package.
+
+- Use ModelAdmin.raw_id_fields for foreign keys to users.
+
+- General cleanup and compatibility with Django 1.9a1.
+
+
+v0.3.1 - April 3, 2015 - Django 1.8
+-----------------------------------
+
+- Add support for the new app registry, when available.
+
+- Add Django 1.8 to the test matrix and fix a few test bugs.
+
+
+v0.3.0 - February 7, 2015 - Support Django migrations
+-----------------------------------------------------
+
+- All plugins now have both Django and South migrations. Please see the `upgrade
+  notes`_ for details on upgrading from previous versions.
+
+.. _upgrade notes: https://pythonhosted.org/django-otp/overview.html#upgrading
+
+
+v0.2.7 - April 26, 2014 - Fix for Custom user models with South
+---------------------------------------------------------------
+
+- Updated the otp_totp South migrations to support custom user models. Thanks to
+  https://bitbucket.org/robirichter.
+
+
+v0.2.6 - April 18, 2014 - Fix for Python 3.2 with South
+-------------------------------------------------------
+
+- Removed South-generated unicode string literals.
+
+
+v0.2.4 - April 15, 2014 - TOTP plugin fix (migration warning)
+-------------------------------------------------------------
+
+- Per the RFC, :class:`~django_otp.plugins.otp_totp.models.TOTPDevice` will no
+  longer verify the same token twice.
+
+- Cosmetic fixes to the admin login form on Django 1.6.
+
+.. warning::
+
+    This includes a model change in TOTPDevice. If you are upgrading and your
+    project uses South, you should first convert it to South with ``manage
+    migrate otp_totp 0001 --fake``. If you're not using South, you will need to
+    generate and run the appropriate SQL manually.
+
+
+v0.2.3 - March 3, 2014 - Fix pickling
+-------------------------------------
+
+- OTPMiddleware no longer interferes with pickling request.user.
+
+
+v0.2.2 - December 31, 2013 - Require Django 1.4.2
+-------------------------------------------------
+
+- Update Django requirement to 1.4.2, the first version with django.utils.six.
+
+
+v0.2.1 - November 19, 2013 - Bug fix
+------------------------------------
+
+- Fix unicode representation of devices in some exotic scenarios.
+
+
+v0.2.0 - November 10, 2013 - Django 1.6
+---------------------------------------
+
+- Now supports Django 1.4 to 1.6 on Python 2.6, 2.7, 3.2, and 3.3. This is the
+  first release for Python 3.
+
+
+v0.1.8 - August 20, 2013 - user_has_device API
+-----------------------------------------------
+
+- Add :func:`django_otp.user_has_device` to detect whether a user has any
+  devices configured. This change supports a fix in django-otp-agents 0.1.4.
+
+
+v0.1.7 - July 3, 2013 - Decorator improvement
+-----------------------------------------------
+
+- Add if_configured argument to :func:`~django_otp.decorators.otp_required`.
+
+
+v0.1.6 - May 9, 2013 - Unit test improvements
+---------------------------------------------
+
+- Major unit test cleanup. Tests should pass or be skipped under all supported
+  versions of Django, with or without custom users and timzeone support.
+
+
+v0.1.5 - May 8, 2013 - OTPAdminSite improvement
+-----------------------------------------------
+
+- OTPAdminSite now selects an apporpriate login template automatically, based on
+  the current Django version. Django versions 1.3 to 1.5 are currently
+  supported.
+
+- Unit test cleanup.
+
+
+v0.1.3 - March 10, 2013 - Django 1.5 compatibility
+--------------------------------------------------
+
+- Add support for custom user models in Django 1.5.
+
+- Stop using ``Device.objects``: Django doesn't allow access to an abstract
+  model's manager any more.
+
+
+v0.1.2 - October 8, 2012 - Bug fix
+----------------------------------
+
+- Fix an exception when an empty login form is submitted.
+
+
+v0.1.0 - August 20, 2012 - Initial Release
+------------------------------------------
+
+Initial release.
+
+
+.. vim: ft=rst nospell tw=80
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..be76807
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2012, Peter Sagerson
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..3caa31a
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,7 @@
+include README.rst CHANGES LICENSE
+
+recursive-include docs *.rst *.py Makefile
+prune docs/build
+
+recursive-include django_otp/plugins/otp_email/templates *
+recursive-include django_otp/templates *
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..c4e393f
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,48 @@
+Metadata-Version: 1.1
+Name: django-otp
+Version: 0.3.8
+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: psagersDjwublJf at ignorare.net
+License: BSD
+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
+        authentication backend. The primary target is developers wishing to incorporate
+        OTPs into their Django projects as a form of `two-factor authentication
+        <http://en.wikipedia.org/wiki/Two-factor_authentication>`_.
+        
+        This project includes several simple OTP plugins and more are available
+        separately. This package also includes an implementation of OATH `HOTP
+        <http://tools.ietf.org/html/rfc4226>`_ and `TOTP
+        <http://tools.ietf.org/html/rfc6238>`_ for convenience, as these are standard
+        OTP algorithms used by multiple plugins.
+        
+        This version is supported on Python 2.6, 2.7, and 3.3+; and Django >= 1.4.2.
+        
+        .. warning::
+        
+            All plugins now contain both South and Django migrations. If you're using
+            South or upgrading to Django 1.7, please see the `upgrade notes`_ in the
+            documentation first.
+        
+        .. _upgrade notes: https://pythonhosted.org/django-otp/overview.html#upgrading
+        
+        .. vim:ft=rst
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Framework :: Django
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Topic :: Security
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..bceb8bc
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,25 @@
+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
+authentication backend. The primary target is developers wishing to incorporate
+OTPs into their Django projects as a form of `two-factor authentication
+<http://en.wikipedia.org/wiki/Two-factor_authentication>`_.
+
+This project includes several simple OTP plugins and more are available
+separately. This package also includes an implementation of OATH `HOTP
+<http://tools.ietf.org/html/rfc4226>`_ and `TOTP
+<http://tools.ietf.org/html/rfc6238>`_ for convenience, as these are standard
+OTP algorithms used by multiple plugins.
+
+This version is supported on Python 2.6, 2.7, and 3.3+; and Django >= 1.4.2.
+
+.. warning::
+
+    All plugins now contain both South and Django migrations. If you're using
+    South or upgrading to Django 1.7, please see the `upgrade notes`_ in the
+    documentation first.
+
+.. _upgrade notes: https://pythonhosted.org/django-otp/overview.html#upgrading
+
+.. vim:ft=rst
diff --git a/django_otp.egg-info/PKG-INFO b/django_otp.egg-info/PKG-INFO
new file mode 100644
index 0000000..c4e393f
--- /dev/null
+++ b/django_otp.egg-info/PKG-INFO
@@ -0,0 +1,48 @@
+Metadata-Version: 1.1
+Name: django-otp
+Version: 0.3.8
+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: psagersDjwublJf at ignorare.net
+License: BSD
+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
+        authentication backend. The primary target is developers wishing to incorporate
+        OTPs into their Django projects as a form of `two-factor authentication
+        <http://en.wikipedia.org/wiki/Two-factor_authentication>`_.
+        
+        This project includes several simple OTP plugins and more are available
+        separately. This package also includes an implementation of OATH `HOTP
+        <http://tools.ietf.org/html/rfc4226>`_ and `TOTP
+        <http://tools.ietf.org/html/rfc6238>`_ for convenience, as these are standard
+        OTP algorithms used by multiple plugins.
+        
+        This version is supported on Python 2.6, 2.7, and 3.3+; and Django >= 1.4.2.
+        
+        .. warning::
+        
+            All plugins now contain both South and Django migrations. If you're using
+            South or upgrading to Django 1.7, please see the `upgrade notes`_ in the
+            documentation first.
+        
+        .. _upgrade notes: https://pythonhosted.org/django-otp/overview.html#upgrading
+        
+        .. vim:ft=rst
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Framework :: Django
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Topic :: Security
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff --git a/django_otp.egg-info/SOURCES.txt b/django_otp.egg-info/SOURCES.txt
new file mode 100644
index 0000000..c20a3ba
--- /dev/null
+++ b/django_otp.egg-info/SOURCES.txt
@@ -0,0 +1,78 @@
+CHANGES
+LICENSE
+MANIFEST.in
+README.rst
+setup.cfg
+setup.py
+django_otp/__init__.py
+django_otp/admin.py
+django_otp/conf.py
+django_otp/decorators.py
+django_otp/forms.py
+django_otp/middleware.py
+django_otp/models.py
+django_otp/oath.py
+django_otp/tests.py
+django_otp/util.py
+django_otp/views.py
+django_otp.egg-info/PKG-INFO
+django_otp.egg-info/SOURCES.txt
+django_otp.egg-info/dependency_links.txt
+django_otp.egg-info/not-zip-safe
+django_otp.egg-info/requires.txt
+django_otp.egg-info/top_level.txt
+django_otp/plugins/__init__.py
+django_otp/plugins/otp_email/__init__.py
+django_otp/plugins/otp_email/admin.py
+django_otp/plugins/otp_email/conf.py
+django_otp/plugins/otp_email/models.py
+django_otp/plugins/otp_email/tests.py
+django_otp/plugins/otp_email/migrations/0001_initial.py
+django_otp/plugins/otp_email/migrations/__init__.py
+django_otp/plugins/otp_email/south_migrations/0001_initial.py
+django_otp/plugins/otp_email/south_migrations/__init__.py
+django_otp/plugins/otp_email/templates/otp/email/token.txt
+django_otp/plugins/otp_hotp/__init__.py
+django_otp/plugins/otp_hotp/admin.py
+django_otp/plugins/otp_hotp/models.py
+django_otp/plugins/otp_hotp/tests.py
+django_otp/plugins/otp_hotp/migrations/0001_initial.py
+django_otp/plugins/otp_hotp/migrations/__init__.py
+django_otp/plugins/otp_hotp/south_migrations/0001_initial.py
+django_otp/plugins/otp_hotp/south_migrations/__init__.py
+django_otp/plugins/otp_static/__init__.py
+django_otp/plugins/otp_static/admin.py
+django_otp/plugins/otp_static/lib.py
+django_otp/plugins/otp_static/models.py
+django_otp/plugins/otp_static/tests.py
+django_otp/plugins/otp_static/management/__init__.py
+django_otp/plugins/otp_static/management/commands/__init__.py
+django_otp/plugins/otp_static/management/commands/addstatictoken.py
+django_otp/plugins/otp_static/migrations/0001_initial.py
+django_otp/plugins/otp_static/migrations/__init__.py
+django_otp/plugins/otp_static/south_migrations/0001_initial.py
+django_otp/plugins/otp_static/south_migrations/__init__.py
+django_otp/plugins/otp_totp/__init__.py
+django_otp/plugins/otp_totp/admin.py
+django_otp/plugins/otp_totp/models.py
+django_otp/plugins/otp_totp/tests.py
+django_otp/plugins/otp_totp/migrations/0001_initial.py
+django_otp/plugins/otp_totp/migrations/__init__.py
+django_otp/plugins/otp_totp/south_migrations/0001_initial.py
+django_otp/plugins/otp_totp/south_migrations/0002_last_t.py
+django_otp/plugins/otp_totp/south_migrations/__init__.py
+django_otp/templates/otp/.DS_Store
+django_otp/templates/otp/admin14/login.html
+django_otp/templates/otp/admin15/login.html
+django_otp/templates/otp/admin16/login.html
+django_otp/templates/otp/admin17/login.html
+django_otp/templates/otp/admin18/login.html
+django_otp/templates/otp/admin19/login.html
+docs/Makefile
+docs/ext/otpdocs.py
+docs/source/auth.rst
+docs/source/changes.rst
+docs/source/conf.py
+docs/source/extend.rst
+docs/source/index.rst
+docs/source/overview.rst
\ No newline at end of file
diff --git a/django_otp.egg-info/dependency_links.txt b/django_otp.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/django_otp.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/django_otp.egg-info/not-zip-safe b/django_otp.egg-info/not-zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/django_otp.egg-info/not-zip-safe
@@ -0,0 +1 @@
+
diff --git a/django_otp.egg-info/requires.txt b/django_otp.egg-info/requires.txt
new file mode 100644
index 0000000..5137bb2
--- /dev/null
+++ b/django_otp.egg-info/requires.txt
@@ -0,0 +1 @@
+django >= 1.4.2
diff --git a/django_otp.egg-info/top_level.txt b/django_otp.egg-info/top_level.txt
new file mode 100644
index 0000000..54bbdb1
--- /dev/null
+++ b/django_otp.egg-info/top_level.txt
@@ -0,0 +1 @@
+django_otp
diff --git a/django_otp/__init__.py b/django_otp/__init__.py
new file mode 100644
index 0000000..7ba03d8
--- /dev/null
+++ b/django_otp/__init__.py
@@ -0,0 +1,164 @@
+import sys
+
+import django
+from django.contrib.auth.signals import user_logged_in
+
+
+DEVICE_ID_SESSION_KEY = 'otp_device_id'
+
+
+def login(request, device):
+    """
+    Persist the given OTP device in the current session. The device will be
+    rejected if it does not belong to ``request.user``.
+
+    This is called automatically any time :func:`django.contrib.auth.login` is
+    called with a user having an ``otp_device`` atribute. If you use Django's
+    :func:`~django.contrib.auth.views.login` view with the django-otp
+    authentication forms, then you won't need to call this.
+
+    :param request: The HTTP request
+    :type request: :class:`~django.http.HttpRequest`
+
+    :param device: The OTP device used to verify the user.
+    :type device: :class:`~django_otp.models.Device`
+    """
+    user = getattr(request, 'user', None)
+
+    if (user is not None) and (device is not None) and (device.user_id == user.id):
+        request.session[DEVICE_ID_SESSION_KEY] = device.persistent_id
+        request.user.otp_device = device
+
+
+def _handle_auth_login(sender, request, user, **kwargs):
+    """
+    Automatically persists an OTP device that was set by an OTP-aware
+    AuthenticationForm.
+    """
+    if hasattr(user, 'otp_device'):
+        login(request, user.otp_device)
+
+user_logged_in.connect(_handle_auth_login)
+
+
+def match_token(user, token):
+    """
+    Attempts to verify a :term:`token` on every device attached to the given
+    user until one of them succeeds. When possible, you should prefer to verify
+    tokens against specific devices.
+
+    :param user: The user supplying the token.
+    :type user: :class:`~django.contrib.auth.models.User`
+
+    :param string token: An OTP token to verify.
+
+    :returns: The device that accepted ``token``, if any.
+    :rtype: :class:`~django_otp.models.Device` or ``None``
+    """
+    matches = (d for d in devices_for_user(user) if d.verify_token(token))
+
+    return next(matches, None)
+
+
+def devices_for_user(user, confirmed=True):
+    """
+    Return an iterable of all devices registered to the given user.
+
+    Returns an empty iterable for anonymous users.
+
+    :param user: standard or custom user object.
+    :type user: :class:`~django.contrib.auth.models.User`
+
+    :param confirmed: If ``None``, all matching devices are returned.
+        Otherwise, this can be any true or false value to limit the query
+        to confirmed or unconfirmed devices, respectively.
+
+    :rtype: iterable
+    """
+    if _user_is_anonymous(user):
+        return
+
+    for model in device_classes():
+        for device in model.objects.devices_for_user(user, confirmed=confirmed):
+            yield device
+
+
+def user_has_device(user, confirmed=True):
+    """
+    Return ``True`` if the user has at least one device.
+
+    Returns ``False`` for anonymous users.
+
+    :param user: standard or custom user object.
+    :type user: :class:`~django.contrib.auth.models.User`
+
+    :param confirmed: If ``None``, all matching devices are considered.
+        Otherwise, this can be any true or false value to limit the query
+        to confirmed or unconfirmed devices, respectively.
+    """
+    try:
+        next(devices_for_user(user, confirmed=confirmed))
+    except StopIteration:
+        has_device = False
+    else:
+        has_device = True
+
+    return has_device
+
+
+def device_classes():
+    """
+    Returns an iterable of all loaded device models.
+    """
+    from django_otp.models import Device
+
+    try:
+        from django.apps import apps
+    except ImportError:
+        for model in _device_classes_legacy():
+            yield model
+    else:
+        for config in apps.get_app_configs():
+            for model in config.get_models():
+                if issubclass(model, Device):
+                    yield model
+
+
+def _device_classes_legacy():
+    """
+    Find device models in Django < 1.7.
+    """
+    from django.db.models import get_apps, get_models
+    from django_otp.models import Device
+
+    for app in get_apps():
+        for model in get_models(app):
+            if issubclass(model, Device):
+                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.
+    """
+    return user.is_authenticated if (django.VERSION >= (1, 10)) else user.is_authenticated()
+
+
+def _user_is_anonymous(user):
+    """
+    Wraps django's user.is_anonymous to support both Django 2 and pre-1.10.
+    """
+    return user.is_anonymous if (django.VERSION >= (1, 10)) else user.is_anonymous()
diff --git a/django_otp/admin.py b/django_otp/admin.py
new file mode 100644
index 0000000..a716aca
--- /dev/null
+++ b/django_otp/admin.py
@@ -0,0 +1,85 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import django
+from django import forms
+from django.contrib.admin.forms import AdminAuthenticationForm
+from django.contrib.admin.sites import AdminSite
+
+from .forms import OTPAuthenticationFormMixin
+
+
+def _admin_template_for_django_version():
+    minor_django_version = django.VERSION[:2]
+
+    if minor_django_version <= (1, 4):
+        return 'otp/admin14/login.html'
+    elif minor_django_version == (1, 5):
+        return 'otp/admin15/login.html'
+    elif minor_django_version == (1, 6):
+        return 'otp/admin16/login.html'
+    elif minor_django_version == (1, 7):
+        return 'otp/admin17/login.html'
+    elif minor_django_version == (1, 8):
+        return 'otp/admin18/login.html'
+    else:
+        return 'otp/admin19/login.html'
+
+
+class OTPAdminAuthenticationForm(AdminAuthenticationForm, OTPAuthenticationFormMixin):
+    """
+    An :class:`~django.contrib.admin.forms.AdminAuthenticationForm` subclass
+    that solicits an OTP token. This has the same behavior as
+    :class:`~django_otp.forms.OTPAuthenticationForm`.
+    """
+    otp_device = forms.CharField(required=False, widget=forms.Select)
+    otp_token = forms.CharField(required=False)
+
+    # This is a placeholder field that allows us to detect when the user clicks
+    # the otp_challenge submit button.
+    otp_challenge = forms.CharField(required=False)
+
+    def __init__(self, *args, **kwargs):
+        super(OTPAdminAuthenticationForm, self).__init__(*args, **kwargs)
+
+        # A litle extra cheese to make it prettier.
+        minor_django_version = django.VERSION[:2]
+
+        if minor_django_version < (1, 6):
+            self.fields['otp_token'].widget.attrs['style'] = 'width: 14em;'
+
+    def clean(self):
+        self.cleaned_data = super(OTPAdminAuthenticationForm, self).clean()
+        self.clean_otp(self.get_user())
+
+        return self.cleaned_data
+
+
+class OTPAdminSite(AdminSite):
+    """
+    This is an :class:`~django.contrib.admin.AdminSite` subclass that requires
+    two-factor authentication. Only users that can be verified by a registered
+    OTP device will be authorized for this admin site. Unverified users will be
+    treated as if :attr:`~django.contrib.auth.models.User.is_staff` is
+    ``False``.
+    """
+    #: The default instance name of this admin site. You should instantiate
+    #: this class as ``OTPAdminSite(OTPAdminSite.name)`` to make sure the admin
+    #: templates render the correct URLs.
+    name = 'otpadmin'
+
+    login_form = OTPAdminAuthenticationForm
+
+    #: We automatically select a modified login template based on your Django
+    #: version. If it doesn't look right, your version may not be supported, in
+    #: which case feel free to replace it.
+    login_template = _admin_template_for_django_version()
+
+    def __init__(self, name='otpadmin'):
+        super(OTPAdminSite, self).__init__(name)
+
+    def has_permission(self, request):
+        """
+        In addition to the default requirements, this only allows access to
+        users who have been verified by a registered OTP device.
+        """
+        return super(OTPAdminSite, self).has_permission(request) and request.user.is_verified()
diff --git a/django_otp/conf.py b/django_otp/conf.py
new file mode 100644
index 0000000..129385b
--- /dev/null
+++ b/django_otp/conf.py
@@ -0,0 +1,27 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import django.conf
+from django.utils.six import iteritems
+
+
+class Settings(object):
+    """
+    This is a simple class to take the place of the global settings object. An
+    instance will contain all of our settings as attributes, with default values
+    if they are not specified by the configuration.
+    """
+    defaults = {
+        'OTP_LOGIN_URL': django.conf.settings.LOGIN_URL,
+    }
+
+    def __init__(self):
+        """
+        Loads our settings from django.conf.settings, applying defaults for any
+        that are omitted.
+        """
+        for name, default in iteritems(self.defaults):
+            value = getattr(django.conf.settings, name, default)
+            setattr(self, name, value)
+
+
+settings = Settings()
diff --git a/django_otp/decorators.py b/django_otp/decorators.py
new file mode 100644
index 0000000..d4e1e32
--- /dev/null
+++ b/django_otp/decorators.py
@@ -0,0 +1,27 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from django.contrib.auth.decorators import user_passes_test
+
+from django_otp import user_has_device, _user_is_authenticated
+from django_otp.conf import settings
+
+
+def otp_required(view=None, redirect_field_name='next', login_url=None, if_configured=False):
+    """
+    Similar to :func:`~django.contrib.auth.decorators.login_required`, but
+    requires the user to be :term:`verified`. By default, this redirects users
+    to :setting:`OTP_LOGIN_URL`.
+
+    :param if_configured: If ``True``, an authenticated user with no confirmed
+        OTP devices will be allowed. Default is ``False``.
+    :type if_configured: bool
+    """
+    if login_url is None:
+        login_url = settings.OTP_LOGIN_URL
+
+    def test(user):
+        return user.is_verified() or (if_configured and _user_is_authenticated(user) and not user_has_device(user))
+
+    decorator = user_passes_test(test, login_url=login_url, redirect_field_name=redirect_field_name)
+
+    return decorator if (view is None) else decorator(view)
diff --git a/django_otp/forms.py b/django_otp/forms.py
new file mode 100644
index 0000000..dc71f50
--- /dev/null
+++ b/django_otp/forms.py
@@ -0,0 +1,250 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from django import forms
+from django.utils.translation import ugettext_lazy as _
+from django.contrib.auth.forms import AuthenticationForm
+
+from . import match_token, devices_for_user
+from .models import Device
+
+
+class OTPAuthenticationFormMixin(object):
+    """
+    Shared functionality for
+    :class:`~django.contrib.auth.forms.AuthenticationForm` subclasses that wish
+    to handle OTP tokens. Subclasses must do the following in order to use
+    this:
+
+        #. Define three additional form fields::
+
+            otp_device = forms.CharField(required=False, widget=forms.Select)
+            otp_token = forms.CharField(required=False)
+            otp_challenge = forms.CharField(required=False)
+
+           - ``otp_device`` will be a select widget with all of the user's
+             devices listed. Until the user has entered a valid username and
+             password, this will be empty and may be omitted.
+           - ``otp_token`` is where the user will enter their token.
+           - ``otp_challenge`` is a placeholder field that captures an
+             alternate submit button of the same name.
+
+        #. Override :meth:`~django.forms.Form.clean` to call :meth:`clean_otp`
+           after invoking the inherited :meth:`~django.forms.Form.clean`. See
+           :class:`OTPAuthenticationForm` for an example.
+
+        #. See :class:`OTPAuthenticationForm` for information about writing a
+           login template for this form. The file
+           ``django_otp/templates/otp/admin/login.html`` is also a useful
+           example.
+
+    You will most likely be able to use :class:`OTPAuthenticationForm`,
+    :class:`django_otp.admin.OTPAdminAuthenticationForm`, or
+    :class:`OTPTokenForm` directly. If these do not suit your needs--for
+    instance if your primary authentication is not by password--they should
+    serve as useful examples.
+    """
+    def clean_otp(self, user):
+        """
+        Processes the ``otp_*`` fields.
+
+        :param user: A user that has been authenticated by the first factor
+            (such as a password).
+        :type user: :class:`~django.contrib.auth.models.User`
+        :rasies: :exc:`~django.core.exceptions.ValidationError` if the user is
+            not fully authenticated by an OTP token.
+        """
+        if user is None:
+            return
+
+        device = self._chosen_device(user)
+        token = self.cleaned_data.get('otp_token')
+
+        user.otp_device = None
+
+        try:
+            if self.cleaned_data.get('otp_challenge'):
+                self._handle_challenge(device)
+            elif token:
+                user.otp_device = self._verify_token(user, token, device)
+            else:
+                raise forms.ValidationError(_('Please enter your OTP token.'), code='required')
+        finally:
+            if user.otp_device is None:
+                self._update_form(user)
+
+    def _chosen_device(self, user):
+        device_id = self.cleaned_data.get('otp_device')
+
+        if device_id:
+            device = Device.from_persistent_id(device_id)
+        else:
+            device = None
+
+        # SECURITY: The form doesn't validate otp_device for us, since we don't
+        # have the list of choices until we authenticate the user. Without the
+        # following, an attacker could authenticate using some other user's OTP
+        # device.
+        if (device is not None) and (device.user_id != user.id):
+            device = None
+
+        return device
+
+    def _handle_challenge(self, device):
+        try:
+            challenge = device.generate_challenge() if (device is not None) else None
+        except Exception as e:
... 4136 lines suppressed ...

-- 
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