|
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