import uuid from datetime import datetime, timezone from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.models.refresh_token import RefreshToken async def create( db: AsyncSession, user_id: uuid.UUID, token_hash: str, expires_at: datetime, ) -> RefreshToken: rt = RefreshToken(user_id=user_id, token_hash=token_hash, expires_at=expires_at) db.add(rt) await db.commit() await db.refresh(rt) return rt async def get_by_hash(db: AsyncSession, token_hash: str) -> RefreshToken | None: result = await db.execute( select(RefreshToken).where(RefreshToken.token_hash == token_hash) ) return result.scalar_one_or_none() async def revoke(db: AsyncSession, rt: RefreshToken) -> None: rt.revoked = True await db.commit() def is_valid(rt: RefreshToken) -> bool: if rt.revoked: return False now = datetime.now(timezone.utc) expires = rt.expires_at # SQLite returns naive datetimes; normalise to UTC-aware for comparison if expires.tzinfo is None: expires = expires.replace(tzinfo=timezone.utc) return expires > now