forked from baron/baron-sso
148 lines
4.2 KiB
Go
148 lines
4.2 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"baron-sso-backend/internal/domain"
|
|
"baron-sso-backend/internal/repository"
|
|
"baron-sso-backend/internal/service"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type InitialTenantConfig struct {
|
|
Name string
|
|
Slug string
|
|
Type string
|
|
ParentSlug string
|
|
Description string
|
|
Domains []string
|
|
}
|
|
|
|
// Hardcoded for now, can be moved to config file or env later
|
|
var defaultTenants = []InitialTenantConfig{
|
|
{
|
|
Name: "한맥가족",
|
|
Slug: "hanmac-family",
|
|
Type: domain.TenantTypeCompanyGroup,
|
|
},
|
|
{
|
|
Name: "한맥기술",
|
|
Slug: "hanmac",
|
|
Type: domain.TenantTypeCompany,
|
|
ParentSlug: "hanmac-family",
|
|
Description: "Primary Family Company",
|
|
Domains: []string{"hanmaceng.co.kr", "hmac.kr"},
|
|
},
|
|
{
|
|
Name: "삼안",
|
|
Slug: "saman",
|
|
Type: domain.TenantTypeCompany,
|
|
ParentSlug: "hanmac-family",
|
|
Domains: []string{"samaneng.com"},
|
|
},
|
|
}
|
|
|
|
func SeedTenants(db *gorm.DB) error {
|
|
slog.Info("[Bootstrap] Seeding initial tenants...")
|
|
repo := repository.NewTenantRepository(db)
|
|
userRepo := repository.NewUserRepository(db)
|
|
userGroupRepo := repository.NewUserGroupRepository(db)
|
|
outboxRepo := repository.NewKetoOutboxRepository(db)
|
|
svc := service.NewTenantService(repo, userRepo, userGroupRepo, outboxRepo)
|
|
ctx := context.Background()
|
|
|
|
for _, config := range defaultTenants {
|
|
tenantType := config.Type
|
|
if tenantType == "" {
|
|
tenantType = domain.TenantTypeCompany
|
|
}
|
|
|
|
var parentID *string
|
|
if config.ParentSlug != "" {
|
|
parent, err := repo.FindBySlug(ctx, config.ParentSlug)
|
|
if err != nil || parent == nil {
|
|
if err == nil {
|
|
err = errors.New("parent tenant not found")
|
|
}
|
|
slog.Error("Failed to resolve parent tenant for seed", "slug", config.Slug, "parentSlug", config.ParentSlug, "error", err)
|
|
return fmt.Errorf("resolve parent tenant %q for seed %q: %w", config.ParentSlug, config.Slug, err)
|
|
}
|
|
parentID = &parent.ID
|
|
}
|
|
|
|
existing, err := repo.FindBySlug(ctx, config.Slug)
|
|
if err == nil && existing != nil {
|
|
slog.Info("[Bootstrap] Tenant already exists, checking domains...", "slug", config.Slug)
|
|
changed := false
|
|
if existing.Name != config.Name {
|
|
existing.Name = config.Name
|
|
changed = true
|
|
}
|
|
if existing.Type != tenantType {
|
|
existing.Type = tenantType
|
|
changed = true
|
|
}
|
|
if existing.Status != domain.TenantStatusActive {
|
|
existing.Status = domain.TenantStatusActive
|
|
changed = true
|
|
}
|
|
if config.ParentSlug != "" {
|
|
if existing.ParentID == nil || *existing.ParentID != *parentID {
|
|
existing.ParentID = parentID
|
|
changed = true
|
|
if err := outboxRepo.Create(ctx, &domain.KetoOutbox{
|
|
Namespace: "Tenant",
|
|
Object: existing.ID,
|
|
Relation: "parents",
|
|
Subject: "Tenant:" + *parentID,
|
|
Action: domain.KetoOutboxActionCreate,
|
|
}); err != nil {
|
|
slog.Error("Failed to create outbox entry for seeded tenant hierarchy", "tenant", existing.ID, "error", err)
|
|
return err
|
|
}
|
|
}
|
|
} else if existing.ParentID != nil {
|
|
existing.ParentID = nil
|
|
changed = true
|
|
}
|
|
if changed {
|
|
if err := repo.Update(ctx, existing); err != nil {
|
|
slog.Error("Failed to update seeded tenant", "slug", config.Slug, "error", err)
|
|
return err
|
|
}
|
|
}
|
|
// Optional: Check and add missing domains
|
|
for _, d := range config.Domains {
|
|
found := false
|
|
for _, ed := range existing.Domains {
|
|
if ed.Domain == d {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
slog.Info("[Bootstrap] Adding missing domain to tenant", "slug", config.Slug, "domain", d)
|
|
if err := repo.AddDomain(ctx, existing.ID, d, true); err != nil {
|
|
slog.Error("Failed to add domain", "error", err)
|
|
}
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
slog.Info("[Bootstrap] Creating default tenant", "name", config.Name, "slug", config.Slug)
|
|
tenant, err := svc.RegisterTenant(ctx, config.Name, config.Slug, tenantType, config.Description, config.Domains, parentID, "")
|
|
if err != nil {
|
|
slog.Error("Failed to seed tenant", "slug", config.Slug, "error", err)
|
|
return err
|
|
}
|
|
// Explicitly set to active during seed
|
|
tenant.Status = domain.TenantStatusActive
|
|
db.Save(tenant)
|
|
}
|
|
return nil
|
|
}
|