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

1""" 

2This module contains custom Django password validators. 

3 

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""" 

11 

12from django.core.exceptions import ValidationError 

13from django.utils.translation import gettext as _ 

14 

15from src.accounts.constants import UserErrorMessages 

16 

17 

18class DigitRequiredValidator: 

19 """ 

20 Validate that the password contains at least one digit. 

21 

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 """ 

26 

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 ) 

32 

33 def get_error_message(self): 

34 

35 return _(UserErrorMessages.PASSWORD_NO_DIGIT) 

36 

37 def get_help_text(self): 

38 

39 return _(UserErrorMessages.PASSWORD_NO_DIGIT) 

40 

41 

42class UpperCaseLetterRequiredValidator: 

43 """ 

44 Password validator that requires at least one uppercase letter. 

45 

46 This validator ensures that passwords contain at least one uppercase 

47 letter (A-Z). 

48 """ 

49 

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 ) 

55 

56 def get_error_message(self): 

57 

58 return _(UserErrorMessages.PASSWORD_NO_UPPER_CASE_LETTER) 

59 

60 def get_help_text(self): 

61 

62 return _(UserErrorMessages.PASSWORD_NO_UPPER_CASE_LETTER) 

63 

64 

65class LowerCaseLetterRequiredValidator: 

66 """ 

67 Password validator that requires at least one lowercase letter. 

68 

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 """ 

73 

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 ) 

79 

80 def get_error_message(self): 

81 

82 return _(UserErrorMessages.PASSWORD_NO_LOWER_CASE_LETTER) 

83 

84 def get_help_text(self): 

85 

86 return _(UserErrorMessages.PASSWORD_NO_LOWER_CASE_LETTER) 

87 

88 

89class NoWhiteSpacesRequiredValidator: 

90 """ 

91 Password validator that prevents whitespace characters. 

92 

93 This validator ensures that passwords don't contain any whitespace 

94 characters. 

95 """ 

96 

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 ) 

102 

103 def get_error_message(self): 

104 

105 return _(UserErrorMessages.PASSWORD_NO_WHITE_SPACES) 

106 

107 def get_help_text(self): 

108 

109 return _(UserErrorMessages.PASSWORD_NO_WHITE_SPACES) 

110 

111 

112class SpecialCharRequiredValidator: 

113 """ 

114 Password validator that requires at least one special character. 

115 

116 This validator ensures that passwords contain at least one special 

117 character from the set: !#$%. 

118 """ 

119 

120 def validate(self, password, user=None): 

121 special_chars = '!#$%' 

122 

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 ) 

127 

128 def get_error_message(self): 

129 

130 return _(UserErrorMessages.PASSWORD_NO_SPECIAL_CHAR) 

131 

132 def get_help_text(self): 

133 

134 return _(UserErrorMessages.PASSWORD_NO_SPECIAL_CHAR)