|
1 | 1 | import re
|
| 2 | +from typing import List, Optional |
2 | 3 |
|
3 | 4 | from sanatio.base_class import BaseValidator
|
4 | 5 |
|
5 | 6 |
|
6 | 7 | class PasswordValidator(BaseValidator):
|
7 | 8 |
|
8 |
| - def isStrongPassword(self, value: str, |
9 |
| - min_length: int = 8, |
10 |
| - special_chars: bool = True, |
11 |
| - numbers: bool = True, |
12 |
| - uppercase: bool = True, |
13 |
| - lowercase: bool = True) -> bool: |
14 |
| - """ check if the string is strong password or not |
15 |
| -
|
16 |
| - requirements: |
17 |
| - 1. At least 8 characters long |
18 |
| - 2. At least one uppercase letter |
19 |
| - 3. At least one lowercase letter |
20 |
| - 4. At least one number |
21 |
| - 5. At least one special character |
| 9 | + def is_strong_password(self, value: str, |
| 10 | + min_length: int = 8, |
| 11 | + special_chars: bool = True, |
| 12 | + numbers: bool = True, |
| 13 | + uppercase: bool = True, |
| 14 | + lowercase: bool = True) -> bool: |
| 15 | + """Check if the string is a strong password. |
| 16 | +
|
| 17 | + Requirements: |
| 18 | + 1. At least `min_length` characters |
| 19 | + 2. At least one uppercase letter (optional) |
| 20 | + 3. At least one lowercase letter (optional) |
| 21 | + 4. At least one number (optional) |
| 22 | + 5. At least one special character (optional) |
22 | 23 | """
|
23 |
| - if not self.isPasswordLength(value, min_length) or \ |
24 |
| - (special_chars and not self.isPasswordSpecialChar(value)) or \ |
25 |
| - (numbers and not self.isPasswordNumber(value)) or \ |
26 |
| - (uppercase and not self.isPasswordUppercase(value)) or \ |
27 |
| - (lowercase and not self.isPasswordLowercase(value)): |
| 24 | + if not self.is_password_length(value, min_length): |
| 25 | + return False |
| 26 | + if special_chars and not self.is_password_special_char(value): |
| 27 | + return False |
| 28 | + if numbers and not self.is_password_number(value): |
| 29 | + return False |
| 30 | + if uppercase and not self.is_password_uppercase(value): |
| 31 | + return False |
| 32 | + if lowercase and not self.is_password_lowercase(value): |
28 | 33 | return False
|
29 | 34 |
|
30 | 35 | return True
|
31 | 36 |
|
32 |
| - def isPasswordUppercase(self, value: str, min_length: int = 1) -> bool: |
33 |
| - """ check if the string has uppercase letters """ |
34 |
| - if len(re.findall(r'[A-Z]', value)) >= min_length: |
35 |
| - return True |
36 |
| - |
37 |
| - def isPasswordLowercase(self, value: str, min_length: int = 1) -> bool: |
38 |
| - """ check if the string has lowercase letters """ |
39 |
| - if len(re.findall(r'[a-z]', value)) >= min_length: |
40 |
| - return True |
41 |
| - |
42 |
| - def isPasswordNumber(self, value: str, min_length: int = 1) -> bool: |
43 |
| - """ check if the string has numbers """ |
44 |
| - if len(re.findall(r'[0-9]', value)) >= min_length: |
45 |
| - return True |
46 |
| - |
47 |
| - def isPasswordLength(self, value: str, min_length: int = 8) -> bool: |
48 |
| - """ check if the string length is between min and max """ |
49 |
| - if len(value) >= min_length: |
50 |
| - return True |
51 |
| - |
52 |
| - def isPasswordSpecialChar(self, value: str, min_length: int = 1) -> bool: |
53 |
| - """ check if the string has special characters """ |
54 |
| - if len(re.findall(r'[_@$]', value)) >= min_length: |
55 |
| - return True |
56 |
| - |
57 |
| - def isPasswordMatch(self, value: str, match_value: str, ignore_case: bool = False) -> bool: |
58 |
| - """ check if the string matches the match_value """ |
59 |
| - if ignore_case and value.lower() == match_value.lower(): |
60 |
| - return True |
61 |
| - elif value == match_value: |
62 |
| - return True |
63 |
| - |
64 |
| - def isPasswordNotMatch(self, value: str, match_value: str, ignore_case: bool = False) -> bool: |
65 |
| - """ check if the string does not match the match_value """ |
66 |
| - if ignore_case and value.lower() != match_value.lower(): |
67 |
| - return True |
68 |
| - elif value != match_value: |
69 |
| - return True |
70 |
| - |
71 |
| - def isPasswordNotInList(self, value: str, list_values: list, ignore_case: bool = False) -> bool: |
72 |
| - """ check if the string is not in the list """ |
73 |
| - if ignore_case and value.lower() not in [x.lower() for x in list_values]: |
74 |
| - return True |
75 |
| - elif value not in list_values: |
76 |
| - return True |
77 |
| - |
78 |
| - def isPasswordNotInFile(self, value: str, file_path: str, ignore_case: bool = False) -> bool: |
79 |
| - """ check if the string is not in the file """ |
| 37 | + def is_password_uppercase(self, value: str, min_length: int = 1) -> bool: |
| 38 | + """Check if the string has at least `min_length` uppercase letters.""" |
| 39 | + return len(re.findall(r'[A-Z]', value)) >= min_length |
| 40 | + |
| 41 | + def is_password_lowercase(self, value: str, min_length: int = 1) -> bool: |
| 42 | + """Check if the string has at least `min_length` lowercase letters.""" |
| 43 | + return len(re.findall(r'[a-z]', value)) >= min_length |
| 44 | + |
| 45 | + def is_password_number(self, value: str, min_length: int = 1) -> bool: |
| 46 | + """Check if the string has at least `min_length` digits.""" |
| 47 | + return len(re.findall(r'\d', value)) >= min_length |
| 48 | + |
| 49 | + def is_password_length(self, value: str, min_length: int = 8) -> bool: |
| 50 | + """Check if the string is at least `min_length` characters long.""" |
| 51 | + return len(value) >= min_length |
| 52 | + |
| 53 | + def is_password_special_char(self, value: str, min_length: int = 1) -> bool: |
| 54 | + """Check if the string has at least `min_length` special characters.""" |
| 55 | + # Common special characters set: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ |
| 56 | + return len(re.findall(r'[^a-zA-Z0-9]', value)) >= min_length |
| 57 | + |
| 58 | + def is_password_match(self, value: str, match_value: str, ignore_case: bool = False) -> bool: |
| 59 | + """Check if the password matches `match_value`.""" |
| 60 | + if ignore_case: |
| 61 | + return value.lower() == match_value.lower() |
| 62 | + return value == match_value |
| 63 | + |
| 64 | + def is_password_not_match(self, value: str, match_value: str, ignore_case: bool = False) -> bool: |
| 65 | + """Check if the password does not match `match_value`.""" |
| 66 | + if ignore_case: |
| 67 | + return value.lower() != match_value.lower() |
| 68 | + return value != match_value |
| 69 | + |
| 70 | + def is_password_not_in_list(self, value: str, list_values: Optional[List[str]] = None, |
| 71 | + ignore_case: bool = False) -> bool: |
| 72 | + """Check if the password is not in a list of disallowed passwords.""" |
| 73 | + if list_values is None: |
| 74 | + list_values = [] |
| 75 | + |
| 76 | + if ignore_case: |
| 77 | + return value.lower() not in [x.lower() for x in list_values] |
| 78 | + return value not in list_values |
| 79 | + |
| 80 | + def is_password_not_in_file(self, value: str, file_path: str, ignore_case: bool = False) -> bool: |
| 81 | + """Check if the password is not in a file of disallowed passwords.""" |
| 82 | + if not hasattr(self, "read_file"): |
| 83 | + raise NotImplementedError("read_file() method not implemented in BaseValidator or subclass.") |
| 84 | + |
80 | 85 | data = self.read_file(file_path, split_lines=True)
|
81 | 86 |
|
82 |
| - if ignore_case and value.lower() not in [x.lower() for x in data]: |
83 |
| - return True |
84 |
| - elif value not in data: |
85 |
| - return True |
| 87 | + if ignore_case: |
| 88 | + return value.lower() not in [x.lower() for x in data] |
| 89 | + return value not in data |
0 commit comments