Permalink
Browse files

Fixed #17194 -- Made sure the auth form tests work if a language othe…

…r than English is activated by moving the error message translation strings into class level dictionaries. Many thanks to Claude Paroz, rabio and Bas Peschier for their initial work on this.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17204 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent e7b5e22 commit 5df31c0164e9477a3ebb6b1bbde8604e06fbefd4 @jezdez jezdez committed Dec 15, 2011
Showing with 123 additions and 83 deletions.
  1. +46 −12 django/contrib/auth/forms.py
  2. +34 −26 django/contrib/auth/tests/forms.py
  3. +43 −45 django/contrib/auth/tests/views.py
@@ -15,6 +15,7 @@
mask_password = lambda p: "%s%s" % (p[:UNMASKED_DIGITS_TO_SHOW], "*" * max(len(p) - UNMASKED_DIGITS_TO_SHOW, 0))
+
class ReadOnlyPasswordHashWidget(forms.Widget):
def render(self, name, value, attrs):
if not value:
@@ -39,17 +40,23 @@ def render(self, name, value, attrs):
"masked": masked,
})
+
class ReadOnlyPasswordHashField(forms.Field):
widget = ReadOnlyPasswordHashWidget
def __init__(self, *args, **kwargs):
kwargs.setdefault("required", False)
super(ReadOnlyPasswordHashField, self).__init__(*args, **kwargs)
+
class UserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username and password.
"""
+ error_messages = {
+ 'duplicate_username': _("A user with that username already exists."),
+ 'password_mismatch': _("The two password fields didn't match."),
+ }
username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^[\w.@+-]+$',
help_text = _("Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only."),
error_messages = {'invalid': _("This value may contain only letters, numbers and @/./+/-/_ characters.")})
@@ -67,13 +74,13 @@ def clean_username(self):
User.objects.get(username=username)
except User.DoesNotExist:
return username
- raise forms.ValidationError(_("A user with that username already exists."))
+ raise forms.ValidationError(self.error_messages['duplicate_username'])
def clean_password2(self):
password1 = self.cleaned_data.get("password1", "")
password2 = self.cleaned_data["password2"]
if password1 != password2:
- raise forms.ValidationError(_("The two password fields didn't match."))
+ raise forms.ValidationError(self.error_messages['password_mismatch'])
return password2
def save(self, commit=True):
@@ -83,6 +90,7 @@ def save(self, commit=True):
user.save()
return user
+
class UserChangeForm(forms.ModelForm):
username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^[\w.@+-]+$',
help_text = _("Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only."),
@@ -101,6 +109,7 @@ def __init__(self, *args, **kwargs):
if f is not None:
f.queryset = f.queryset.select_related('content_type')
+
class AuthenticationForm(forms.Form):
"""
Base class for authenticating users. Extend this to get a form that accepts
@@ -109,6 +118,14 @@ class AuthenticationForm(forms.Form):
username = forms.CharField(label=_("Username"), max_length=30)
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
+ error_messages = {
+ 'invalid_login': _("Please enter a correct username and password. "
+ "Note that both fields are case-sensitive."),
+ 'no_cookies': _("Your Web browser doesn't appear to have cookies "
+ "enabled. Cookies are required for logging in."),
+ 'inactive': _("This account is inactive."),
+ }
+
def __init__(self, request=None, *args, **kwargs):
"""
If request is passed in, the form will validate that cookies are
@@ -127,17 +144,15 @@ def clean(self):
if username and password:
self.user_cache = authenticate(username=username, password=password)
if self.user_cache is None:
- raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
+ raise forms.ValidationError(self.error_messages['invalid_login'])
elif not self.user_cache.is_active:
- raise forms.ValidationError(_("This account is inactive."))
+ raise forms.ValidationError(self.error_messages['inactive'])
self.check_for_test_cookie()
return self.cleaned_data
def check_for_test_cookie(self):
if self.request and not self.request.session.test_cookie_worked():
- raise forms.ValidationError(
- _("Your Web browser doesn't appear to have cookies enabled. "
- "Cookies are required for logging in."))
+ raise forms.ValidationError(self.error_messages['no_cookies'])
def get_user_id(self):
if self.user_cache:
@@ -147,7 +162,14 @@ def get_user_id(self):
def get_user(self):
return self.user_cache
+
class PasswordResetForm(forms.Form):
+ error_messages = {
+ 'unknown': _("That e-mail address doesn't have an associated "
+ "user account. Are you sure you've registered?"),
+ 'unusable': _("The user account associated with this e-mail "
+ "address cannot reset the password."),
+ }
email = forms.EmailField(label=_("E-mail"), max_length=75)
def clean_email(self):
@@ -159,9 +181,9 @@ def clean_email(self):
email__iexact=email,
is_active=True)
if not len(self.users_cache):
- raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?"))
+ raise forms.ValidationError(self.error_messages['unknown'])
if any((user.password == UNUSABLE_PASSWORD) for user in self.users_cache):
- raise forms.ValidationError(_("The user account associated with this e-mail address cannot reset the password."))
+ raise forms.ValidationError(self.error_messages['unusable'])
return email
def save(self, domain_override=None,
@@ -195,11 +217,15 @@ def save(self, domain_override=None,
email = loader.render_to_string(email_template_name, c)
send_mail(subject, email, from_email, [user.email])
+
class SetPasswordForm(forms.Form):
"""
A form that lets a user change set his/her password without
entering the old password
"""
+ error_messages = {
+ 'password_mismatch': _("The two password fields didn't match."),
+ }
new_password1 = forms.CharField(label=_("New password"), widget=forms.PasswordInput)
new_password2 = forms.CharField(label=_("New password confirmation"), widget=forms.PasswordInput)
@@ -212,7 +238,7 @@ def clean_new_password2(self):
password2 = self.cleaned_data.get('new_password2')
if password1 and password2:
if password1 != password2:
- raise forms.ValidationError(_("The two password fields didn't match."))
+ raise forms.ValidationError(self.error_messages['password_mismatch'])
return password2
def save(self, commit=True):
@@ -221,11 +247,15 @@ def save(self, commit=True):
self.user.save()
return self.user
+
class PasswordChangeForm(SetPasswordForm):
"""
A form that lets a user change his/her password by entering
their old password.
"""
+ error_messages = dict(SetPasswordForm.error_messages, **{
+ 'password_incorrect': _("Your old password was entered incorrectly. Please enter it again."),
+ })
old_password = forms.CharField(label=_("Old password"), widget=forms.PasswordInput)
def clean_old_password(self):
@@ -234,14 +264,18 @@ def clean_old_password(self):
"""
old_password = self.cleaned_data["old_password"]
if not self.user.check_password(old_password):
- raise forms.ValidationError(_("Your old password was entered incorrectly. Please enter it again."))
+ raise forms.ValidationError(self.error_messages['password_incorrect'])
return old_password
PasswordChangeForm.base_fields.keyOrder = ['old_password', 'new_password1', 'new_password2']
+
class AdminPasswordChangeForm(forms.Form):
"""
A form used to change the password of a user in the admin interface.
"""
+ error_messages = {
+ 'password_mismatch': _("The two password fields didn't match."),
+ }
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
password2 = forms.CharField(label=_("Password (again)"), widget=forms.PasswordInput)
@@ -254,7 +288,7 @@ def clean_password2(self):
password2 = self.cleaned_data.get('password2')
if password1 and password2:
if password1 != password2:
- raise forms.ValidationError(_("The two password fields didn't match."))
+ raise forms.ValidationError(self.error_messages['password_mismatch'])
return password2
def save(self, commit=True):
@@ -1,9 +1,12 @@
from __future__ import with_statement
import os
from django.core import mail
+from django.forms.fields import Field, EmailField
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordChangeForm, SetPasswordForm, UserChangeForm, PasswordResetForm
from django.test import TestCase
+from django.utils.encoding import force_unicode
+from django.utils import translation
class UserCreationFormTest(TestCase):
@@ -19,7 +22,7 @@ def test_user_already_exists(self):
form = UserCreationForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form["username"].errors,
- [u'A user with that username already exists.'])
+ [force_unicode(form.error_messages['duplicate_username'])])
def test_invalid_data(self):
data = {
@@ -30,8 +33,7 @@ def test_invalid_data(self):
form = UserCreationForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form["username"].errors,
- [u'This value may contain only letters, numbers and @/./+/-/_ characters.'])
-
+ [force_unicode(form.fields['username'].error_messages['invalid'])])
def test_password_verification(self):
# The verification password is incorrect.
@@ -43,25 +45,21 @@ def test_password_verification(self):
form = UserCreationForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form["password2"].errors,
- [u"The two password fields didn't match."])
-
+ [force_unicode(form.error_messages['password_mismatch'])])
def test_both_passwords(self):
# One (or both) passwords weren't given
data = {'username': 'jsmith'}
form = UserCreationForm(data)
+ required_error = [force_unicode(Field.default_error_messages['required'])]
self.assertFalse(form.is_valid())
- self.assertEqual(form['password1'].errors,
- [u'This field is required.'])
- self.assertEqual(form['password2'].errors,
- [u'This field is required.'])
-
+ self.assertEqual(form['password1'].errors, required_error)
+ self.assertEqual(form['password2'].errors, required_error)
data['password2'] = 'test123'
form = UserCreationForm(data)
self.assertFalse(form.is_valid())
- self.assertEqual(form['password1'].errors,
- [u'This field is required.'])
+ self.assertEqual(form['password1'].errors, required_error)
def test_success(self):
# The success case.
@@ -91,7 +89,7 @@ def test_invalid_username(self):
form = AuthenticationForm(None, data)
self.assertFalse(form.is_valid())
self.assertEqual(form.non_field_errors(),
- [u'Please enter a correct username and password. Note that both fields are case-sensitive.'])
+ [force_unicode(form.error_messages['invalid_login'])])
def test_inactive_user(self):
# The user is inactive.
@@ -102,8 +100,20 @@ def test_inactive_user(self):
form = AuthenticationForm(None, data)
self.assertFalse(form.is_valid())
self.assertEqual(form.non_field_errors(),
- [u'This account is inactive.'])
-
+ [force_unicode(form.error_messages['inactive'])])
+
+ def test_inactive_user_i18n(self):
+ with self.settings(USE_I18N=True):
+ with translation.override('pt-br', deactivate=True):
+ # The user is inactive.
+ data = {
+ 'username': 'inactive',
+ 'password': 'password',
+ }
+ form = AuthenticationForm(None, data)
+ self.assertFalse(form.is_valid())
+ self.assertEqual(form.non_field_errors(),
+ [force_unicode(form.error_messages['inactive'])])
def test_success(self):
# The success case
@@ -130,7 +140,7 @@ def test_password_verification(self):
form = SetPasswordForm(user, data)
self.assertFalse(form.is_valid())
self.assertEqual(form["new_password2"].errors,
- [u"The two password fields didn't match."])
+ [force_unicode(form.error_messages['password_mismatch'])])
def test_success(self):
user = User.objects.get(username='testclient')
@@ -156,8 +166,7 @@ def test_incorrect_password(self):
form = PasswordChangeForm(user, data)
self.assertFalse(form.is_valid())
self.assertEqual(form["old_password"].errors,
- [u'Your old password was entered incorrectly. Please enter it again.'])
-
+ [force_unicode(form.error_messages['password_incorrect'])])
def test_password_verification(self):
# The two new passwords do not match.
@@ -170,8 +179,7 @@ def test_password_verification(self):
form = PasswordChangeForm(user, data)
self.assertFalse(form.is_valid())
self.assertEqual(form["new_password2"].errors,
- [u"The two password fields didn't match."])
-
+ [force_unicode(form.error_messages['password_mismatch'])])
def test_success(self):
# The success case.
@@ -190,6 +198,7 @@ def test_field_order(self):
self.assertEqual(PasswordChangeForm(user, {}).fields.keys(),
['old_password', 'new_password1', 'new_password2'])
+
class UserChangeFormTest(TestCase):
fixtures = ['authtestdata.json']
@@ -200,7 +209,7 @@ def test_username_validity(self):
form = UserChangeForm(data, instance=user)
self.assertFalse(form.is_valid())
self.assertEqual(form['username'].errors,
- [u'This value may contain only letters, numbers and @/./+/-/_ characters.'])
+ [force_unicode(form.fields['username'].error_messages['invalid'])])
def test_bug_14242(self):
# A regression test, introduce by adding an optimization for the
@@ -232,19 +241,19 @@ def create_dummy_user(self):
return (user, username, email)
def test_invalid_email(self):
- data = {'email':'not valid'}
+ data = {'email': 'not valid'}
form = PasswordResetForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form['email'].errors,
- [u'Enter a valid e-mail address.'])
+ [force_unicode(EmailField.default_error_messages['invalid'])])
def test_nonexistant_email(self):
# Test nonexistant email address
- data = {'email':'foo@bar.com'}
+ data = {'email': 'foo@bar.com'}
form = PasswordResetForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form.errors,
- {'email': [u"That e-mail address doesn't have an associated user account. Are you sure you've registered?"]})
+ {'email': [force_unicode(form.error_messages['unknown'])]})
def test_cleaned_data(self):
# Regression test
@@ -284,7 +293,6 @@ def test_inactive_user(self):
form = PasswordResetForm({'email': email})
self.assertFalse(form.is_valid())
-
def test_unusable_password(self):
user = User.objects.create_user('testuser', 'test@example.com', 'test')
data = {"email": "test@example.com"}
Oops, something went wrong. Retry.

0 comments on commit 5df31c0

Please sign in to comment.