From 2de6e4d4a7c64b4d955f270ee82b6283a9cc0176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Rodrigues?= Date: Sat, 13 Jun 2026 12:37:11 +0100 Subject: [PATCH] fix(finance/seed): resolve admin user via MongoDB instead of HTTP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The seeder was calling the users service over HTTP, which fails when services are in different network namespaces or start up concurrently. Both services share the same MongoDB database, so query the "users" collection directly by email — no cross-service dependency. Co-Authored-By: Claude Sonnet 4.6 --- apps/finance/services/api/main/seed.go | 40 +++++++++----------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/apps/finance/services/api/main/seed.go b/apps/finance/services/api/main/seed.go index a491c80..9a24253 100644 --- a/apps/finance/services/api/main/seed.go +++ b/apps/finance/services/api/main/seed.go @@ -2,25 +2,24 @@ package main import ( "context" - "encoding/json" "fmt" "log/slog" - "net/http" "os" "time" "go.mongodb.org/mongo-driver/v2/bson" ) -// SeedAdmin looks up the admin user by email (via the internal users service) -// and seeds demo data if the account has no existing transactions. +// SeedAdmin looks up the admin user by email directly in the shared MongoDB +// (both services use the same DB) and seeds demo data if the account has no +// existing transactions. func SeedAdmin(ctx context.Context, store *Store) { email := os.Getenv("SEED_USER_EMAIL") if email == "" { email = "admin@homelab.local" } - userID, err := lookupUserByEmail(email) + userID, err := lookupUserByEmailMongo(ctx, store, email) if err != nil { slog.Warn("seed: could not resolve admin user, skipping", "email", email, "err", err) return @@ -42,30 +41,19 @@ func SeedAdmin(ctx context.Context, store *Store) { } } -func lookupUserByEmail(email string) (string, error) { - usersURL := os.Getenv("USERS_SERVICE_URL") - if usersURL == "" { - usersURL = "http://users" +// lookupUserByEmailMongo queries the shared "users" collection directly, +// avoiding any cross-service HTTP dependency. +func lookupUserByEmailMongo(ctx context.Context, store *Store, email string) (string, error) { + coll := store.db.Collection("users") + var result struct { + ID string `bson:"_id"` + Email string `bson:"email"` } - resp, err := http.Get(fmt.Sprintf("%s/admin/users?search=%s", usersURL, email)) + err := coll.FindOne(ctx, bson.M{"email": email}).Decode(&result) if err != nil { - return "", fmt.Errorf("users service unreachable: %w", err) + return "", fmt.Errorf("user %q not found in mongo: %w", email, err) } - defer resp.Body.Close() - - var users []struct { - ID string `json:"id"` - Email string `json:"email"` - } - if err := json.NewDecoder(resp.Body).Decode(&users); err != nil { - return "", fmt.Errorf("decode users response: %w", err) - } - for _, u := range users { - if u.Email == email { - return u.ID, nil - } - } - return "", fmt.Errorf("user %q not found", email) + return result.ID, nil } func seedAll(ctx context.Context, store *Store, userID string) error {