- Introduced `lint` and `lint-fix` applications in `flake.nix` for unified linting of backend (Python) and frontend (TypeScript/Svelte) code. - Added `scripts/lint.sh` for manual linting execution. - Created `scripts/install-hooks.sh` to set up git hooks for automatic linting before commits and optional tests before pushes. - Updated `README.md` with instructions for using the new linting features and git hooks.
67 lines
1.7 KiB
Python
67 lines
1.7 KiB
Python
"""Password hashing utilities using passlib."""
|
|
|
|
import re
|
|
|
|
from passlib.context import CryptContext
|
|
|
|
# Create password context for hashing and verification
|
|
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
|
|
|
|
|
def hash_password(password: str) -> str:
|
|
"""
|
|
Hash a password using bcrypt.
|
|
|
|
Args:
|
|
password: Plain text password
|
|
|
|
Returns:
|
|
Hashed password string
|
|
"""
|
|
return pwd_context.hash(password)
|
|
|
|
|
|
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
|
"""
|
|
Verify a plain password against a hashed password.
|
|
|
|
Args:
|
|
plain_password: Plain text password to verify
|
|
hashed_password: Hashed password from database
|
|
|
|
Returns:
|
|
True if password matches, False otherwise
|
|
"""
|
|
return pwd_context.verify(plain_password, hashed_password)
|
|
|
|
|
|
def validate_password_strength(password: str) -> tuple[bool, str]:
|
|
"""
|
|
Validate password meets complexity requirements.
|
|
|
|
Requirements:
|
|
- At least 8 characters
|
|
- At least 1 uppercase letter
|
|
- At least 1 lowercase letter
|
|
- At least 1 number
|
|
|
|
Args:
|
|
password: Plain text password to validate
|
|
|
|
Returns:
|
|
Tuple of (is_valid, error_message)
|
|
"""
|
|
if len(password) < 8:
|
|
return False, "Password must be at least 8 characters long"
|
|
|
|
if not re.search(r"[A-Z]", password):
|
|
return False, "Password must contain at least one uppercase letter"
|
|
|
|
if not re.search(r"[a-z]", password):
|
|
return False, "Password must contain at least one lowercase letter"
|
|
|
|
if not re.search(r"\d", password):
|
|
return False, "Password must contain at least one number"
|
|
|
|
return True, ""
|