|
1 | 1 | import abc |
2 | 2 | import re |
3 | | -import unicodedata |
4 | 3 |
|
5 | 4 | import django.core.exceptions |
6 | 5 | from django.utils.translation import gettext as _ |
@@ -135,35 +134,35 @@ def get_error_message(self) -> str: |
135 | 134 | return _(f'Password must contain at least {self.min_count} digit(s).') |
136 | 135 |
|
137 | 136 |
|
138 | | -class LatinLetterPasswordValidator(BaseCountPasswordValidator): |
| 137 | +class LowercaseLatinLetterPasswordValidator(BaseCountPasswordValidator): |
139 | 138 | """ |
140 | | - Validates presence of minimum required Latin letters (ASCII) |
| 139 | + Validates presence of minimum required lowercase Latin letters |
141 | 140 |
|
142 | 141 | Args: |
143 | | - min_count (int): Minimum required letters (default: 1) |
| 142 | + min_count (int): Minimum required lowercase letters (default: 1) |
144 | 143 | """ |
145 | 144 |
|
146 | 145 | def __init__(self, min_count=1): |
147 | 146 | super().__init__(min_count) |
148 | | - self.code = 'password_no_latin_letter' |
| 147 | + self.code = 'password_no_lowercase_latin' |
149 | 148 |
|
150 | 149 | def validate_char(self, char) -> bool: |
151 | | - """Check if character is a Latin ASCII letter""" |
152 | | - return unicodedata.category(char).startswith('L') and char.isascii() |
| 150 | + """Check if character is lower Latin letter""" |
| 151 | + return char.islower() and char.isascii() |
153 | 152 |
|
154 | 153 | def get_help_text(self) -> str: |
155 | 154 | return _( |
156 | 155 | ( |
157 | 156 | f'Your password must contain at least {self.min_count} ' |
158 | | - 'Latin letter(s).' |
| 157 | + 'lowercase Latin letter(s).' |
159 | 158 | ), |
160 | 159 | ) |
161 | 160 |
|
162 | 161 | def get_error_message(self) -> str: |
163 | 162 | return _( |
164 | 163 | ( |
165 | 164 | f'Password must contain at least {self.min_count} ' |
166 | | - 'Latin letter(s).' |
| 165 | + 'lowercase Latin letter(s).' |
167 | 166 | ), |
168 | 167 | ) |
169 | 168 |
|
@@ -199,3 +198,40 @@ def get_error_message(self) -> str: |
199 | 198 | 'uppercase Latin letter(s).' |
200 | 199 | ), |
201 | 200 | ) |
| 201 | + |
| 202 | + |
| 203 | +class ASCIIOnlyPasswordValidator: |
| 204 | + """ |
| 205 | + Validates that password contains only ASCII characters |
| 206 | +
|
| 207 | + Example: |
| 208 | + - Valid: 'Passw0rd!123' |
| 209 | + - Invalid: 'Pässwörd§123' |
| 210 | + """ |
| 211 | + |
| 212 | + code = 'password_not_only_ascii_characters' |
| 213 | + |
| 214 | + def validate(self, password, user=None) -> bool: |
| 215 | + try: |
| 216 | + password.encode('ascii', errors='strict') |
| 217 | + except UnicodeEncodeError: |
| 218 | + raise django.core.exceptions.ValidationError( |
| 219 | + _('Password contains non-ASCII characters'), |
| 220 | + code=self.code, |
| 221 | + ) |
| 222 | + |
| 223 | + def get_help_text(self) -> str: |
| 224 | + return _( |
| 225 | + ( |
| 226 | + 'Your password must contain only standard English letters, ' |
| 227 | + 'digits and punctuation symbols (ASCII character set)' |
| 228 | + ), |
| 229 | + ) |
| 230 | + |
| 231 | + def get_error_message(self) -> str: |
| 232 | + return _( |
| 233 | + ( |
| 234 | + 'Your password must contain only standard English letters, ' |
| 235 | + 'digits and punctuation symbols (ASCII character set)' |
| 236 | + ), |
| 237 | + ) |
0 commit comments