from datetime import datetime, timedelta, timezone from secrets import token_urlsafe from jose import JWTError, jwt from passlib.context import CryptContext from app.config.settings import settings pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") def hash_password(password: str) -> str: return pwd_context.hash(password) def verify_password(password: str, hashed_password: str) -> bool: return pwd_context.verify(password, hashed_password) def _create_token(subject: str, token_type: str, expires_delta: timedelta) -> str: expire = datetime.now(timezone.utc) + expires_delta payload = {"sub": subject, "type": token_type, "exp": expire} return jwt.encode(payload, settings.secret_key, algorithm=settings.jwt_algorithm) def create_access_token(subject: str) -> str: return _create_token( subject=subject, token_type="access", expires_delta=timedelta(minutes=settings.access_token_expire_minutes), ) def create_refresh_token(subject: str) -> str: return _create_token( subject=subject, token_type="refresh", expires_delta=timedelta(days=settings.refresh_token_expire_days), ) def decode_token(token: str) -> dict: try: return jwt.decode(token, settings.secret_key, algorithms=[settings.jwt_algorithm]) except JWTError as exc: raise ValueError("Invalid token") from exc def generate_random_token() -> str: return token_urlsafe(48)