fix(finance/seed): resolve admin user via MongoDB instead of HTTP

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 <noreply@anthropic.com>
This commit is contained in:
Gonçalo Rodrigues 2026-06-13 12:37:11 +01:00
parent 7a2cb10c79
commit 2de6e4d4a7

View File

@ -2,25 +2,24 @@ package main
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"log/slog" "log/slog"
"net/http"
"os" "os"
"time" "time"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
) )
// SeedAdmin looks up the admin user by email (via the internal users service) // SeedAdmin looks up the admin user by email directly in the shared MongoDB
// and seeds demo data if the account has no existing transactions. // (both services use the same DB) and seeds demo data if the account has no
// existing transactions.
func SeedAdmin(ctx context.Context, store *Store) { func SeedAdmin(ctx context.Context, store *Store) {
email := os.Getenv("SEED_USER_EMAIL") email := os.Getenv("SEED_USER_EMAIL")
if email == "" { if email == "" {
email = "admin@homelab.local" email = "admin@homelab.local"
} }
userID, err := lookupUserByEmail(email) userID, err := lookupUserByEmailMongo(ctx, store, email)
if err != nil { if err != nil {
slog.Warn("seed: could not resolve admin user, skipping", "email", email, "err", err) slog.Warn("seed: could not resolve admin user, skipping", "email", email, "err", err)
return return
@ -42,30 +41,19 @@ func SeedAdmin(ctx context.Context, store *Store) {
} }
} }
func lookupUserByEmail(email string) (string, error) { // lookupUserByEmailMongo queries the shared "users" collection directly,
usersURL := os.Getenv("USERS_SERVICE_URL") // avoiding any cross-service HTTP dependency.
if usersURL == "" { func lookupUserByEmailMongo(ctx context.Context, store *Store, email string) (string, error) {
usersURL = "http://users" 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 { 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() return result.ID, nil
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)
} }
func seedAll(ctx context.Context, store *Store, userID string) error { func seedAll(ctx context.Context, store *Store, userID string) error {