diff options
| author | nessita <124304+nessita@users.noreply.github.com> | 2025-02-01 22:49:07 -0300 |
|---|---|---|
| committer | Natalia <124304+nessita@users.noreply.github.com> | 2025-02-01 22:50:26 -0300 |
| commit | affad13d0c56184e2089cd7e8ecd80dd4217f6c4 (patch) | |
| tree | dc9496afe0bfa2efb0fb9557756dd658e4ed780b /tests/auth_tests/test_forms.py | |
| parent | e939cffa504837d90cf2958306f57649ee6a8323 (diff) | |
[5.2.x] Fixed #36140 -- Allowed BaseUserCreationForm to define non required password fields.
Regression in e626716c28b6286f8cf0f8174077f3d2244f3eb3.
Thanks buffgecko12 for the report and Sarah Boyce for the review.
Backport of d15454a6e84a595ffc8dc1b926282f484f782a8f from main.
Diffstat (limited to 'tests/auth_tests/test_forms.py')
| -rw-r--r-- | tests/auth_tests/test_forms.py | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py index 5d81d8f7fd..4740cb6200 100644 --- a/tests/auth_tests/test_forms.py +++ b/tests/auth_tests/test_forms.py @@ -1,8 +1,10 @@ import datetime import re +import sys import urllib.parse from unittest import mock +from django import forms from django.contrib.auth.forms import ( AdminPasswordChangeForm, AdminUserCreationForm, @@ -13,6 +15,7 @@ from django.contrib.auth.forms import ( ReadOnlyPasswordHashField, ReadOnlyPasswordHashWidget, SetPasswordForm, + SetPasswordMixin, UserChangeForm, UserCreationForm, UsernameField, @@ -24,13 +27,14 @@ from django.contrib.sites.models import Site from django.core import mail from django.core.exceptions import ValidationError from django.core.mail import EmailMultiAlternatives -from django.forms import forms from django.forms.fields import CharField, Field, IntegerField -from django.test import SimpleTestCase, TestCase, override_settings +from django.test import RequestFactory, SimpleTestCase, TestCase, override_settings from django.urls import reverse from django.utils import translation from django.utils.text import capfirst from django.utils.translation import gettext as _ +from django.views.debug import technical_500_response +from django.views.decorators.debug import sensitive_variables from .models.custom_user import ( CustomUser, @@ -412,6 +416,19 @@ class CustomUserCreationFormTest(TestDataMixin, TestCase): user = form.save(commit=True) self.assertSequenceEqual(user.orgs.all(), [organization]) + def test_custom_form_with_non_required_password(self): + class CustomUserCreationForm(BaseUserCreationForm): + password1 = forms.CharField(required=False) + password2 = forms.CharField(required=False) + another_field = forms.CharField(required=True) + + data = { + "username": "testclientnew", + "another_field": "Content", + } + form = CustomUserCreationForm(data) + self.assertIs(form.is_valid(), True, form.errors) + class UserCreationFormTest(BaseUserCreationFormTest): @@ -1671,3 +1688,50 @@ class AdminUserCreationFormTest(BaseUserCreationFormTest): u = form.save() self.assertEqual(u.username, data["username"]) self.assertFalse(u.has_usable_password()) + + +class SensitiveVariablesTest(TestDataMixin, TestCase): + @sensitive_variables("data") + def test_passwords_marked_as_sensitive_in_admin_forms(self): + data = { + "password1": "passwordsensitive", + "password2": "sensitivepassword", + "usable_password": "true", + } + forms = [ + AdminUserCreationForm({**data, "username": "newusername"}), + AdminPasswordChangeForm(self.u1, data), + ] + + password1_fragment = """ + <td>password1</td> + <td class="code"><pre>'********************'</pre></td> + """ + password2_fragment = """ + <td>password2</td> + <td class="code"><pre>'********************'</pre></td> + """ + error = ValueError("Forced error") + for form in forms: + with self.subTest(form=form): + with mock.patch.object( + SetPasswordMixin, "validate_passwords", side_effect=error + ): + try: + form.is_valid() + except ValueError: + exc_info = sys.exc_info() + else: + self.fail("Form validation should have failed.") + + response = technical_500_response(RequestFactory().get("/"), *exc_info) + + self.assertNotContains(response, "sensitivepassword", status_code=500) + self.assertNotContains(response, "passwordsensitive", status_code=500) + self.assertContains(response, str(error), status_code=500) + self.assertContains( + response, password1_fragment, html=True, status_code=500 + ) + self.assertContains( + response, password2_fragment, html=True, status_code=500 + ) |
