40 lines
1.3 KiB
Python
40 lines
1.3 KiB
Python
"""
|
|
forms.py
|
|
Shared form utilities and password strength validator.
|
|
Per-module WTForms classes live in their respective blueprint directories.
|
|
"""
|
|
|
|
import re
|
|
|
|
|
|
_PASSWORD_MIN_LENGTH = 10
|
|
_HAS_UPPERCASE = re.compile(r"[A-Z]")
|
|
_HAS_LOWERCASE = re.compile(r"[a-z]")
|
|
_HAS_DIGIT = re.compile(r"\d")
|
|
|
|
|
|
def validate_password_strength(password: str, confirm: str = None) -> str | None:
|
|
"""
|
|
Validate password strength per the security policy:
|
|
- Minimum 10 characters
|
|
- Must include at least one uppercase letter
|
|
- Must include at least one lowercase letter
|
|
- Must include at least one digit
|
|
|
|
Returns an error string, or None if the password is acceptable.
|
|
If confirm is supplied, also checks they match.
|
|
"""
|
|
if not password:
|
|
return "Password is required."
|
|
if len(password) < _PASSWORD_MIN_LENGTH:
|
|
return f"Password must be at least {_PASSWORD_MIN_LENGTH} characters."
|
|
if not _HAS_UPPERCASE.search(password):
|
|
return "Password must include at least one uppercase letter."
|
|
if not _HAS_LOWERCASE.search(password):
|
|
return "Password must include at least one lowercase letter."
|
|
if not _HAS_DIGIT.search(password):
|
|
return "Password must include at least one digit."
|
|
if confirm is not None and password != confirm:
|
|
return "Passwords do not match."
|
|
return None
|