From 022b1ef8ec755ee3c081c6276ecda3c3bd4aaea7 Mon Sep 17 00:00:00 2001 From: mrhid6 Date: Tue, 21 Jul 2026 16:25:37 +0100 Subject: [PATCH] feat(server): auth indexes + default-org backfill migration --- server/cmd/main.go | 7 +++ server/internal/services/migrate.go | 89 +++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 server/internal/services/migrate.go diff --git a/server/cmd/main.go b/server/cmd/main.go index cec38b2..639e1bd 100644 --- a/server/cmd/main.go +++ b/server/cmd/main.go @@ -24,6 +24,13 @@ func main() { } log.Println("connected to MongoDB") + if err := services.EnsureAuthIndexes(); err != nil { + log.Printf("warning: failed to ensure auth indexes: %v", err) + } + if err := services.RunMigrations(); err != nil { + log.Fatalf("migration failed: %v", err) + } + if err := services.EnsureSecretIndexes(); err != nil { log.Printf("warning: failed to ensure secret indexes: %v", err) } diff --git a/server/internal/services/migrate.go b/server/internal/services/migrate.go new file mode 100644 index 0000000..cae5574 --- /dev/null +++ b/server/internal/services/migrate.go @@ -0,0 +1,89 @@ +package services + +import ( + "context" + "time" + + "github.com/google/uuid" + "github.com/mrhid6/vantage/server/internal/db" + "github.com/mrhid6/vantage/server/internal/models" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" +) + +var scopedCollections = []string{ + "servers", "keys", "assignments", "secrets", + "workflows", "workflow_steps", "workflow_runs", + "audit", "monitors", "channels", +} + +// EnsureAuthIndexes creates unique indexes for the new auth collections. +func EnsureAuthIndexes() error { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + if _, err := db.Col("users").Indexes().CreateOne(ctx, mongo.IndexModel{ + Keys: bson.D{{Key: "email", Value: 1}}, + Options: options.Index().SetUnique(true), + }); err != nil { + return err + } + if _, err := db.Col("orgs").Indexes().CreateOne(ctx, mongo.IndexModel{ + Keys: bson.D{{Key: "slug", Value: 1}}, + Options: options.Index().SetUnique(true), + }); err != nil { + return err + } + if _, err := db.Col("org_oidc").Indexes().CreateOne(ctx, mongo.IndexModel{ + Keys: bson.D{{Key: "org_id", Value: 1}}, + Options: options.Index().SetUnique(true), + }); err != nil { + return err + } + return nil +} + +// RunMigrations backfills a default org onto pre-existing documents. Idempotent +// via a marker in the migrations collection. +func RunMigrations() error { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + const marker = "0001_default_org_backfill" + if n, _ := db.Col("migrations").CountDocuments(ctx, bson.M{"_id": marker}); n > 0 { + return nil + } + + // Only backfill if there is legacy data lacking org_id. + needs := false + for _, col := range scopedCollections { + n, _ := db.Col(col).CountDocuments(ctx, bson.M{"org_id": bson.M{"$exists": false}}) + if n > 0 { + needs = true + break + } + } + + if needs { + var org models.Org + err := db.Col("orgs").FindOne(ctx, bson.M{"slug": "default"}).Decode(&org) + if err != nil { + org = models.Org{OrgID: uuid.NewString(), Name: "Default", Slug: "default", CreatedAt: time.Now()} + if _, err := db.Col("orgs").InsertOne(ctx, org); err != nil { + return err + } + } + for _, col := range scopedCollections { + if _, err := db.Col(col).UpdateMany(ctx, + bson.M{"org_id": bson.M{"$exists": false}}, + bson.M{"$set": bson.M{"org_id": org.OrgID}}, + ); err != nil { + return err + } + } + } + + _, err := db.Col("migrations").InsertOne(ctx, bson.M{"_id": marker, "applied_at": time.Now()}) + return err +}