1
0
forked from wrenn/wrenn

Fix API key cleanup on user deactivation and build archive race condition

Delete all API keys created by a user when their account is disabled,
deleted, or soft-deleted. Store build archives before enqueuing to Redis
so workers never dequeue a build with missing files.
This commit is contained in:
2026-04-16 05:29:02 +06:00
parent 451d0819cc
commit e91109d69c
5 changed files with 28 additions and 6 deletions

View File

@ -25,6 +25,15 @@ func (q *Queries) DeleteAPIKey(ctx context.Context, arg DeleteAPIKeyParams) erro
return err
}
const deleteAPIKeysByCreator = `-- name: DeleteAPIKeysByCreator :exec
DELETE FROM team_api_keys WHERE created_by = $1
`
func (q *Queries) DeleteAPIKeysByCreator(ctx context.Context, createdBy pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteAPIKeysByCreator, createdBy)
return err
}
const deleteAPIKeysByTeam = `-- name: DeleteAPIKeysByTeam :exec
DELETE FROM team_api_keys WHERE team_id = $1
`

View File

@ -139,16 +139,16 @@ func (s *BuildService) Create(ctx context.Context, p BuildCreateParams) (db.Temp
return db.TemplateBuild{}, fmt.Errorf("insert build: %w", err)
}
// Enqueue build ID (as formatted string) to Redis for workers to pick up.
if err := s.Redis.RPush(ctx, buildQueueKey, buildIDStr).Err(); err != nil {
return db.TemplateBuild{}, fmt.Errorf("enqueue build: %w", err)
}
// Store archive for the worker if provided.
// Store archive before enqueue so the worker never dequeues without files.
if len(p.Archive) > 0 {
s.storeArchive(buildIDStr, p.Archive)
}
if err := s.Redis.RPush(ctx, buildQueueKey, buildIDStr).Err(); err != nil {
s.takeArchive(buildIDStr) // clean up on enqueue failure
return db.TemplateBuild{}, fmt.Errorf("enqueue build: %w", err)
}
return build, nil
}

View File

@ -3,6 +3,7 @@ package service
import (
"context"
"fmt"
"log/slog"
"time"
"github.com/jackc/pgx/v5/pgtype"
@ -66,5 +67,10 @@ func (s *UserService) SetUserStatus(ctx context.Context, userID pgtype.UUID, sta
}); err != nil {
return fmt.Errorf("set user status: %w", err)
}
if status == "disabled" || status == "deleted" {
if err := s.DB.DeleteAPIKeysByCreator(ctx, userID); err != nil {
slog.Warn("failed to delete API keys for deactivated user", "user_id", userID, "error", err)
}
}
return nil
}