Coverage for src/accounts/validators/password.py: 52%
44 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-08-04 12:59 +0300
« prev ^ index » next coverage.py v7.9.2, created at 2025-08-04 12:59 +0300
1"""
2This module contains custom Django password validators.
4Validators included:
5- DigitRequiredValidator: Ensures password contains at least one digit
6- UpperCaseLetterRequiredValidator: Ensures password contains uppercase letters
7- LowerCaseLetterRequiredValidator: Ensures password contains lowercase letters
8- NoWhiteSpacesRequiredValidator: Prevents whitespace in passwords
9- SpecialCharRequiredValidator: Ensures password contains special characters
10"""
12from django.core.exceptions import ValidationError
13from django.utils.translation import gettext as _
15from src.accounts.constants import UserErrorMessages
18class DigitRequiredValidator:
19 """
20 Validate that the password contains at least one digit.
22 This method is called by Django's password validation system
23 when a user sets or changes their password. It checks if the
24 password contains at least one numeric character.
25 """
27 def validate(self, password, user=None):
28 if not any(char.isdigit() for char in password):
29 raise ValidationError(
30 self.get_error_message(), code='password_no_digit'
31 )
33 def get_error_message(self):
35 return _(UserErrorMessages.PASSWORD_NO_DIGIT)
37 def get_help_text(self):
39 return _(UserErrorMessages.PASSWORD_NO_DIGIT)
42class UpperCaseLetterRequiredValidator:
43 """
44 Password validator that requires at least one uppercase letter.
46 This validator ensures that passwords contain at least one uppercase
47 letter (A-Z).
48 """
50 def validate(self, password, user=None):
51 if not any(char.isupper() for char in password):
52 raise ValidationError(
53 self.get_error_message(), code='password_no_upper_case_letter'
54 )
56 def get_error_message(self):
58 return _(UserErrorMessages.PASSWORD_NO_UPPER_CASE_LETTER)
60 def get_help_text(self):
62 return _(UserErrorMessages.PASSWORD_NO_UPPER_CASE_LETTER)
65class LowerCaseLetterRequiredValidator:
66 """
67 Password validator that requires at least one lowercase letter.
69 This validator ensures that passwords contain at least one lowercase
70 letter (a-z). This is a common security requirement that makes
71 passwords harder to guess or crack.
72 """
74 def validate(self, password, user=None):
75 if not any(char.islower() for char in password):
76 raise ValidationError(
77 self.get_error_message(), code='password_no_lower_case_letter'
78 )
80 def get_error_message(self):
82 return _(UserErrorMessages.PASSWORD_NO_LOWER_CASE_LETTER)
84 def get_help_text(self):
86 return _(UserErrorMessages.PASSWORD_NO_LOWER_CASE_LETTER)
89class NoWhiteSpacesRequiredValidator:
90 """
91 Password validator that prevents whitespace characters.
93 This validator ensures that passwords don't contain any whitespace
94 characters.
95 """
97 def validate(self, password, user=None):
98 if any(char.isspace() for char in password):
99 raise ValidationError(
100 self.get_error_message(), code='password_no_white_spaces'
101 )
103 def get_error_message(self):
105 return _(UserErrorMessages.PASSWORD_NO_WHITE_SPACES)
107 def get_help_text(self):
109 return _(UserErrorMessages.PASSWORD_NO_WHITE_SPACES)
112class SpecialCharRequiredValidator:
113 """
114 Password validator that requires at least one special character.
116 This validator ensures that passwords contain at least one special
117 character from the set: !#$%.
118 """
120 def validate(self, password, user=None):
121 special_chars = '!#$%'
123 if not any(char in special_chars for char in password):
124 raise ValidationError(
125 self.get_error_message(), code='password_no_special_char'
126 )
128 def get_error_message(self):
130 return _(UserErrorMessages.PASSWORD_NO_SPECIAL_CHAR)
132 def get_help_text(self):
134 return _(UserErrorMessages.PASSWORD_NO_SPECIAL_CHAR)