Spaces:
Running
Running
| """ | |
| Shared password strength validation for registration and password updates. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| MIN_PASSWORD_LENGTH = 8 | |
| SPECIAL_CHAR_PATTERN = re.compile(r'[!@#$%^&*(),.?":{}|<>\-_=+\[\]\\;/\'`~]') | |
| COMMON_PASSWORDS = frozenset( | |
| { | |
| "123456", | |
| "1234567", | |
| "12345678", | |
| "123456789", | |
| "1234567890", | |
| "12345", | |
| "1234", | |
| "123123", | |
| "111111", | |
| "000000", | |
| "password", | |
| "password1", | |
| "password123", | |
| "passw0rd", | |
| "qwerty", | |
| "qwerty123", | |
| "qwertyuiop", | |
| "abc123", | |
| "admin", | |
| "admin123", | |
| "letmein", | |
| "welcome", | |
| "welcome1", | |
| "monkey", | |
| "dragon", | |
| "master", | |
| "login", | |
| "shadow", | |
| "sunshine", | |
| "princess", | |
| "football", | |
| "baseball", | |
| "iloveyou", | |
| "trustno1", | |
| "superman", | |
| "batman", | |
| "access", | |
| "hello", | |
| "charlie", | |
| "donald", | |
| "mustang", | |
| "696969", | |
| "654321", | |
| "987654321", | |
| "qazwsx", | |
| "asdfgh", | |
| "zxcvbnm", | |
| "1q2w3e4r", | |
| "1qaz2wsx", | |
| "aa123456", | |
| "p@ssw0rd", | |
| "changeme", | |
| "secret", | |
| "test123", | |
| "guest", | |
| "root", | |
| "toor", | |
| } | |
| ) | |
| def validate_password(password: str) -> None: | |
| """ | |
| Validate password strength. Raises ValueError with a user-friendly message | |
| when the password does not meet requirements. | |
| """ | |
| errors: list[str] = [] | |
| if len(password) < MIN_PASSWORD_LENGTH: | |
| errors.append("Password must be at least 8 characters long") | |
| if not re.search(r"[A-Z]", password): | |
| errors.append("Password must contain at least one uppercase letter") | |
| if not re.search(r"[a-z]", password): | |
| errors.append("Password must contain at least one lowercase letter") | |
| if not re.search(r"\d", password): | |
| errors.append("Password must contain at least one number") | |
| if not SPECIAL_CHAR_PATTERN.search(password): | |
| errors.append("Password must contain at least one special character") | |
| normalized = password.strip().lower() | |
| if normalized in COMMON_PASSWORDS or password in COMMON_PASSWORDS: | |
| errors.append("This password is too common. Please choose a stronger one") | |
| if errors: | |
| raise ValueError("; ".join(errors)) | |