from __future__ import annotations from datetime import UTC, datetime, timedelta from sqlalchemy import delete, or_ from app.core.database import session_scope from app.modules.auth.models import EmailVerificationToken, PasswordResetToken, RefreshToken def cleanup_expired_tokens(retention_days: int = 30) -> dict[str, int]: now = datetime.now(UTC) revoked_cutoff = now - timedelta(days=retention_days) with session_scope() as db: refresh_deleted = db.execute( delete(RefreshToken).where( or_( RefreshToken.expires_at < now, RefreshToken.revoked_at.is_not(None) & (RefreshToken.revoked_at < revoked_cutoff), ) ) ).rowcount or 0 reset_deleted = db.execute( delete(PasswordResetToken).where( or_( PasswordResetToken.expires_at < now, PasswordResetToken.used_at.is_not(None) & (PasswordResetToken.used_at < now), ) ) ).rowcount or 0 verify_deleted = db.execute( delete(EmailVerificationToken).where( or_( EmailVerificationToken.expires_at < now, EmailVerificationToken.used_at.is_not(None) & (EmailVerificationToken.used_at < now), ) ) ).rowcount or 0 return { "refresh_tokens_deleted": int(refresh_deleted), "password_reset_tokens_deleted": int(reset_deleted), "email_verification_tokens_deleted": int(verify_deleted), }