from jose import jwt, JOSEError from pydantic import BaseModel from datetime import timedelta, datetime from typing import ClassVar, Literal import logging from ..settings import settings from ..exc import Unauthorized class Token(BaseModel): token_type: str exp: datetime sub: int secret_key: ClassVar[str] expire_delta: ClassVar[timedelta] @classmethod def calculate_exp(cls, now: datetime) -> datetime: return now + cls.expire_delta @classmethod def decode(cls, jwt_token: str | bytes) -> "Token": try: data = jwt.decode( jwt_token, cls.secret_key, algorithms=[settings.ALGORITHM] ) except JOSEError as e: logging.error(e) raise Unauthorized() return cls(**data) def encode(self) -> str: data = self.model_dump() data["sub"] = str(data["sub"]) return jwt.encode(data, self.secret_key, settings.ALGORITHM) class AccessToken(Token): token_type: Literal["access"] = "access" secret_key = settings.SECRET_KEY expire_delta = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) class RefreshToken(Token): token_type: Literal["refresh"] = "refresh" secret_key = settings.REFRESH_SECRET_KEY expire_delta = timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS)