Projet

Général

Profil

0002-convert-password-validation-code-to-new-API-24833.patch

Benjamin Dauvergne, 06 juillet 2018 15:15

Télécharger (10,7 ko)

Voir les différences:

Subject: [PATCH 2/2] convert password validation code to new API (#24833)

 src/authentic2/validators.py  | 67 +++++++----------------------------
 tests/test_attribute_kinds.py | 52 +++++++++++++--------------
 tests/test_registration.py    |  2 +-
 3 files changed, 39 insertions(+), 82 deletions(-)
src/authentic2/validators.py
15 15
import dns.resolver
16 16
import dns.exception
17 17

  
18
from . import app_settings
18
from . import app_settings, passwords
19 19

  
20 20
# copied from http://www.djangotips.com/real-email-validation
21 21
class EmailValidator(object):
......
80 80

  
81 81
email_validator = EmailValidator()
82 82

  
83
def validate_password(password):
84
    password_set = set(password)
85
    digits = set(string.digits)
86
    lower = set(string.lowercase)
87
    upper = set(string.uppercase)
88
    punc = set(string.punctuation)
89
    errors = []
90

  
91
    if not password:
92
        return
93
    min_len = app_settings.A2_PASSWORD_POLICY_MIN_LENGTH
94
    if len(password) < min_len:
95
        errors.append(ValidationError(_('password must contain at least %d '
96
            'characters') % min_len))
97

  
98
    class_count = 0
99
    for cls in (digits, lower, upper, punc):
100
        if not password_set.isdisjoint(cls):
101
            class_count += 1
102
    min_class_count = app_settings.A2_PASSWORD_POLICY_MIN_CLASSES
103
    if class_count < min_class_count:
104
        errors.append(ValidationError(_('password must contain characters '
105
            'from at least %d classes among: lowercase letters, '
106
            'uppercase letters, digits, and punctuations') % min_class_count))
107
    if app_settings.A2_PASSWORD_POLICY_REGEX:
108
        if not re.match(app_settings.A2_PASSWORD_POLICY_REGEX, password):
109
            msg = app_settings.A2_PASSWORD_POLICY_REGEX_ERROR_MSG
110
            msg = msg or _('your password dit not match the regular expession %s') % app_settings.A2_PASSWORD_POLICY_REGEX
111
            errors.append(ValidationError(msg))
112
    if errors:
113
        raise ValidationError(errors)
114

  
115 83

  
116 84
class UsernameValidator(RegexValidator):
117 85
    def __init__(self, *args, **kwargs):
......
119 87
        super(UsernameValidator, self).__init__(*args, **kwargs)
120 88

  
121 89

  
122
def __password_help_text_helper():
123
    if app_settings.A2_PASSWORD_POLICY_MIN_LENGTH and \
124
            app_settings.A2_PASSWORD_POLICY_MIN_CLASSES:
125
        yield ugettext('Your password must contain at least %(min_length)d characters from at '
126
                'least %(min_classes)d classes among: lowercase letters, uppercase letters, '
127
                'digits and punctuations.') % {
128
                        'min_length': app_settings.A2_PASSWORD_POLICY_MIN_LENGTH,
129
                        'min_classes': app_settings.A2_PASSWORD_POLICY_MIN_CLASSES}
130
    else:
131
        if app_settings.A2_PASSWORD_POLICY_MIN_LENGTH:
132
            yield ugettext('Your password must contain at least %(min_length)d characters.') % {'min_length': app_settings.A2_PASSWORD_POLICY_MIN_LENGTH}
133
        if app_settings.A2_PASSWORD_POLICY_MIN_CLASSES:
134
            yield ugettext('Your password must contain characters from at least %(min_classes)d '
135
                    'classes among: lowercase letters, uppercase letters, digits '
136
                    'and punctuations.') % {'min_classes': app_settings.A2_PASSWORD_POLICY_MIN_CLASSES}
137
    if app_settings.A2_PASSWORD_POLICY_REGEX:
138
        yield ugettext(app_settings.A2_PASSWORD_POLICY_REGEX_ERROR_MSG) or \
139
                ugettext('Your password must match the regular expression: '
140
                        '%(regexp)s, please change this message using the '
141
                        'A2_PASSWORD_POLICY_REGEX_ERROR_MSG setting.') % \
142
                        {'regexp': app_settings.A2_PASSWORD_POLICY_REGEX}
90
def validate_password(password):
91
    errors = []
92
    password_checker = passwords.get_password_checker()
93
    for check in password_checker(password):
94
        if not check.result:
95
            errors.append(ugettext('Password must obey the rule: %s') % check.label)
96
    if errors:
97
        raise ValidationError(errors)
98

  
143 99

  
144 100
def password_help_text():
145
    return ' '.join(__password_help_text_helper())
101
    password_checker = passwords.get_password_checker()
102
    return ugettext('Password must obey the rules: ') + ', '.join(check.label for check in password_checker(''))
146 103

  
147 104
password_help_text = lazy(password_help_text, six.text_type)
tests/test_attribute_kinds.py
23 23
    form.set('first_name', 'John')
24 24
    form.set('last_name', 'Doe')
25 25
    form.set('nom_de_naissance', '1234567890' * 30)
26
    form.set('password1', '12345abcd#')
27
    form.set('password2', '12345abcd#')
26
    form.set('password1', '12345abcdA')
27
    form.set('password2', '12345abcdA')
28 28
    response = form.submit()
29 29
    assert response.pyquery.find('.form-field-error #id_nom_de_naissance')
30 30

  
31 31
    form = response.form
32 32
    form.set('nom_de_naissance', u'Noël')
33
    form.set('password1', '12345abcd#')
34
    form.set('password2', '12345abcd#')
33
    form.set('password1', '12345abcdA')
34
    form.set('password2', '12345abcdA')
35 35
    response = form.submit().follow()
36 36
    assert qs.get().attributes.nom_de_naissance == u'Noël'
37 37
    qs.delete()
......
71 71
    form.set('first_name', 'John')
72 72
    form.set('last_name', 'Doe')
73 73
    form.set('postcode', 'abc')
74
    form.set('password1', '12345abcd#')
75
    form.set('password2', '12345abcd#')
74
    form.set('password1', '12345abcdA')
75
    form.set('password2', '12345abcdA')
76 76
    response = form.submit()
77 77
    assert response.pyquery.find('.form-field-error #id_postcode')
78 78

  
79 79
    form = response.form
80 80
    form.set('postcode', '123')
81
    form.set('password1', '12345abcd#')
82
    form.set('password2', '12345abcd#')
81
    form.set('password1', '12345abcdA')
82
    form.set('password2', '12345abcdA')
83 83
    response = form.submit()
84 84
    assert response.pyquery.find('.form-field-error #id_postcode')
85 85

  
86 86
    form = response.form
87 87
    form.set('postcode', '12345')
88
    form.set('password1', '12345abcd#')
89
    form.set('password2', '12345abcd#')
88
    form.set('password1', '12345abcdA')
89
    form.set('password2', '12345abcdA')
90 90
    response = form.submit().follow()
91 91
    assert qs.get().attributes.postcode == '12345'
92 92
    qs.delete()
......
96 96
    form.set('first_name', 'John')
97 97
    form.set('last_name', 'Doe')
98 98
    form.set('postcode', ' 12345 ')
99
    form.set('password1', '12345abcd#')
100
    form.set('password2', '12345abcd#')
99
    form.set('password1', '12345abcdA')
100
    form.set('password2', '12345abcdA')
101 101
    response = form.submit().follow()
102 102
    assert qs.get().attributes.postcode == '12345'
103 103
    qs.delete()
......
107 107
    form.set('first_name', 'John')
108 108
    form.set('last_name', 'Doe')
109 109
    form.set('postcode', '')
110
    form.set('password1', '12345abcd#')
111
    form.set('password2', '12345abcd#')
110
    form.set('password1', '12345abcdA')
111
    form.set('password2', '12345abcdA')
112 112
    response = form.submit().follow()
113 113
    assert qs.get().attributes.postcode == ''
114 114
    qs.delete()
......
174 174
    form.set('first_name', 'John')
175 175
    form.set('last_name', 'Doe')
176 176
    form.set('phone_number', 'abc')
177
    form.set('password1', '12345abcd#')
178
    form.set('password2', '12345abcd#')
177
    form.set('password1', '12345abcdA')
178
    form.set('password2', '12345abcdA')
179 179
    response = form.submit()
180 180
    assert response.pyquery.find('.form-field-error #id_phone_number')
181 181

  
182 182
    form = response.form
183 183
    assert response.pyquery('#id_phone_number').attr('maxlength') == '30'
184 184
    form.set('phone_number', '1234512345' * 10)
185
    form.set('password1', '12345abcd#')
186
    form.set('password2', '12345abcd#')
185
    form.set('password1', '12345abcdA')
186
    form.set('password2', '12345abcdA')
187 187
    response = form.submit()
188 188
    assert response.pyquery.find('.form-field-error #id_phone_number')
189 189

  
190 190
    form = response.form
191 191
    form.set('phone_number', '12345')
192
    form.set('password1', '12345abcd#')
193
    form.set('password2', '12345abcd#')
192
    form.set('password1', '12345abcdA')
193
    form.set('password2', '12345abcdA')
194 194
    response = form.submit().follow()
195 195
    assert qs.get().attributes.phone_number == '12345'
196 196
    qs.delete()
......
200 200
    form.set('first_name', 'John')
201 201
    form.set('last_name', 'Doe')
202 202
    form.set('phone_number', '+12345')
203
    form.set('password1', '12345abcd#')
204
    form.set('password2', '12345abcd#')
203
    form.set('password1', '12345abcdA')
204
    form.set('password2', '12345abcdA')
205 205
    response = form.submit().follow()
206 206
    assert qs.get().attributes.phone_number == '+12345'
207 207
    qs.delete()
......
211 211
    form.set('first_name', 'John')
212 212
    form.set('last_name', 'Doe')
213 213
    form.set('phone_number', '')
214
    form.set('password1', '12345abcd#')
215
    form.set('password2', '12345abcd#')
214
    form.set('password1', '12345abcdA')
215
    form.set('password2', '12345abcdA')
216 216
    response = form.submit().follow()
217 217
    assert qs.get().attributes.phone_number == ''
218 218
    qs.delete()
......
222 222
    form.set('first_name', 'John')
223 223
    form.set('last_name', 'Doe')
224 224
    form.set('phone_number', ' +  1.2-3  4 5 ')
225
    form.set('password1', '12345abcd#')
226
    form.set('password2', '12345abcd#')
225
    form.set('password1', '12345abcdA')
226
    form.set('password2', '12345abcdA')
227 227
    response = form.submit().follow()
228 228
    assert qs.get().attributes.phone_number == '+12345'
229 229
    qs.delete()
tests/test_registration.py
40 40
    response.form.set('password1', 'toto')
41 41
    response.form.set('password2', 'toto')
42 42
    response = response.form.submit()
43
    assert 'password must contain at least 8 characters' in response.content
43
    assert 'at least 8 characters' in response.content
44 44

  
45 45
    # set valid password
46 46
    response.form.set('password1', 'T0==toto')
47
-