refactor: move auth, GDPR, and booking cleanup to centralized scheduler

Convert CleanupRevokedJTIs to return (int, error) and remove StartJTICleanup goroutine. Add CleanupStaleLoginEntries and CleanupGDPRExportCache for centralized scheduler. Add clock.London timezone location.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-07-07 00:10:00 +01:00
co-authored by Sisyphus
parent a4fa75154d
commit e86248b27c
7 changed files with 276 additions and 79 deletions
+16 -30
View File
@@ -8,8 +8,9 @@ import (
"log"
"time"
"crussell/db"
"crussell/clock"
"crussell/db"
"github.com/jackc/pgx/v5"
"github.com/go-chi/jwtauth/v5"
@@ -43,7 +44,7 @@ func RevokeJTI(ctx context.Context, jti string, expiresAt time.Time) {
}
tx, err := db.Conn.Begin(ctx)
if err != nil {
fmt.Printf("WARN: Failed to begin transaction for JTI revocation: %v\n", err)
log.Printf("WARN: Failed to begin transaction for JTI revocation: %v", err)
return
}
defer tx.Rollback(ctx)
@@ -54,12 +55,12 @@ func RevokeJTI(ctx context.Context, jti string, expiresAt time.Time) {
jti, expiresAt)
if err != nil {
// Log but don't fail - this is best effort
fmt.Printf("WARN: Failed to revoke JTI %s: %v\n", jti, err)
log.Printf("WARN: Failed to revoke JTI %s: %v", jti, err)
return
}
if err := tx.Commit(ctx); err != nil {
fmt.Printf("WARN: Failed to commit transaction for JTI revocation: %v\n", err)
log.Printf("WARN: Failed to commit transaction for JTI revocation: %v", err)
}
}
@@ -81,46 +82,31 @@ func IsJTIRevoked(ctx context.Context, jti string) bool {
return exists
}
// CleanupRevokedJTIs removes expired entries from PostgreSQL
func CleanupRevokedJTIs(ctx context.Context) {
// CleanupRevokedJTIs removes expired entries from PostgreSQL and returns the count of deleted rows.
func CleanupRevokedJTIs(ctx context.Context) (int, error) {
if db.Conn == nil {
return
return 0, nil
}
tx, err := db.Conn.Begin(ctx)
if err != nil {
fmt.Printf("WARN: Failed to begin transaction for JTI cleanup: %v\n", err)
return
log.Printf("WARN: Failed to begin transaction for JTI cleanup: %v", err)
return 0, err
}
defer tx.Rollback(ctx)
_, err = tx.Exec(ctx,
tag, err := tx.Exec(ctx,
`DELETE FROM revoked_jtis WHERE expires_at < NOW()`)
if err != nil {
fmt.Printf("WARN: Failed to cleanup revoked JTIs: %v\n", err)
return
log.Printf("WARN: Failed to cleanup revoked JTIs: %v", err)
return 0, err
}
if err := tx.Commit(ctx); err != nil {
fmt.Printf("WARN: Failed to commit transaction for JTI cleanup: %v\n", err)
log.Printf("WARN: Failed to commit transaction for JTI cleanup: %v", err)
return 0, err
}
}
// StartJTICleanup starts a background goroutine to periodically clean expired JTIs
func StartJTICleanup() {
go func() {
ticker := time.NewTicker(30 * time.Minute)
defer ticker.Stop()
for range ticker.C {
func() {
defer func() {
if r := recover(); r != nil {
log.Printf("Panic recovered in JWT cleanup ticker: %v", r)
}
}()
CleanupRevokedJTIs(context.Background())
}()
}
}()
return int(tag.RowsAffected()), nil
}
func InitJWT(secret string) {