package bootstrap import ( "baron-sso-backend/internal/domain" "baron-sso-backend/internal/repository" "context" "log/slog" "gorm.io/gorm" ) // SyncKetoRelations synchronizes all existing DB users, tenants and RPs to Ory Keto via Outbox. // This ensures data consistency for existing data when ReBAC is introduced. func SyncKetoRelations(db *gorm.DB, outbox repository.KetoOutboxRepository) error { slog.Info("🚀 Starting Keto ReBAC relation synchronization (via Outbox)...") ctx := context.Background() // 1. Sync All Tenants var tenants []domain.Tenant if err := db.Find(&tenants).Error; err != nil { return err } slog.Info("Syncing tenants to Keto Outbox", "count", len(tenants)) for _, t := range tenants { // Global Super Admin access to every tenant _ = outbox.Create(ctx, &domain.KetoOutbox{ Namespace: "Tenant", Object: t.ID, Relation: "admins", Subject: "System:global#super_admins", Action: domain.KetoOutboxActionCreate, }) if t.ParentID != nil { _ = outbox.Create(ctx, &domain.KetoOutbox{ Namespace: "Tenant", Object: t.ID, Relation: "parents", Subject: "Tenant:" + *t.ParentID, Action: domain.KetoOutboxActionCreate, }) } } // 2. Sync All RelyingParties (if needed) // Note: We'll need a way to list them from Hydra or local DB if we had them. // Assuming they are in a table domain.RelyingParty (though it was removed, let's see) // Actually, the comment said SSOT is Hydra. But we might have them in a local table for metadata. // If not, we skip for now or fetch from Hydra. // 3. Sync All Users Roles and Tenant Memberships var users []domain.User if err := db.Find(&users).Error; err != nil { return err } slog.Info("Syncing users to Keto Outbox", "count", len(users)) for _, u := range users { // Tenant Membership if u.TenantID != nil { _ = outbox.Create(ctx, &domain.KetoOutbox{ Namespace: "Tenant", Object: *u.TenantID, Relation: "members", Subject: "User:" + u.ID, Action: domain.KetoOutboxActionCreate, }) } // Roles role := domain.NormalizeRole(u.Role) if role == domain.RoleSuperAdmin { _ = outbox.Create(ctx, &domain.KetoOutbox{ Namespace: "System", Object: "global", Relation: "super_admins", Subject: "User:" + u.ID, Action: domain.KetoOutboxActionCreate, }) } } slog.Info("✅ Keto ReBAC synchronization items added to Outbox.") return nil }