package bootstrap import ( "baron-sso-backend/internal/domain" "baron-sso-backend/internal/service" "context" "log/slog" "gorm.io/gorm" ) // SyncKetoRelations synchronizes all existing DB users and tenants to Ory Keto. // This ensures data consistency for existing data when ReBAC is introduced. func SyncKetoRelations(db *gorm.DB, keto service.KetoService) error { slog.Info("🚀 Starting Keto ReBAC relation synchronization...") ctx := context.Background() // 1. Sync All Tenants (Ensure they exist in Keto if needed) var tenants []domain.Tenant if err := db.Find(&tenants).Error; err != nil { return err } slog.Info("Syncing tenants to Keto", "count", len(tenants)) for _, t := range tenants { if t.ParentID != nil { _ = keto.CreateRelation(ctx, "Tenant", t.ID, "parents", "Tenant:"+*t.ParentID) } } // 2. Sync All Users var users []domain.User if err := db.Find(&users).Error; err != nil { return err } slog.Info("Syncing users to Keto", "count", len(users)) for _, u := range users { role := domain.NormalizeRole(u.Role) // Membership if u.TenantID != nil { _ = keto.CreateRelation(ctx, "Tenant", *u.TenantID, "members", "User:"+u.ID) } // Roles if role == domain.RoleSuperAdmin { _ = keto.CreateRelation(ctx, "System", "global", "super_admins", "User:"+u.ID) } else if role == domain.RoleTenantAdmin && u.TenantID != nil { _ = keto.CreateRelation(ctx, "Tenant", *u.TenantID, "admins", "User:"+u.ID) } } slog.Info("✅ Keto ReBAC synchronization completed.") return nil }