forked from baron/baron-sso
callback 검증 보강. seed-tenant 추가보강
This commit is contained in:
@@ -2,9 +2,19 @@ package bootstrap
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"baron-sso-backend/internal/testsupport"
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
postgres_module "github.com/testcontainers/testcontainers-go/modules/postgres"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
gorm_postgres "gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestSeedTenantCSVDefinesWorksmobileDomainClassTenants(t *testing.T) {
|
||||
@@ -165,3 +175,144 @@ func TestIsSeedTenantSlugUsesConfiguredCSVPath(t *testing.T) {
|
||||
t.Fatal("normal-tenant must not be detected as seed tenant")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterMissingSeedTenantConfigsSkipsExistingSlugs(t *testing.T) {
|
||||
configs := []InitialTenantConfig{
|
||||
{TenantID: "existing-root-id", Name: "Existing Root", Slug: "existing-root"},
|
||||
{Name: "Missing Child", Slug: "missing-child", ParentSlug: "existing-root"},
|
||||
{TenantID: "existing-child-id", Name: "Existing Child", Slug: "existing-child", ParentSlug: "existing-root"},
|
||||
{TenantID: "existing-other-id", Name: "Conflicting ID", Slug: "new-slug"},
|
||||
}
|
||||
existingSlugs := map[string]bool{
|
||||
"existing-root": true,
|
||||
"existing-child": true,
|
||||
}
|
||||
existingIDs := map[string]bool{
|
||||
"existing-root-id": true,
|
||||
"existing-child-id": true,
|
||||
"existing-other-id": true,
|
||||
}
|
||||
|
||||
filtered := filterMissingSeedTenantConfigs(configs, existingSlugs, existingIDs)
|
||||
|
||||
if len(filtered) != 1 {
|
||||
t.Fatalf("filtered count = %d, want 1: %#v", len(filtered), filtered)
|
||||
}
|
||||
if filtered[0].Slug != "missing-child" {
|
||||
t.Fatalf("filtered slug = %q, want missing-child", filtered[0].Slug)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeedTenantsCreatesMissingSeedRowsWithoutTouchingExistingSlugs(t *testing.T) {
|
||||
if !testsupport.DockerAvailable() {
|
||||
t.Skip("Docker provider is unavailable in this environment")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
postgresContainer, err := postgres_module.Run(ctx,
|
||||
"postgres:16-alpine",
|
||||
postgres_module.WithDatabase("testdb"),
|
||||
postgres_module.WithUsername("user"),
|
||||
postgres_module.WithPassword("password"),
|
||||
testcontainers.WithWaitStrategy(
|
||||
wait.ForLog("database system is ready to accept connections").
|
||||
WithOccurrence(2).
|
||||
WithStartupTimeout(30*time.Second),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to start postgres container: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := postgresContainer.Terminate(ctx); err != nil {
|
||||
log.Printf("failed to terminate postgres container: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
connStr, err := postgresContainer.ConnectionString(ctx, "sslmode=disable")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get postgres connection string: %v", err)
|
||||
}
|
||||
db, err := gorm.Open(gorm_postgres.Open(connStr), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open postgres connection: %v", err)
|
||||
}
|
||||
if err := db.AutoMigrate(&domain.Tenant{}, &domain.TenantDomain{}, &domain.KetoOutbox{}); err != nil {
|
||||
t.Fatalf("failed to migrate seed test tables: %v", err)
|
||||
}
|
||||
|
||||
existingRoot := domain.Tenant{
|
||||
ID: "00000000-0000-0000-0000-000000000001",
|
||||
Name: "Existing Root Name",
|
||||
Slug: "existing-root",
|
||||
Type: domain.TenantTypeCompanyGroup,
|
||||
Description: "manual tenant must not be overwritten",
|
||||
Status: domain.TenantStatusActive,
|
||||
}
|
||||
nonSeedTenant := domain.Tenant{
|
||||
ID: "00000000-0000-0000-0000-000000000002",
|
||||
Name: "Manual Tenant",
|
||||
Slug: "manual-tenant",
|
||||
Type: domain.TenantTypeCompany,
|
||||
Status: domain.TenantStatusActive,
|
||||
}
|
||||
if err := db.Create(&existingRoot).Error; err != nil {
|
||||
t.Fatalf("failed to create existing root tenant: %v", err)
|
||||
}
|
||||
if err := db.Create(&nonSeedTenant).Error; err != nil {
|
||||
t.Fatalf("failed to create non-seed tenant: %v", err)
|
||||
}
|
||||
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "seed-tenant.csv")
|
||||
csv := "id,name,type,parent_tenant_slug,slug,memo,email_domain\n" +
|
||||
"10000000-0000-0000-0000-000000000001,Seed Root Name,COMPANY_GROUP,,existing-root,seed must be skipped,\n" +
|
||||
"00000000-0000-0000-0000-000000000002,Conflicting ID,COMPANY,existing-root,conflicting-id,seed id must be skipped,\n" +
|
||||
"10000000-0000-0000-0000-000000000002,Missing Child,COMPANY,existing-root,missing-child,created from seed,child.example.com\n"
|
||||
if err := os.WriteFile(path, []byte(csv), 0o600); err != nil {
|
||||
t.Fatalf("failed to write seed csv: %v", err)
|
||||
}
|
||||
t.Setenv(seedTenantCSVPathEnv, path)
|
||||
|
||||
if err := SeedTenants(db); err != nil {
|
||||
t.Fatalf("SeedTenants returned error: %v", err)
|
||||
}
|
||||
|
||||
var root domain.Tenant
|
||||
if err := db.First(&root, "slug = ?", "existing-root").Error; err != nil {
|
||||
t.Fatalf("failed to load existing root after seed: %v", err)
|
||||
}
|
||||
if root.ID != existingRoot.ID {
|
||||
t.Fatalf("existing root ID = %q, want %q", root.ID, existingRoot.ID)
|
||||
}
|
||||
if root.Name != existingRoot.Name {
|
||||
t.Fatalf("existing root name = %q, want untouched %q", root.Name, existingRoot.Name)
|
||||
}
|
||||
|
||||
var child domain.Tenant
|
||||
if err := db.Preload("Domains").First(&child, "slug = ?", "missing-child").Error; err != nil {
|
||||
t.Fatalf("missing seed child was not created: %v", err)
|
||||
}
|
||||
if child.ParentID == nil || *child.ParentID != existingRoot.ID {
|
||||
t.Fatalf("child parent ID = %v, want %q", child.ParentID, existingRoot.ID)
|
||||
}
|
||||
if len(child.Domains) != 1 || child.Domains[0].Domain != "child.example.com" {
|
||||
t.Fatalf("child domains = %#v, want child.example.com", child.Domains)
|
||||
}
|
||||
|
||||
var rootCount int64
|
||||
if err := db.Model(&domain.Tenant{}).Where("slug = ?", "existing-root").Count(&rootCount).Error; err != nil {
|
||||
t.Fatalf("failed to count existing root rows: %v", err)
|
||||
}
|
||||
if rootCount != 1 {
|
||||
t.Fatalf("existing-root row count = %d, want 1", rootCount)
|
||||
}
|
||||
|
||||
var conflictingIDCount int64
|
||||
if err := db.Model(&domain.Tenant{}).Where("slug = ?", "conflicting-id").Count(&conflictingIDCount).Error; err != nil {
|
||||
t.Fatalf("failed to count conflicting-id rows: %v", err)
|
||||
}
|
||||
if conflictingIDCount != 0 {
|
||||
t.Fatalf("conflicting-id row count = %d, want 0", conflictingIDCount)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user