refactor(auth): wrap JWT operations in transactions and migrate to clock.Now()

Wrap JTI revocation, cleanup, refresh token generation, and verification in explicit DB transactions with Begin/defer Rollback/Commit. Replace time.Now() with clock.Now() for testability.

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-06-24 23:43:07 +01:00
co-authored by Sisyphus
parent da0e64c02b
commit e95b1a65af
2 changed files with 65 additions and 11 deletions
+6 -5
View File
@@ -18,6 +18,7 @@ import (
"testing"
"time"
"crussell/clock"
"crussell/testutils/testtx"
)
@@ -160,7 +161,7 @@ func TestVerifyToken_RevokedJTI(t *testing.T) {
t.Fatalf("GenerateToken() failed: %v", err)
}
RevokeJTI(ctx, jti, time.Now().Add(30*24*time.Hour))
RevokeJTI(ctx, jti, clock.Now().Add(30*24*time.Hour))
_, _, _, err = VerifyToken(token, ctx)
if err == nil {
@@ -178,7 +179,7 @@ func TestVerifyToken_MissingJTI(t *testing.T) {
_, tokenString, err := TokenAuth.Encode(map[string]interface{}{
"user_id": "user-005",
"role": "verified_email",
"exp": time.Now().Add(30 * 24 * time.Hour).Unix(),
"exp": clock.Now().Add(30 * 24 * time.Hour).Unix(),
})
if err != nil {
t.Fatalf("failed to create token without JTI: %v", err)
@@ -210,7 +211,7 @@ func TestRevokeJTI_AddsToSet(t *testing.T) {
t.Fatal("JTI should not be revoked before calling RevokeJTI")
}
RevokeJTI(ctx, jti, time.Now().Add(30*24*time.Hour))
RevokeJTI(ctx, jti, clock.Now().Add(30*24*time.Hour))
if !IsJTIRevoked(ctx, jti) {
t.Error("expected IsJTIRevoked to return true after RevokeJTI")
@@ -240,7 +241,7 @@ func TestCleanupRevokedJTIs_RemovesExpired(t *testing.T) {
}
// Add with future expiry so IsJTIRevoked sees it
RevokeJTI(ctx, jti, time.Now().Add(1*time.Hour))
RevokeJTI(ctx, jti, clock.Now().Add(1*time.Hour))
if !IsJTIRevoked(ctx, jti) {
t.Fatal("JTI should be in revoked set after RevokeJTI")
@@ -270,7 +271,7 @@ func TestCleanupRevokedJTIs_KeepsValid(t *testing.T) {
}
// Add with future expiry
RevokeJTI(ctx, jti, time.Now().Add(30*24*time.Hour))
RevokeJTI(ctx, jti, clock.Now().Add(30*24*time.Hour))
if !IsJTIRevoked(ctx, jti) {
t.Fatal("JTI should be in revoked set before cleanup")