unusable passwords - support for all djangos
authorThierry Parmentelat <thierry.parmentelat@inria.fr>
Mon, 10 Feb 2014 14:28:02 +0000 (15:28 +0100)
committerThierry Parmentelat <thierry.parmentelat@inria.fr>
Mon, 10 Feb 2014 14:28:02 +0000 (15:28 +0100)
portal/django_passresetview.py
portal/forms.py

index 769e9f5..8e57199 100644 (file)
@@ -34,7 +34,7 @@ If the email address provided does not exist in the system, this view won't send
 This prevents information leaking to potential attackers. If you want to provide an error message in this case, you can subclass PasswordResetForm 
 and use the password_reset_form argument.
 
-Users flagged with an unusable password (see set_unusable_password() aren't allowed to request a password reset to prevent misuse when using an external 
+Users flagged with an unusable password - see set_unusable_password() - aren't allowed to request a password reset to prevent misuse when using an external 
 authentication source like LDAP. Note that they won't receive any error message since this would expose their account's existence but no mail will be sent either.
 
 More Detail: https://docs.djangoproject.com/en/dev/topics/auth/default/#topics-auth-creating-users
@@ -64,7 +64,7 @@ from django.contrib.auth.decorators import login_required
 from portal.forms import PasswordResetForm, SetPasswordForm
 from django.contrib.auth.tokens import default_token_generator
 from django.contrib.sites.models import get_current_site
-from django.contrib.auth.hashers import UNUSABLE_PASSWORD, identify_hasher
+from django.contrib.auth.hashers import identify_hasher
 
 ##
 import os.path, re
index afbf344..61ffb86 100644 (file)
@@ -28,15 +28,26 @@ from portal.models import PendingUser, PendingSlice
 from django.utils.translation import ugettext_lazy as _
 from django.contrib.auth.tokens import default_token_generator
 from django.contrib.auth import authenticate, get_user_model
-# TODO: Remove these automated forms and use html templates and views like any other page !
-# ERROR ImportError: cannot import name UNUSABLE_PASSWORD
-# XXX This is not compatible with Django 1.6.1
-# Ref: https://github.com/dot2code/varnish-bans-manager/issues/8
-from django.contrib.auth.hashers import UNUSABLE_PASSWORD, identify_hasher
 from django.contrib.sites.models import get_current_site
 from django.utils.http import int_to_base36
 from django.template import loader
 
+# TODO: Remove these automated forms and use html templates and views like any other page !
+from django.contrib.auth.hashers import identify_hasher
+# adapted from https://sourcegraph.com/github.com/fusionbox/django-authtools/symbols/python/authtools/forms
+
+def is_password_unusable(pw):
+    # like Django's is_password_usable, but only checks for unusable
+    # passwords, not invalidly encoded passwords too.
+    try:
+        # 1.5
+        from django.contrib.auth.hashers import UNUSABLE_PASSWORD
+        return pw == UNUSABLE_PASSWORD
+    except ImportError:
+        # 1.6
+        from django.contrib.auth.hashers import UNUSABLE_PASSWORD_PREFIX
+        return pw.startswith(UNUSABLE_PASSWORD_PREFIX)
+
 
 
 
@@ -146,8 +157,7 @@ class PasswordResetForm(forms.Form):
         if not any(user.is_active for user in self.users_cache):
             # none of the filtered users are active
             raise forms.ValidationError(self.error_messages['unknown'])
-        if any((user.password == UNUSABLE_PASSWORD)
-               for user in self.users_cache):
+        if any(is_password_unusable(user.password) for user in self.users_cache):
             raise forms.ValidationError(self.error_messages['unusable'])
         return email