summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES3
-rw-r--r--docs/conf.py5
-rw-r--r--docs/contents.rst7
-rw-r--r--docs/lib/passlib.ext.django.rst129
-rw-r--r--passlib/ext/django/__init__.py2
-rw-r--r--passlib/ext/django/models.py84
-rw-r--r--passlib/ext/django/utils.py55
7 files changed, 198 insertions, 87 deletions
diff --git a/CHANGES b/CHANGES
index e5fdf7b..93a7a74 100644
--- a/CHANGES
+++ b/CHANGES
@@ -67,6 +67,9 @@ Release History
* Builtin tests now use :mod:`!unittest2` if available.
* Setup script no longer requires distribute or setuptools.
+ * added (undocumented, experimental) Django app
+ for overriding Django's default hash format,
+ see ``docs/lib/passlib.ext.django.rst`` for more.
**1.4** (2011-05-04)
diff --git a/docs/conf.py b/docs/conf.py
index 4167e36..29239be 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -85,7 +85,10 @@ version = cloud_sptheme.get_version(release)
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = []
+exclude_patterns = [
+ #disabling documentation of this until module is more mature.
+ "lib/passlib.ext.django.rst"
+]
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
diff --git a/docs/contents.rst b/docs/contents.rst
index 436b578..058361c 100644
--- a/docs/contents.rst
+++ b/docs/contents.rst
@@ -21,7 +21,7 @@ Table Of Contents
lib/passlib.registry
lib/passlib.utils
-
+
modular_crypt_format
history
@@ -29,3 +29,8 @@ Table Of Contents
* :ref:`General Index <genindex>`
* :ref:`Module List <modindex>`
+
+..
+ unlisted:
+
+ lib/passlib.ext.django
diff --git a/docs/lib/passlib.ext.django.rst b/docs/lib/passlib.ext.django.rst
new file mode 100644
index 0000000..69e8970
--- /dev/null
+++ b/docs/lib/passlib.ext.django.rst
@@ -0,0 +1,129 @@
+.. index:: django; password hashing app
+
+==================================================
+:mod:`passlib.ext.django` - Django Password Helper
+==================================================
+
+.. module:: passlib.ext.django
+
+.. warning::
+
+ This module is currently under development.
+ It will probably work, but has not seen very much
+ testing or real-world use, and may change in future releases;
+ *caveat emptor*.
+
+.. todo::
+
+ This documentation needs to be cleaned up significantly
+ for new users.
+
+Overview
+========
+This module is intended for use with
+`Django <http://www.djangoproject.com>`_-based web applications.
+It contains a Django app which allows you to override
+Django's :doc:`default <passlib.hash.django_std>` password hash formats
+with any passlib :doc:`CryptContext <passlib.context>`.
+By default, it comes configured to add support for
+:class:`~passlib.hash.pbkdf2_sha256`, and will automatically
+upgrade all existing Django passwords as your users log in.
+
+Installation
+=============
+Installation is simple, just add ``passlib.ext.django`` to
+``settings.INSTALLED_APPS``. This module will handle
+everything else.
+
+Once done, when this app is imported by Django,
+it will automatically monkeypatch
+:class:`!django.contrib.auth.models.User`
+to use a Passlib CryptContext instance in place of normal Django
+password authentication. This provides hash migration,
+ability to set stronger policies for superuser & staff passwords,
+and stronger password hashing schemes.
+
+Configuration
+=============
+You can set the following options in django ``settings.py``:
+
+``PASSLIB_CONTEXT``
+ This may be one of a number of values:
+
+ * The string ``"passlib-default"``, which will cause Passlib
+ to replace Django's hash routines with a builtin policy
+ that supports all existing django hashes; but as users
+ log in, upgrades them all to :class:`~passlib.hash.pbkdf2_sha256`.
+ It also supports stronger hashing for the superuser account.
+
+ This is the default behavior if ``PASSLIB_CONTEXT`` is not set.
+
+ The exact default policy can be found at
+ :data:`passlib.ext.django.utils.DEFAULT_CTX`.
+
+ * ``None``, in which case this app will do nothing when django is loaded.
+
+ * A :class:`~passlib.context.CryptContext`
+ instance which will be used in place of the normal Django password
+ hash routines.
+
+ It is *strongly* recommended to use a context which will support
+ the existing Django hashes.
+
+ * A multiline config string suitable for passing to
+ :meth:`passlib.context.CryptPolicy.from_string`.
+ This will be parsed and used much like a :class:`!CryptContext` instance.
+
+``PASSLIB_GET_CATEGORY``
+
+ By default, Passlib will invoke the specified context with a category
+ string that's dependant on the User instance.
+ superusers will be assigned to the ``superuser`` category,
+ staff to the ``staff`` category, and all other accounts
+ assigned to ``None``.
+
+ This allows overriding that logic by specifying an alternate
+ function of the format ``get_category(user) -> category|None``.
+
+ .. seealso::
+
+ See :ref:`user-categories` for more details about
+ the category system in Passlib.
+
+Utility Functions
+=================
+.. module:: passlib.ext.django.utils
+
+Whether or not you install this application into Django,
+the following utility functions are available for overriding
+Django's password hashes:
+
+.. data:: DEFAULT_CTX
+
+ This is a string containing the default hashing policy
+ that will be used by this application if none is specified
+ via ``settings.PASSLIB_CONTEXT``.
+ It defaults to the following::
+
+ [passlib]
+ schemes =
+ pbkdf2_sha256,
+ django_salted_sha1, django_salted_md5,
+ django_des_crypt, hex_md5,
+ django_disabled
+
+ default = pbkdf2_sha256
+
+ deprecated =
+ django_salted_sha1, django_salted_md5,
+ django_des_crypt, hex_md5
+
+ all__vary_rounds = 5%%
+
+ pbkdf2_sha256__default_rounds = 4000
+ staff__pbkdf2_sha256__default_rounds = 8000
+ superuser__pbkdf2_sha256__default_rounds = 10000
+
+.. autofunction:: get_category
+
+.. autofunction:: set_django_password_context \ No newline at end of file
diff --git a/passlib/ext/django/__init__.py b/passlib/ext/django/__init__.py
index 1545e9c..b4fcb2c 100644
--- a/passlib/ext/django/__init__.py
+++ b/passlib/ext/django/__init__.py
@@ -6,5 +6,5 @@
and not officially documented in Passlib just yet
(though it should work).
-see ``models`` submodule for details on how this app works.
+see the Passlib documentation for details on how to use this app
"""
diff --git a/passlib/ext/django/models.py b/passlib/ext/django/models.py
index 02b54cc..aaf13ee 100644
--- a/passlib/ext/django/models.py
+++ b/passlib/ext/django/models.py
@@ -6,58 +6,7 @@
and not officially documented in Passlib just yet
(though it should work).
-When this is imported on Django load,
-it automatically monkeypatches
-:class:`django.contrib.auth.models.User`
-to use a Passlib CryptContext instance in place of normal Django
-password authentication. This provides hash migration,
-ability to set stronger policies for superuser & staff passwords,
-and stronger password hashing schemes.
-
-You can set the following options in django ``settings.py``:
-
-``PASSLIB_CONTEXT``
- This may be one of a number of values:
-
- * The string ``"passlib-default"``, which will cause Passlib
- to replace Django's hash routines with a builtin policy
- that supports all existing django hashes; but as users
- log in, upgrades them all to :class:`~passlib.hash.pbkdf2_sha256`.
- It also supports stronger hashing for the superuser account.
-
- This is the default behavior if ``PASSLIB_CONTEXT`` is not set.
-
- The exact policy can be found at
- :data:`passlib.ext.django.models.passlib_default_ctx`.
-
- * ``None``, in which case this app will do nothing when django is loaded.
-
- * A :class:`~passlib.context.CryptContext`
- instance which will be used in place of the normal Django password
- hash routines.
-
- It is *strongly* recommended to use a context which will support
- the existing Django hashes.
-
- * A multiline config string suitable for passing to
- :meth:`passlib.context.CryptPolicy.from_string`.
- This will be parsed and used much like a :class:`!CryptContext` instance.
-
-``PASSLIB_GET_CATEGORY``
-
- By default, Passlib will invoke the specified context with a category
- string that's dependant on the User instance.
- superusers will be assigned to the ``superuser`` category,
- staff to the ``staff`` category, and all other accounts
- assigned to ``None``.
-
- This allows overriding that logic by specifying an alternate
- function of the format ``get_category(user) -> category|None``.
-
- .. seealso::
-
- See :ref:`user-categories` for more details about
- the category system in Passlib.
+see the Passlib documentation for details on how to use this app
"""
#===================================================================
#imports
@@ -67,33 +16,8 @@ from django.conf import settings
#pkg
from passlib.context import CryptContext, CryptPolicy
from passlib.utils import is_crypt_context, bytes
-from passlib.ext.django.utils import get_category, set_django_password_context
-
-#===================================================================
-#constants
-#===================================================================
-
-#: default context used by app
-passlib_default_ctx = """
-[passlib]
-schemes =
- pbkdf2_sha256,
- django_salted_sha1, django_salted_md5,
- django_des_crypt, hex_md5,
- django_disabled
-
-default = pbkdf2_sha256
-
-deprecated =
- django_salted_sha1, django_salted_md5,
- django_des_crypt, hex_md5
-
-all__vary_rounds = 5%%
-
-pbkdf2_sha256__default_rounds = 4000
-staff__pbkdf2_sha256__default_rounds = 8000
-superuser__pbkdf2_sha256__default_rounds = 10000
-"""
+from passlib.ext.django.utils import DEFAULT_CTX, get_category, \
+ set_django_password_context
#===================================================================
#main
@@ -107,7 +31,7 @@ def patch():
if not ctx:
return
if ctx == "passlib-default":
- ctx = passlib_default_ctx
+ ctx = DEFAULT_CTX
if isinstance(ctx, (unicode, bytes)):
ctx = CryptPolicy.from_string(ctx)
if isinstance(ctx, CryptPolicy):
diff --git a/passlib/ext/django/utils.py b/passlib/ext/django/utils.py
index 9285f16..41d4196 100644
--- a/passlib/ext/django/utils.py
+++ b/passlib/ext/django/utils.py
@@ -10,7 +10,6 @@
#imports
#===================================================================
#site
-from django.contrib.auth.models import User
#pkg
from passlib.utils import is_crypt_context, bytes
#local
@@ -20,6 +19,45 @@ __all__ = [
]
#===================================================================
+#lazy import
+#===================================================================
+#NOTE: doing this lazily so sphinx can crawl module without
+# having django import problems.
+
+User = None #imported from django.contrib.auth.models
+
+def _lazy_import():
+ global User
+ if User is None:
+ from django.contrib.auth.models import User
+
+#===================================================================
+#constants
+#===================================================================
+
+#: default context used by app
+DEFAULT_CTX = """
+[passlib]
+schemes =
+ pbkdf2_sha256,
+ django_salted_sha1, django_salted_md5,
+ django_des_crypt, hex_md5,
+ django_disabled
+
+default = pbkdf2_sha256
+
+deprecated =
+ django_salted_sha1, django_salted_md5,
+ django_des_crypt, hex_md5
+
+all__vary_rounds = 5%%
+
+pbkdf2_sha256__default_rounds = 4000
+staff__pbkdf2_sha256__default_rounds = 8000
+superuser__pbkdf2_sha256__default_rounds = 10000
+"""
+
+#===================================================================
#monkeypatch framework
#===================================================================
@@ -31,7 +69,15 @@ __all__ = [
_django_patch_state = None
def get_category(user):
- "default get_category() implementation used by set_django_password_context"
+ """default get_category() implementation used by set_django_password_context
+
+ this is the function used if ``settings.PASSLIB_GET_CONTEXT`` is not
+ specified.
+
+ it maps superusers to the ``"superuser"`` category,
+ staff to the ``"staff"`` category,
+ and all others to the default category.
+ """
if user.is_superuser:
return "superuser"
if user.is_staff:
@@ -43,7 +89,7 @@ def um(func):
return func.im_func
def set_django_password_context(context=None, get_category=get_category):
- """monkeypatches django.contrib.auth to use specified password context
+ """monkeypatches :mod:`!django.contrib.auth` to use specified password context.
:arg context:
Passlib context to use for Django password hashing.
@@ -64,8 +110,9 @@ def set_django_password_context(context=None, get_category=get_category):
By default, uses a function which returns ``"superuser"``
for superusers, and ``"staff"`` for staff.
"""
- global _django_patch_state
+ global _django_patch_state, User
state = _django_patch_state
+ _lazy_import()
# issue warning if something else monkeypatched User
# while our patch was applied.