diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py index 1d6d5e2743..a5de5bf650 100644 --- a/django/contrib/auth/forms.py +++ b/django/contrib/auth/forms.py @@ -100,10 +100,19 @@ class UserCreationForm(forms.ModelForm): self.error_messages['password_mismatch'], code='password_mismatch', ) - self.instance.username = self.cleaned_data.get('username') - password_validation.validate_password(self.cleaned_data.get('password2'), self.instance) return password2 + def _post_clean(self): + super()._post_clean() + # Validate the password after self.instance is updated with form data + # by super(). + password = self.cleaned_data.get('password2') + if password: + try: + password_validation.validate_password(password, self.instance) + except forms.ValidationError as error: + self.add_error('password2', error) + def save(self, commit=True): user = super().save(commit=False) user.set_password(self.cleaned_data["password1"]) diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py index 05f1f41961..e5cd05d0d8 100644 --- a/tests/auth_tests/test_forms.py +++ b/tests/auth_tests/test_forms.py @@ -239,6 +239,28 @@ class UserCreationFormTest(TestDataMixin, TestCase): '' ) + @override_settings(AUTH_PASSWORD_VALIDATORS=[ + {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'}, + ]) + def test_user_create_form_validates_password_with_all_data(self): + """UserCreationForm password validation uses all of the form's data.""" + class CustomUserCreationForm(UserCreationForm): + class Meta(UserCreationForm.Meta): + model = User + fields = ('username', 'email', 'first_name', 'last_name') + form = CustomUserCreationForm({ + 'username': 'testuser', + 'password1': 'testpassword', + 'password2': 'testpassword', + 'first_name': 'testpassword', + 'last_name': 'lastname', + }) + self.assertFalse(form.is_valid()) + self.assertEqual( + form.errors['password2'], + ['The password is too similar to the first name.'], + ) + # To verify that the login form rejects inactive users, use an authentication # backend that allows them.