Skip to content

Commit 5214525

Browse files
jonradoffclaude
andcommitted
Fix CI failures: test isolation, collection limit, APIDeleteAPIKey auth
- Drop collections (not just delete documents) in test cleanup — prevents duplicate key errors on MigrateToMultiUser and stops Atlas collection accumulation that hit the 500-collection free-tier limit - Add middleware.InjectAPIUser helper for injecting auth context in tests - Update TestAPIDeleteAPIKey to inject admin user context (delete requires auth) - Drop 27 stale collections from abandoned test databases on Atlas Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c3e8713 commit 5214525

3 files changed

Lines changed: 21 additions & 5 deletions

File tree

internal/handlers/api_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import (
77
"strings"
88
"testing"
99

10+
"lightcms/internal/auth"
11+
"lightcms/internal/middleware"
12+
1013
"github.com/gorilla/mux"
1114
)
1215

@@ -522,10 +525,14 @@ func TestAPIDeleteAPIKey(t *testing.T) {
522525
ah, _, cleanup := newTestAPIHandler(t)
523526
defer cleanup()
524527

525-
// Create first
528+
// Inject an admin user so the delete handler can determine key ownership
529+
adminUser := &auth.SessionUser{ID: "000000000000000000000001", Email: "admin@test", Role: "admin"}
530+
531+
// Create first (as admin)
526532
createRR := httptest.NewRecorder()
527533
createReq := httptest.NewRequest(http.MethodPost, "/api/v1/api-keys", strings.NewReader(`{"name":"del-key"}`))
528534
createReq.Header.Set("Content-Type", "application/json")
535+
createReq = createReq.WithContext(middleware.InjectAPIUser(createReq.Context(), adminUser))
529536
ah.APICreateAPIKey(createRR, createReq)
530537

531538
var created map[string]interface{}
@@ -540,6 +547,7 @@ func TestAPIDeleteAPIKey(t *testing.T) {
540547

541548
rr := httptest.NewRecorder()
542549
req := httptest.NewRequest(http.MethodDelete, "/api/v1/api-keys/"+id, nil)
550+
req = req.WithContext(middleware.InjectAPIUser(req.Context(), adminUser))
543551
router.ServeHTTP(rr, req)
544552

545553
if rr.Code != http.StatusOK {

internal/handlers/testhelper_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,11 @@ func testDB(t *testing.T) *database.DB {
8989
return sharedTestDB
9090
}
9191

92-
// cleanupCollections removes all documents from test collections for isolation.
93-
// Deletes are issued in parallel to minimise Atlas round-trip overhead.
92+
// cleanupCollections drops test collections for isolation.
93+
// Dropping (rather than just deleting documents) ensures indexes are also cleared,
94+
// preventing duplicate key errors on re-creation and avoiding Atlas collection
95+
// accumulation when tests use unique indexes (e.g. users.email).
96+
// Drops are issued in parallel to minimise Atlas round-trip overhead.
9497
func cleanupCollections(t *testing.T, db *database.DB) {
9598
t.Helper()
9699
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
@@ -102,13 +105,12 @@ func cleanupCollections(t *testing.T, db *database.DB) {
102105
"snippets", "users", "audit_logs", "contact_messages", "login_attempts",
103106
"oauth_clients", "user_activity",
104107
}
105-
empty := bson.M{}
106108
var wg sync.WaitGroup
107109
for _, name := range collections {
108110
wg.Add(1)
109111
go func(col string) {
110112
defer wg.Done()
111-
db.Collection(col).DeleteMany(ctx, empty)
113+
db.Collection(col).Drop(ctx) //nolint:errcheck
112114
}(name)
113115
}
114116
wg.Wait()

internal/middleware/apiauth.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ func APIUserFromContext(ctx context.Context) (interface{}, bool) {
2929
return user, user != nil
3030
}
3131

32+
// InjectAPIUser returns a context with the given user injected as the API user.
33+
// Intended for use in tests only.
34+
func InjectAPIUser(ctx context.Context, user interface{}) context.Context {
35+
return context.WithValue(ctx, apiUserContextKey, user)
36+
}
37+
3238
// SessionValidateFunc validates a session cookie and returns the authenticated user (as interface{}).
3339
// It receives the full HTTP request so it can read cookies.
3440
type SessionValidateFunc func(r *http.Request) interface{}

0 commit comments

Comments
 (0)