from __future__ import annotations import datetime as dt from typing import Optional import jwt from passlib.context import CryptContext from .settings import settings pwd_context = CryptContext(schemes=["pbkdf2_sha256"], deprecated="auto") def hash_password(password: str) -> str: return pwd_context.hash(password) def verify_password(password: str, password_hash: str) -> bool: return pwd_context.verify(password, password_hash) def create_token(user_id: int, username: str) -> str: now = dt.datetime.now(dt.timezone.utc) payload = { "sub": str(user_id), "username": username, "exp": now + dt.timedelta(hours=settings.jwt_exp_hours), } return jwt.encode(payload, settings.jwt_secret, algorithm=settings.jwt_algorithm) def decode_token(token: str) -> dict: return jwt.decode(token, settings.jwt_secret, algorithms=[settings.jwt_algorithm]) def get_token_subject(token: str) -> Optional[int]: try: payload = decode_token(token) except jwt.PyJWTError: return None sub = payload.get("sub") if not sub: return None try: return int(sub) except ValueError: return None