Loading django/contrib/auth/forms.py +8 −1 Original line number Diff line number Diff line Loading @@ -69,9 +69,11 @@ class UserCreationForm(forms.ModelForm): 'password_mismatch': _("The two password fields didn't match."), } password1 = forms.CharField(label=_("Password"), strip=False, widget=forms.PasswordInput) password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput, strip=False, help_text=_("Enter the same password as before, for verification.")) class Meta: Loading Loading @@ -134,7 +136,7 @@ class AuthenticationForm(forms.Form): max_length=254, widget=forms.TextInput(attrs={'autofocus': ''}), ) password = forms.CharField(label=_("Password"), widget=forms.PasswordInput) password = forms.CharField(label=_("Password"), strip=False, widget=forms.PasswordInput) error_messages = { 'invalid_login': _("Please enter a correct %(username)s and password. " Loading Loading @@ -276,8 +278,10 @@ class SetPasswordForm(forms.Form): } new_password1 = forms.CharField(label=_("New password"), widget=forms.PasswordInput, strip=False, help_text=password_validation.password_validators_help_text_html()) new_password2 = forms.CharField(label=_("New password confirmation"), strip=False, widget=forms.PasswordInput) def __init__(self, user, *args, **kwargs): Loading Loading @@ -315,6 +319,7 @@ class PasswordChangeForm(SetPasswordForm): }) old_password = forms.CharField( label=_("Old password"), strip=False, widget=forms.PasswordInput(attrs={'autofocus': ''}), ) Loading Loading @@ -344,11 +349,13 @@ class AdminPasswordChangeForm(forms.Form): password1 = forms.CharField( label=_("Password"), widget=forms.PasswordInput(attrs={'autofocus': ''}), strip=False, help_text=password_validation.password_validators_help_text_html(), ) password2 = forms.CharField( label=_("Password (again)"), widget=forms.PasswordInput, strip=False, help_text=_("Enter the same password as before, for verification."), ) Loading docs/releases/1.9.5.txt +6 −0 Original line number Diff line number Diff line Loading @@ -19,3 +19,9 @@ Bugfixes * Fixed data loss on SQLite where ``DurationField`` values with fractional seconds could be saved as ``None`` (:ticket:`26324`). * The forms in ``contrib.auth`` no longer strip trailing and leading whitespace from the password fields (:ticket:`26334`). The change requires users who set their password to something with such whitespace after a site updated to Django 1.9 to reset their password. It provides backwards-compatibility for earlier versions of Django. tests/auth_tests/test_forms.py +56 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,17 @@ class UserCreationFormTest(TestDataMixin, TestCase): form = CustomUserCreationForm(data) self.assertTrue(form.is_valid()) def test_password_whitespace_not_stripped(self): data = { 'username': 'testuser', 'password1': ' testpassword ', 'password2': ' testpassword ', } form = UserCreationForm(data) self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['password1'], data['password1']) self.assertEqual(form.cleaned_data['password2'], data['password2']) class AuthenticationFormTest(TestDataMixin, TestCase): Loading Loading @@ -248,6 +259,15 @@ class AuthenticationFormTest(TestDataMixin, TestCase): form = CustomAuthenticationForm() self.assertEqual(form.fields['username'].label, "") def test_password_whitespace_not_stripped(self): data = { 'username': 'testuser', 'password': ' pass ', } form = AuthenticationForm(None, data) form.is_valid() # Not necessary to have valid credentails for the test. self.assertEqual(form.cleaned_data['password'], data['password']) class SetPasswordFormTest(TestDataMixin, TestCase): Loading Loading @@ -298,6 +318,17 @@ class SetPasswordFormTest(TestDataMixin, TestCase): form["new_password2"].errors ) def test_password_whitespace_not_stripped(self): user = User.objects.get(username='testclient') data = { 'new_password1': ' password ', 'new_password2': ' password ', } form = SetPasswordForm(user, data) self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['new_password1'], data['new_password1']) self.assertEqual(form.cleaned_data['new_password2'], data['new_password2']) class PasswordChangeFormTest(TestDataMixin, TestCase): Loading Loading @@ -348,6 +379,20 @@ class PasswordChangeFormTest(TestDataMixin, TestCase): self.assertEqual(list(PasswordChangeForm(user, {}).fields), ['old_password', 'new_password1', 'new_password2']) def test_password_whitespace_not_stripped(self): user = User.objects.get(username='testclient') user.set_password(' oldpassword ') data = { 'old_password': ' oldpassword ', 'new_password1': ' pass ', 'new_password2': ' pass ', } form = PasswordChangeForm(user, data) self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['old_password'], data['old_password']) self.assertEqual(form.cleaned_data['new_password1'], data['new_password1']) self.assertEqual(form.cleaned_data['new_password2'], data['new_password2']) class UserChangeFormTest(TestDataMixin, TestCase): Loading Loading @@ -635,3 +680,14 @@ class AdminPasswordChangeFormTest(TestDataMixin, TestCase): self.assertEqual(password_changed.call_count, 0) form.save() self.assertEqual(password_changed.call_count, 1) def test_password_whitespace_not_stripped(self): user = User.objects.get(username='testclient') data = { 'password1': ' pass ', 'password2': ' pass ', } form = AdminPasswordChangeForm(user, data) self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['password1'], data['password1']) self.assertEqual(form.cleaned_data['password2'], data['password2']) Loading
django/contrib/auth/forms.py +8 −1 Original line number Diff line number Diff line Loading @@ -69,9 +69,11 @@ class UserCreationForm(forms.ModelForm): 'password_mismatch': _("The two password fields didn't match."), } password1 = forms.CharField(label=_("Password"), strip=False, widget=forms.PasswordInput) password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput, strip=False, help_text=_("Enter the same password as before, for verification.")) class Meta: Loading Loading @@ -134,7 +136,7 @@ class AuthenticationForm(forms.Form): max_length=254, widget=forms.TextInput(attrs={'autofocus': ''}), ) password = forms.CharField(label=_("Password"), widget=forms.PasswordInput) password = forms.CharField(label=_("Password"), strip=False, widget=forms.PasswordInput) error_messages = { 'invalid_login': _("Please enter a correct %(username)s and password. " Loading Loading @@ -276,8 +278,10 @@ class SetPasswordForm(forms.Form): } new_password1 = forms.CharField(label=_("New password"), widget=forms.PasswordInput, strip=False, help_text=password_validation.password_validators_help_text_html()) new_password2 = forms.CharField(label=_("New password confirmation"), strip=False, widget=forms.PasswordInput) def __init__(self, user, *args, **kwargs): Loading Loading @@ -315,6 +319,7 @@ class PasswordChangeForm(SetPasswordForm): }) old_password = forms.CharField( label=_("Old password"), strip=False, widget=forms.PasswordInput(attrs={'autofocus': ''}), ) Loading Loading @@ -344,11 +349,13 @@ class AdminPasswordChangeForm(forms.Form): password1 = forms.CharField( label=_("Password"), widget=forms.PasswordInput(attrs={'autofocus': ''}), strip=False, help_text=password_validation.password_validators_help_text_html(), ) password2 = forms.CharField( label=_("Password (again)"), widget=forms.PasswordInput, strip=False, help_text=_("Enter the same password as before, for verification."), ) Loading
docs/releases/1.9.5.txt +6 −0 Original line number Diff line number Diff line Loading @@ -19,3 +19,9 @@ Bugfixes * Fixed data loss on SQLite where ``DurationField`` values with fractional seconds could be saved as ``None`` (:ticket:`26324`). * The forms in ``contrib.auth`` no longer strip trailing and leading whitespace from the password fields (:ticket:`26334`). The change requires users who set their password to something with such whitespace after a site updated to Django 1.9 to reset their password. It provides backwards-compatibility for earlier versions of Django.
tests/auth_tests/test_forms.py +56 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,17 @@ class UserCreationFormTest(TestDataMixin, TestCase): form = CustomUserCreationForm(data) self.assertTrue(form.is_valid()) def test_password_whitespace_not_stripped(self): data = { 'username': 'testuser', 'password1': ' testpassword ', 'password2': ' testpassword ', } form = UserCreationForm(data) self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['password1'], data['password1']) self.assertEqual(form.cleaned_data['password2'], data['password2']) class AuthenticationFormTest(TestDataMixin, TestCase): Loading Loading @@ -248,6 +259,15 @@ class AuthenticationFormTest(TestDataMixin, TestCase): form = CustomAuthenticationForm() self.assertEqual(form.fields['username'].label, "") def test_password_whitespace_not_stripped(self): data = { 'username': 'testuser', 'password': ' pass ', } form = AuthenticationForm(None, data) form.is_valid() # Not necessary to have valid credentails for the test. self.assertEqual(form.cleaned_data['password'], data['password']) class SetPasswordFormTest(TestDataMixin, TestCase): Loading Loading @@ -298,6 +318,17 @@ class SetPasswordFormTest(TestDataMixin, TestCase): form["new_password2"].errors ) def test_password_whitespace_not_stripped(self): user = User.objects.get(username='testclient') data = { 'new_password1': ' password ', 'new_password2': ' password ', } form = SetPasswordForm(user, data) self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['new_password1'], data['new_password1']) self.assertEqual(form.cleaned_data['new_password2'], data['new_password2']) class PasswordChangeFormTest(TestDataMixin, TestCase): Loading Loading @@ -348,6 +379,20 @@ class PasswordChangeFormTest(TestDataMixin, TestCase): self.assertEqual(list(PasswordChangeForm(user, {}).fields), ['old_password', 'new_password1', 'new_password2']) def test_password_whitespace_not_stripped(self): user = User.objects.get(username='testclient') user.set_password(' oldpassword ') data = { 'old_password': ' oldpassword ', 'new_password1': ' pass ', 'new_password2': ' pass ', } form = PasswordChangeForm(user, data) self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['old_password'], data['old_password']) self.assertEqual(form.cleaned_data['new_password1'], data['new_password1']) self.assertEqual(form.cleaned_data['new_password2'], data['new_password2']) class UserChangeFormTest(TestDataMixin, TestCase): Loading Loading @@ -635,3 +680,14 @@ class AdminPasswordChangeFormTest(TestDataMixin, TestCase): self.assertEqual(password_changed.call_count, 0) form.save() self.assertEqual(password_changed.call_count, 1) def test_password_whitespace_not_stripped(self): user = User.objects.get(username='testclient') data = { 'password1': ' pass ', 'password2': ' pass ', } form = AdminPasswordChangeForm(user, data) self.assertTrue(form.is_valid()) self.assertEqual(form.cleaned_data['password1'], data['password1']) self.assertEqual(form.cleaned_data['password2'], data['password2'])