diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py
index 75b3ca4ece..08488237c7 100644
--- a/django/contrib/auth/forms.py
+++ b/django/contrib/auth/forms.py
@@ -11,7 +11,7 @@ from django.utils.translation import ugettext, ugettext_lazy as _
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
-from django.contrib.auth.hashers import UNUSABLE_PASSWORD, is_password_usable, identify_hasher
+from django.contrib.auth.hashers import UNUSABLE_PASSWORD, identify_hasher
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.models import get_current_site
@@ -24,22 +24,22 @@ mask_password = lambda p: "%s%s" % (p[:UNMASKED_DIGITS_TO_SHOW], "*" * max(len(p
class ReadOnlyPasswordHashWidget(forms.Widget):
def render(self, name, value, attrs):
encoded = value
-
- if not is_password_usable(encoded):
- return "None"
-
final_attrs = self.build_attrs(attrs)
- try:
- hasher = identify_hasher(encoded)
- except ValueError:
- summary = mark_safe("Invalid password format or unknown hashing algorithm.")
+ if encoded == '' or encoded == UNUSABLE_PASSWORD:
+ summary = mark_safe("%s" % ugettext("No password set."))
else:
- summary = format_html_join('',
- "{0}: {1} ",
- ((ugettext(key), value)
- for key, value in hasher.safe_summary(encoded).items())
- )
+ try:
+ hasher = identify_hasher(encoded)
+ except ValueError:
+ summary = mark_safe("%s" % ugettext(
+ "Invalid password format or unknown hashing algorithm."))
+ else:
+ summary = format_html_join('',
+ "{0}: {1} ",
+ ((ugettext(key), value)
+ for key, value in hasher.safe_summary(encoded).items())
+ )
return format_html("
{1}
", flatatt(final_attrs), summary)
diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
index bd0c6778c9..c628059d34 100644
--- a/django/contrib/auth/hashers.py
+++ b/django/contrib/auth/hashers.py
@@ -28,7 +28,13 @@ def reset_hashers(**kwargs):
def is_password_usable(encoded):
- return (encoded is not None and encoded != UNUSABLE_PASSWORD)
+ if encoded is None or encoded == UNUSABLE_PASSWORD:
+ return False
+ try:
+ hasher = identify_hasher(encoded)
+ except ValueError:
+ return False
+ return True
def check_password(password, encoded, setter=None, preferred='default'):
diff --git a/django/contrib/auth/tests/forms.py b/django/contrib/auth/tests/forms.py
index 594b55c633..8fee3501c5 100644
--- a/django/contrib/auth/tests/forms.py
+++ b/django/contrib/auth/tests/forms.py
@@ -236,23 +236,30 @@ class UserChangeFormTest(TestCase):
# Just check we can create it
form = MyUserForm({})
+ def test_unsuable_password(self):
+ user = User.objects.get(username='empty_password')
+ user.set_unusable_password()
+ user.save()
+ form = UserChangeForm(instance=user)
+ self.assertIn(_("No password set."), form.as_table())
+
def test_bug_17944_empty_password(self):
user = User.objects.get(username='empty_password')
form = UserChangeForm(instance=user)
- # Just check that no error is raised.
- form.as_table()
+ self.assertIn(_("Invalid password format or unknown hashing algorithm."),
+ form.as_table())
def test_bug_17944_unmanageable_password(self):
user = User.objects.get(username='unmanageable_password')
form = UserChangeForm(instance=user)
- # Just check that no error is raised.
- form.as_table()
+ self.assertIn(_("Invalid password format or unknown hashing algorithm."),
+ form.as_table())
def test_bug_17944_unknown_password_algorithm(self):
user = User.objects.get(username='unknown_password')
form = UserChangeForm(instance=user)
- # Just check that no error is raised.
- form.as_table()
+ self.assertIn(_("Invalid password format or unknown hashing algorithm."),
+ form.as_table())
@override_settings(USE_TZ=False, PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
diff --git a/django/contrib/auth/tests/hashers.py b/django/contrib/auth/tests/hashers.py
index 673263b566..d867a57d98 100644
--- a/django/contrib/auth/tests/hashers.py
+++ b/django/contrib/auth/tests/hashers.py
@@ -100,6 +100,10 @@ class TestUtilsHashPass(unittest.TestCase):
self.assertRaises(ValueError, doit)
self.assertRaises(ValueError, identify_hasher, "lolcat$salt$hash")
+ def test_bad_encoded(self):
+ self.assertFalse(is_password_usable('letmein_badencoded'))
+ self.assertFalse(is_password_usable(''))
+
def test_low_level_pkbdf2(self):
hasher = PBKDF2PasswordHasher()
encoded = hasher.encode('letmein', 'seasalt')