使用UserAttributesimarityValidator和Customuser Django验证密码验证

发布于 2025-01-23 13:58:40 字数 3773 浏览 2 评论 0原文

我正在尝试针对自定义者字段验证密码: 电子邮件和full_name。

所有测试验证都可以正常工作,除了UserAttributesimilityValidator,这是我在下面的代码中包含的唯一测试。

    class RegistrationForm(forms.ModelForm):
        email = forms.EmailField(label=_('Email address'),
                                 widget=forms.EmailInput(attrs={'class': 'form-control mb-4',
                                                            'class': 'form-control mb-4',
                                                            }))

        full_name = forms.CharField(label=_('Full name'),
                                    widget=forms.TextInput(attrs={'class': 'form-control mb-4',
                                                              }))
        password = forms.CharField(label=_('Password'),
                                   widget=forms.PasswordInput(attrs={'class': 'form-control mb-4',
                                                                 'autocomplete': 'new-password',
                                                                 'id': 'psw',
                                                                 }))

        class Meta:
            model = get_user_model()
            fields = ('full_name', 'email', 'password')

        def clean_password(self):
            password = self.cleaned_data.get("password")
            if password:
                try:
                    password_validation.validate_password(password, self.instance)
                except ValidationError as error:
                    self.add_error("password", error)
            return password

        def clean_email(self):
            email = self.cleaned_data['email']
            if User.objects.filter(email=email).exists():
                raise forms.ValidationError(
                mark_safe(_(f'A user with that email already exists, click this <br><a href="{reverse("account:pwdreset")}">Password Reset</a> link'
                      ' to recover your account.'))
            )

            return email

表格

@override_settings(
        AUTH_PASSWORD_VALIDATORS=[
            {
                'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
                'OPTIONS': {
                    'user_attributes': (
                            'email', 'full_name',
                    )},
            },

        ]
    )
    def test_validates_password(self):
        data = {
            "email": "[email protected]",
            "full_name": "John Smith",
            "password": "jsmith",
        }
        form = RegistrationForm(data)
        self.assertFalse(form.is_valid()
        self.assertEqual(len(form["password"].errors), 1)

        self.assertIn(
            "The password is too similar to the email.",
            form["password"].errors,
        )

FAIL: test_validates_password (account.tests.test_forms.RegistrationFormTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/tester/Documents/dev/test/venv/lib/python3.8/site-packages/django/test/utils.py", line 437, in inner
    return func(*args, **kwargs)
  File "/Users/tester/Documents/dev/test/account/tests/test_forms.py", line 112, in test_validates_password
    self.assertFalse(form.is_valid())
AssertionError: True is not false

----------------------------------------------------------------------
Ran 5 tests in 0.868s

FAILED (failures=1)
Destroying test database for alias 'default'...

拜托,我在做什么错?

    Django 4.0.2

I am trying to validate a password against CustomUser fields:
email and full_name.

All test validations are working except for UserAttributeSimilarityValidator, which is the only test that I have included with the code below.

forms.py

    class RegistrationForm(forms.ModelForm):
        email = forms.EmailField(label=_('Email address'),
                                 widget=forms.EmailInput(attrs={'class': 'form-control mb-4',
                                                            'class': 'form-control mb-4',
                                                            }))

        full_name = forms.CharField(label=_('Full name'),
                                    widget=forms.TextInput(attrs={'class': 'form-control mb-4',
                                                              }))
        password = forms.CharField(label=_('Password'),
                                   widget=forms.PasswordInput(attrs={'class': 'form-control mb-4',
                                                                 'autocomplete': 'new-password',
                                                                 'id': 'psw',
                                                                 }))

        class Meta:
            model = get_user_model()
            fields = ('full_name', 'email', 'password')

        def clean_password(self):
            password = self.cleaned_data.get("password")
            if password:
                try:
                    password_validation.validate_password(password, self.instance)
                except ValidationError as error:
                    self.add_error("password", error)
            return password

        def clean_email(self):
            email = self.cleaned_data['email']
            if User.objects.filter(email=email).exists():
                raise forms.ValidationError(
                mark_safe(_(f'A user with that email already exists, click this <br><a href="{reverse("account:pwdreset")}">Password Reset</a> link'
                      ' to recover your account.'))
            )

            return email

tests.py

@override_settings(
        AUTH_PASSWORD_VALIDATORS=[
            {
                'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
                'OPTIONS': {
                    'user_attributes': (
                            'email', 'full_name',
                    )},
            },

        ]
    )
    def test_validates_password(self):
        data = {
            "email": "[email protected]",
            "full_name": "John Smith",
            "password": "jsmith",
        }
        form = RegistrationForm(data)
        self.assertFalse(form.is_valid()
        self.assertEqual(len(form["password"].errors), 1)

        self.assertIn(
            "The password is too similar to the email.",
            form["password"].errors,
        )

Which results in this test result:

FAIL: test_validates_password (account.tests.test_forms.RegistrationFormTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/tester/Documents/dev/test/venv/lib/python3.8/site-packages/django/test/utils.py", line 437, in inner
    return func(*args, **kwargs)
  File "/Users/tester/Documents/dev/test/account/tests/test_forms.py", line 112, in test_validates_password
    self.assertFalse(form.is_valid())
AssertionError: True is not false

----------------------------------------------------------------------
Ran 5 tests in 0.868s

FAILED (failures=1)
Destroying test database for alias 'default'...

Which is completely logical because the UserAttributeSimilarityValidator is not picking up the similarity between the email and the password fields.

Please, what am I doing wrong?

    Django 4.0.2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

过气美图社 2025-01-30 13:58:40

解决方案是从django.contrib.auth.forms.usercreationform复制save()方法并添加到表单:

def save(self, commit=True):
      """
      Save user.
      Save the provided password in hashed format.
      :return custom_user.models.EmailUser: user
      """
      user = super().save(commit=False)
      user.set_password(self.cleaned_data["password"])

     if commit:
            user.save()
     return user

The solution is to copy the save() method from django.contrib.auth.forms.UserCreationForm and add to the form:

def save(self, commit=True):
      """
      Save user.
      Save the provided password in hashed format.
      :return custom_user.models.EmailUser: user
      """
      user = super().save(commit=False)
      user.set_password(self.cleaned_data["password"])

     if commit:
            user.save()
     return user
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文