Initial commit: site monorepo with API, web, and infra.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
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),
|
||||
}
|
||||
Reference in New Issue
Block a user