Fixed #26909 -- Allowed UserAttributeSimilarityValidator to validate against model properties.

This commit is contained in:
Andrew Nester 2016-07-22 11:51:38 +03:00 committed by Tim Graham
parent f5c6295797
commit 4591cf3fd8
2 changed files with 22 additions and 2 deletions

View File

@ -6,7 +6,9 @@ import re
from difflib import SequenceMatcher from difflib import SequenceMatcher
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, ValidationError from django.core.exceptions import (
FieldDoesNotExist, ImproperlyConfigured, ValidationError,
)
from django.utils import lru_cache from django.utils import lru_cache
from django.utils._os import upath from django.utils._os import upath
from django.utils.encoding import force_text from django.utils.encoding import force_text
@ -144,7 +146,10 @@ class UserAttributeSimilarityValidator(object):
value_parts = re.split('\W+', value) + [value] value_parts = re.split('\W+', value) + [value]
for value_part in value_parts: for value_part in value_parts:
if SequenceMatcher(a=password.lower(), b=value_part.lower()).quick_ratio() > self.max_similarity: if SequenceMatcher(a=password.lower(), b=value_part.lower()).quick_ratio() > self.max_similarity:
try:
verbose_name = force_text(user._meta.get_field(attribute_name).verbose_name) verbose_name = force_text(user._meta.get_field(attribute_name).verbose_name)
except FieldDoesNotExist:
verbose_name = attribute_name
raise ValidationError( raise ValidationError(
_("The password is too similar to the %(verbose_name)s."), _("The password is too similar to the %(verbose_name)s."),
code='password_too_similar', code='password_too_similar',

View File

@ -13,7 +13,9 @@ from django.contrib.auth.password_validation import (
validate_password, validate_password,
) )
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from django.test.utils import isolate_apps
from django.utils._os import upath from django.utils._os import upath
@ -127,6 +129,19 @@ class UserAttributeSimilarityValidatorTest(TestCase):
UserAttributeSimilarityValidator(user_attributes=['first_name']).validate('testclient', user=user) UserAttributeSimilarityValidator(user_attributes=['first_name']).validate('testclient', user=user)
) )
@isolate_apps('auth_tests')
def test_validate_property(self):
class TestUser(models.Model):
pass
@property
def username(self):
return 'foobar'
with self.assertRaises(ValidationError) as cm:
UserAttributeSimilarityValidator().validate('foobar', user=TestUser()),
self.assertEqual(cm.exception.messages, ['The password is too similar to the username.'])
def test_help_text(self): def test_help_text(self):
self.assertEqual( self.assertEqual(
UserAttributeSimilarityValidator().get_help_text(), UserAttributeSimilarityValidator().get_help_text(),