from datetime import datetime, timedelta, timezone from uuid import UUID import jwt from argon2 import PasswordHasher from argon2.exceptions import VerifyMismatchError from app.core.config import get_settings _hasher = PasswordHasher() def hash_password(password: str) -> str: return _hasher.hash(password) def verify_password(password: str, hashed: str) -> bool: try: return _hasher.verify(hashed, password) except VerifyMismatchError: return False def create_access_token(user_id: UUID) -> str: settings = get_settings() expires_at = datetime.now(timezone.utc) + timedelta(minutes=settings.jwt_expire_minutes) payload = {"sub": str(user_id), "exp": expires_at} return jwt.encode(payload, settings.jwt_secret_key, algorithm=settings.jwt_algorithm) def decode_access_token(token: str) -> UUID | None: settings = get_settings() try: payload = jwt.decode(token, settings.jwt_secret_key, algorithms=[settings.jwt_algorithm]) except jwt.InvalidTokenError: return None subject = payload.get("sub") if subject is None: return None return UUID(subject)