44 lines
1.6 KiB
Python
44 lines
1.6 KiB
Python
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),
|
|
}
|