1
0
forked from baron/baron-sso

조직 연동 오류 해결

This commit is contained in:
2026-05-20 11:17:31 +09:00
parent 42b49674cc
commit fd82dd9bdd
15 changed files with 592 additions and 30 deletions

View File

@@ -56,7 +56,7 @@ func TestEnsureSuperAdminPromotesExistingLocalUser(t *testing.T) {
Email: "existing@example.com",
Name: "Existing",
Role: domain.RoleUser,
Status: domain.UserStatusInactive,
Status: domain.UserStatusPreboarding,
},
}

View File

@@ -23,6 +23,9 @@ func Run(db *gorm.DB) error {
}
// 3. Normalize staging seed/read-model data
if err := CanonicalizeLegacyUserStatuses(db); err != nil {
return fmt.Errorf("legacy user status canonicalization failed: %w", err)
}
if err := SanitizeLegacyUserMetadata(db); err != nil {
return fmt.Errorf("legacy user metadata sanitize failed: %w", err)
}
@@ -64,6 +67,25 @@ func migrateSchemas(db *gorm.DB) error {
)
}
func CanonicalizeLegacyUserStatuses(db *gorm.DB) error {
if db == nil || !db.Migrator().HasTable(&domain.User{}) {
return nil
}
updates := map[string]string{
"inactive": domain.UserStatusPreboarding,
"leave_of_absence": domain.UserStatusTemporaryLeave,
"baron_only": domain.UserStatusBaronGuest,
}
for legacy, canonical := range updates {
if err := db.Model(&domain.User{}).
Where("status = ?", legacy).
Update("status", canonical).Error; err != nil {
return fmt.Errorf("failed to canonicalize users.status %s to %s: %w", legacy, canonical, err)
}
}
return nil
}
func dropLegacyUserCompanyColumns(db *gorm.DB) error {
if !db.Migrator().HasTable(&domain.User{}) {
return nil

View File

@@ -68,6 +68,52 @@ func TestSanitizeLegacyUserMetadataRemovesClassificationFlags(t *testing.T) {
}
}
func TestCanonicalizeLegacyUserStatuses(t *testing.T) {
db := openBootstrapPostgresTestDB(t)
if err := db.AutoMigrate(&domain.User{}); err != nil {
t.Fatalf("failed to migrate users table: %v", err)
}
users := []domain.User{
{ID: "11000000-0000-0000-0000-000000000001", Email: "inactive@example.com", Name: "Inactive", Role: domain.RoleUser, Status: "inactive"},
{ID: "11000000-0000-0000-0000-000000000002", Email: "leave@example.com", Name: "Leave", Role: domain.RoleUser, Status: "leave_of_absence"},
{ID: "11000000-0000-0000-0000-000000000003", Email: "baron-only@example.com", Name: "Baron Only", Role: domain.RoleUser, Status: "baron_only"},
{ID: "11000000-0000-0000-0000-000000000004", Email: "active@example.com", Name: "Active", Role: domain.RoleUser, Status: domain.UserStatusActive},
}
if err := db.Create(&users).Error; err != nil {
t.Fatalf("failed to create users: %v", err)
}
if err := CanonicalizeLegacyUserStatuses(db); err != nil {
t.Fatalf("CanonicalizeLegacyUserStatuses returned error: %v", err)
}
if err := CanonicalizeLegacyUserStatuses(db); err != nil {
t.Fatalf("CanonicalizeLegacyUserStatuses must be idempotent: %v", err)
}
got := map[string]string{}
var loaded []domain.User
if err := db.Find(&loaded).Error; err != nil {
t.Fatalf("failed to load users: %v", err)
}
for _, user := range loaded {
got[user.Email] = user.Status
}
if got["inactive@example.com"] != domain.UserStatusPreboarding {
t.Fatalf("inactive status = %q, want %q", got["inactive@example.com"], domain.UserStatusPreboarding)
}
if got["leave@example.com"] != domain.UserStatusTemporaryLeave {
t.Fatalf("leave status = %q, want %q", got["leave@example.com"], domain.UserStatusTemporaryLeave)
}
if got["baron-only@example.com"] != domain.UserStatusBaronGuest {
t.Fatalf("baron_only status = %q, want %q", got["baron-only@example.com"], domain.UserStatusBaronGuest)
}
if got["active@example.com"] != domain.UserStatusActive {
t.Fatalf("active status = %q, want %q", got["active@example.com"], domain.UserStatusActive)
}
}
func TestRunSanitizesLegacyUserMetadata(t *testing.T) {
db := openBootstrapPostgresTestDB(t)
if err := db.AutoMigrate(&domain.User{}); err != nil {

View File

@@ -21,9 +21,7 @@ const (
// User statuses
const (
UserStatusActive = "active"
UserStatusInactive = "inactive"
UserStatusSuspended = "suspended"
UserStatusLeaveOfAbsence = "leave_of_absence"
UserStatusTemporaryLeave = "temporary_leave"
UserStatusPreboarding = "preboarding"
UserStatusBaronGuest = "baron_guest"
@@ -37,9 +35,9 @@ func NormalizeUserStatus(status string) string {
return UserStatusActive
case "blocked", UserStatusSuspended:
return UserStatusSuspended
case UserStatusInactive, UserStatusPreboarding:
case "inactive", UserStatusPreboarding:
return UserStatusPreboarding
case UserStatusLeaveOfAbsence, UserStatusTemporaryLeave:
case "leave_of_absence", UserStatusTemporaryLeave:
return UserStatusTemporaryLeave
case "baron_only", UserStatusBaronGuest:
return UserStatusBaronGuest

View File

@@ -46,8 +46,8 @@ func TestUserStatusPolicy(t *testing.T) {
{status: UserStatusBaronGuest, normalized: UserStatusBaronGuest, baronAllowed: true, worksDeprovisioned: true},
{status: UserStatusExtendedLeave, normalized: UserStatusExtendedLeave, worksDeprovisioned: true},
{status: UserStatusArchived, normalized: UserStatusArchived, worksDeprovisioned: true},
{status: UserStatusInactive, normalized: UserStatusPreboarding},
{status: UserStatusLeaveOfAbsence, normalized: UserStatusTemporaryLeave, baronAllowed: true, orgVisible: true, worksProvisioned: true},
{status: "inactive", normalized: UserStatusPreboarding},
{status: "leave_of_absence", normalized: UserStatusTemporaryLeave, baronAllowed: true, orgVisible: true, worksProvisioned: true},
{status: "BARON_ONLY", normalized: UserStatusBaronGuest, baronAllowed: true, worksDeprovisioned: true},
}

View File

@@ -2618,7 +2618,7 @@ func normalizeKratosState(status *string) string {
}
value := strings.ToLower(strings.TrimSpace(*status))
if value == "blocked" {
return domain.UserStatusInactive
return "inactive"
}
if value == domain.UserStatusActive {
return domain.UserStatusActive
@@ -2630,7 +2630,7 @@ func normalizeKratosState(status *string) string {
normalized == domain.UserStatusBaronGuest ||
normalized == domain.UserStatusExtendedLeave ||
normalized == domain.UserStatusArchived {
return domain.UserStatusInactive
return "inactive"
}
return ""
}

View File

@@ -376,7 +376,7 @@ func TestWorksmobileUserStatusAction(t *testing.T) {
require.Equal(t, domain.WorksmobileActionDelete, WorksmobileUserStatusAction(domain.UserStatusExtendedLeave))
require.Equal(t, domain.WorksmobileActionDelete, WorksmobileUserStatusAction(domain.UserStatusBaronGuest))
require.Equal(t, domain.WorksmobileActionDelete, WorksmobileUserStatusAction(domain.UserStatusArchived))
require.Equal(t, WorksmobileUserActionUpsert, WorksmobileUserStatusAction(domain.UserStatusLeaveOfAbsence))
require.Equal(t, WorksmobileUserActionUpsert, WorksmobileUserStatusAction("leave_of_absence"))
require.Equal(t, domain.WorksmobileActionDelete, WorksmobileUserStatusAction("baron_only"))
}

View File

@@ -736,6 +736,9 @@ func isWorksmobileOrgUnitTenant(tenant domain.Tenant, tenantByID map[string]doma
if tenant.Type == domain.TenantTypeOrganization {
return true
}
if tenant.Type == domain.TenantTypeUserGroup {
return true
}
if tenant.Type == domain.TenantTypeCompany {
return isWorksmobileBarongroupChildCompany(tenant, tenantByID)
}
@@ -749,7 +752,7 @@ func isWorksmobileUserScopeTenant(tenant domain.Tenant) bool {
func worksmobileDomainClassificationTenant(tenant domain.Tenant, tenantByID map[string]domain.Tenant) domain.Tenant {
current := tenant
for {
if current.Type == domain.TenantTypeCompany || len(current.Domains) > 0 {
if isWorksmobileDomainRootTenant(current) {
return current
}
parentID := worksmobileTenantParentID(current)
@@ -764,6 +767,25 @@ func worksmobileDomainClassificationTenant(tenant domain.Tenant, tenantByID map[
}
}
func isWorksmobileDomainRootTenant(tenant domain.Tenant) bool {
slug := strings.ToLower(strings.TrimSpace(tenant.Slug))
switch slug {
case "saman", "hanmac", "gpdtdc", "baron-group":
return true
}
if tenantHasDomain(tenant, "samaneng.com") ||
tenantHasDomain(tenant, "hanmaceng.co.kr") ||
tenantHasDomain(tenant, "baroncs.co.kr") ||
tenantHasDomain(tenant, "brsw.kr") {
return true
}
name := strings.TrimSpace(tenant.Name)
return name == "삼안" ||
name == "한맥기술" ||
name == "총괄기획&기술개발센터" ||
name == "바론그룹"
}
func isWorksmobileBarongroupChildCompany(tenant domain.Tenant, tenantByID map[string]domain.Tenant) bool {
if tenant.Type != domain.TenantTypeCompany || tenant.Slug == "baron-group" {
return false
@@ -972,14 +994,14 @@ func worksmobileUserPrimaryOrgSlug(user domain.User, localTenants map[string]dom
}
func compareWorksmobileGroups(localTenants []domain.Tenant, remoteGroups []WorksmobileRemoteGroup, includeMatched bool) []WorksmobileComparisonItem {
remoteByExternalID := map[string]WorksmobileRemoteGroup{}
remoteByExternalID := map[string][]WorksmobileRemoteGroup{}
remoteByID := map[string]WorksmobileRemoteGroup{}
for _, remote := range remoteGroups {
if remote.ID != "" {
remoteByID[remote.ID] = remote
}
if remote.ExternalID != "" {
remoteByExternalID[remote.ExternalID] = remote
remoteByExternalID[remote.ExternalID] = append(remoteByExternalID[remote.ExternalID], remote)
}
}
tenantByID := worksmobileTenantByID(localTenants)
@@ -993,11 +1015,7 @@ func compareWorksmobileGroups(localTenants []domain.Tenant, remoteGroups []Works
continue
}
localByID[tenant.ID] = tenant
remote, matched := remoteByExternalID[tenant.ID]
if matched && !includeMatched {
matchedRemoteIDs[remote.ID] = true
continue
}
remote, matched := matchingWorksmobileRemoteGroupForTenant(tenant, remoteByExternalID[tenant.ID], tenantByID)
item := WorksmobileComparisonItem{
ResourceType: "GROUP",
BaronID: tenant.ID,
@@ -1018,7 +1036,13 @@ func compareWorksmobileGroups(localTenants []domain.Tenant, remoteGroups []Works
item.WorksmobileDomainName = remote.DomainName
item.WorksmobileParentID = remote.ParentID
item.WorksmobileParentName = remote.ParentName
if parentRemote, ok := remoteByExternalID[item.BaronParentID]; ok {
if parent, ok := tenantByID[item.BaronParentID]; ok {
if parentRemote, ok := matchingWorksmobileRemoteGroupForTenant(parent, remoteByExternalID[item.BaronParentID], tenantByID); ok {
item.BaronParentWorksmobileID = parentRemote.ID
item.BaronParentWorksmobileName = parentRemote.DisplayName
item.BaronParentWorksmobileEmail = parentRemote.Email
}
} else if parentRemote, ok := firstWorksmobileRemoteGroup(remoteByExternalID[item.BaronParentID]); ok {
item.BaronParentWorksmobileID = parentRemote.ID
item.BaronParentWorksmobileName = parentRemote.DisplayName
item.BaronParentWorksmobileEmail = parentRemote.Email
@@ -1031,8 +1055,14 @@ func compareWorksmobileGroups(localTenants []domain.Tenant, remoteGroups []Works
item.WorksmobileParentExternalKey = parentRemote.ExternalID
}
item = fillWorksmobileParentFromBaronParentMatch(item)
if worksmobileGroupNeedsUpdate(tenant, remote, remoteByID, remoteByExternalID, tenantByID) {
item.Status = "needs_update"
}
matchedRemoteIDs[remote.ID] = true
}
if matched && item.Status == "matched" && !includeMatched {
continue
}
result = append(result, item)
}
for _, remote := range remoteGroups {
@@ -1091,6 +1121,79 @@ func compareWorksmobileGroups(localTenants []domain.Tenant, remoteGroups []Works
return result
}
func matchingWorksmobileRemoteGroupForTenant(tenant domain.Tenant, remotes []WorksmobileRemoteGroup, tenantByID map[string]domain.Tenant) (WorksmobileRemoteGroup, bool) {
if len(remotes) == 0 {
return WorksmobileRemoteGroup{}, false
}
expectedDomainID, hasExpectedDomainID := expectedWorksmobileDomainIDForTenant(tenant, tenantByID)
if !hasExpectedDomainID {
return remotes[0], true
}
var unknownDomain WorksmobileRemoteGroup
hasUnknownDomain := false
for i := range remotes {
remote := remotes[i]
if remote.DomainID == expectedDomainID {
return remote, true
}
if remote.DomainID == 0 && !hasUnknownDomain {
unknownDomain = remote
hasUnknownDomain = true
}
}
if hasUnknownDomain {
return unknownDomain, true
}
return WorksmobileRemoteGroup{}, false
}
func firstWorksmobileRemoteGroup(remotes []WorksmobileRemoteGroup) (WorksmobileRemoteGroup, bool) {
if len(remotes) == 0 {
return WorksmobileRemoteGroup{}, false
}
return remotes[0], true
}
func expectedWorksmobileDomainIDForTenant(tenant domain.Tenant, tenantByID map[string]domain.Tenant) (int64, bool) {
domainTenant := worksmobileDomainClassificationTenant(tenant, tenantByID)
domainID, err := ResolveWorksmobileDomainIDFromTenant(domainTenant, nil)
if err != nil || domainID <= 0 {
return 0, false
}
return domainID, true
}
func worksmobileGroupNeedsUpdate(tenant domain.Tenant, remote WorksmobileRemoteGroup, remoteByID map[string]WorksmobileRemoteGroup, remoteByExternalID map[string][]WorksmobileRemoteGroup, tenantByID map[string]domain.Tenant) bool {
if strings.TrimSpace(tenant.Name) != strings.TrimSpace(remote.DisplayName) {
return true
}
expectedParentExternalKey := expectedWorksmobileParentExternalKey(tenant, remoteByExternalID, tenantByID)
actualParentExternalKey := ""
if remote.ParentID != "" {
actualParentExternalKey = strings.TrimSpace(remoteByID[remote.ParentID].ExternalID)
}
return expectedParentExternalKey != actualParentExternalKey
}
func expectedWorksmobileParentExternalKey(tenant domain.Tenant, remoteByExternalID map[string][]WorksmobileRemoteGroup, tenantByID map[string]domain.Tenant) string {
parentID := worksmobileTenantParentID(tenant)
if parentID == "" {
return ""
}
if parent, ok := tenantByID[parentID]; ok && parent.Slug == "baron-group" {
return ""
}
parent, ok := tenantByID[parentID]
if !ok {
return ""
}
if _, ok := matchingWorksmobileRemoteGroupForTenant(parent, remoteByExternalID[parentID], tenantByID); !ok {
return ""
}
return parentID
}
func fillWorksmobileParentFromBaronParentMatch(item WorksmobileComparisonItem) WorksmobileComparisonItem {
if item.WorksmobileParentID == "" || item.WorksmobileParentID != item.BaronParentWorksmobileID {
return item

View File

@@ -200,28 +200,28 @@ func TestCompareWorksmobileGroupsUsesOrganizationsAndBarongroupChildCompanies(t
Type: domain.TenantTypeOrganization,
ParentID: &hanmac.ID,
}
legacyUserGroup := domain.Tenant{
userGroup := domain.Tenant{
ID: "legacy-user-group-tenant",
Name: "레거시 사용자 그룹",
Name: "사용자 그룹 조직",
Type: domain.TenantTypeUserGroup,
ParentID: &hanmac.ID,
}
items := compareWorksmobileGroups(
[]domain.Tenant{root, hanmac, barongroup, barongroupChildCompany, organization, legacyUserGroup},
[]domain.Tenant{root, hanmac, barongroup, barongroupChildCompany, organization, userGroup},
[]WorksmobileRemoteGroup{
{ID: "works-root", ExternalID: root.ID, DisplayName: root.Name},
{ID: "works-hanmac", ExternalID: hanmac.ID, DisplayName: hanmac.Name, Email: "hanmac@hanmaceng.co.kr"},
{ID: "works-barongroup", ExternalID: barongroup.ID, DisplayName: barongroup.Name},
{ID: "works-barongroup-child", ExternalID: barongroupChildCompany.ID, DisplayName: barongroupChildCompany.Name},
{ID: "works-organization", ExternalID: organization.ID, DisplayName: organization.Name, ParentID: "works-hanmac"},
{ID: "works-legacy-user-group", ExternalID: legacyUserGroup.ID, DisplayName: legacyUserGroup.Name},
{ID: "works-user-group", ExternalID: userGroup.ID, DisplayName: userGroup.Name, ParentID: "works-hanmac"},
{ID: "works-orphan", ExternalID: "works-orphan", DisplayName: "WORKS 전용 조직"},
},
true,
)
require.Len(t, items, 3)
require.Len(t, items, 4)
require.Equal(t, barongroupChildCompany.ID, items[0].BaronID)
require.Equal(t, "matched", items[0].Status)
require.Equal(t, organization.ID, items[1].BaronID)
@@ -233,8 +233,159 @@ func TestCompareWorksmobileGroupsUsesOrganizationsAndBarongroupChildCompanies(t
require.Equal(t, "works-hanmac", items[1].BaronParentWorksmobileID)
require.Equal(t, hanmac.Name, items[1].BaronParentWorksmobileName)
require.Equal(t, "hanmac@hanmaceng.co.kr", items[1].BaronParentWorksmobileEmail)
require.Equal(t, "works-orphan", items[2].ExternalKey)
require.Equal(t, "missing_in_baron", items[2].Status)
require.Equal(t, userGroup.ID, items[2].BaronID)
require.Equal(t, "matched", items[2].Status)
require.Equal(t, "works-orphan", items[3].ExternalKey)
require.Equal(t, "missing_in_baron", items[3].Status)
}
func TestCompareWorksmobileGroupsShowsUserGroupMissingInWorksmobile(t *testing.T) {
parentID := "company-tenant"
userGroup := domain.Tenant{
ID: "team-tenant",
Name: "신규 팀",
Slug: "new-team",
Type: domain.TenantTypeUserGroup,
ParentID: &parentID,
}
items := compareWorksmobileGroups(
[]domain.Tenant{
{ID: parentID, Slug: "company", Name: "계열사", Type: domain.TenantTypeCompany},
userGroup,
},
nil,
false,
)
require.Len(t, items, 1)
require.Equal(t, userGroup.ID, items[0].BaronID)
require.Equal(t, "missing_in_worksmobile", items[0].Status)
}
func TestCompareWorksmobileGroupsMarksMatchedOrgUnitNeedsUpdate(t *testing.T) {
parentID := "parent-tenant"
tenant := domain.Tenant{
ID: "team-tenant",
Name: "변경된 팀명",
Slug: "team",
Type: domain.TenantTypeUserGroup,
ParentID: &parentID,
}
items := compareWorksmobileGroups(
[]domain.Tenant{
{ID: parentID, Slug: "parent", Name: "상위 조직", Type: domain.TenantTypeUserGroup},
tenant,
},
[]WorksmobileRemoteGroup{
{ID: "works-parent", ExternalID: parentID, DisplayName: "상위 조직"},
{ID: "works-team", ExternalID: tenant.ID, DisplayName: "이전 팀명", ParentID: "works-parent"},
},
false,
)
require.Len(t, items, 1)
require.Equal(t, tenant.ID, items[0].BaronID)
require.Equal(t, "needs_update", items[0].Status)
}
func TestCompareWorksmobileGroupsCoversHanmacOrganizationRegressionIDs(t *testing.T) {
rootID := "038326b6-954a-48a7-a85f-efd83f62b82a"
samanID := "9caf62e1-297d-4e8f-870b-61780998bbeb"
hanmacID := "369c1843-56af-4344-9c21-0e01197ab861"
baronGroupID := "96369f12-6b66-4b2a-a916-d1c99d326f02"
changedID := "818c856b-9545-442f-b827-d1c569f200b0"
hanmacOnlyID := "2d217948-9c5a-42ea-805b-eef9c7421775"
baronOnlyID := "32464fd6-da51-473f-844a-ab88603ad1f0"
localTenants := []domain.Tenant{
{ID: rootID, Slug: HanmacFamilyTenantSlug, Name: "한맥가족", Type: domain.TenantTypeCompanyGroup},
{ID: samanID, Slug: "saman", Name: "삼안", Type: domain.TenantTypeCompany, ParentID: &rootID},
{ID: hanmacID, Slug: "hanmac", Name: "한맥기술", Type: domain.TenantTypeCompany, ParentID: &rootID},
{ID: baronGroupID, Slug: "baron-group", Name: "바론그룹", Type: domain.TenantTypeCompanyGroup, ParentID: &rootID},
{ID: changedID, Slug: "rnd-saman", Name: "삼안기술개발센터(조직도용)", Type: domain.TenantTypeOrganization, ParentID: &samanID},
{ID: hanmacOnlyID, Slug: "rnd-hanmac", Name: "한맥기술개발센터(조직도용)", Type: domain.TenantTypeOrganization, ParentID: &hanmacID},
{ID: baronOnlyID, Slug: "rnd-baron", Name: "바론기술개발센터(조직도용)", Type: domain.TenantTypeOrganization, ParentID: &baronGroupID},
}
remoteGroups := []WorksmobileRemoteGroup{
{ID: "works-saman", ExternalID: samanID, DisplayName: "삼안"},
{ID: "works-hanmac", ExternalID: hanmacID, DisplayName: "한맥기술"},
{
ID: "works-rnd-saman",
ExternalID: changedID,
DisplayName: "삼안기술개발센터(조직도용)",
},
}
items := compareWorksmobileGroups(localTenants, remoteGroups, false)
itemsByBaronID := map[string]WorksmobileComparisonItem{}
for _, item := range items {
itemsByBaronID[item.BaronID] = item
}
require.Equal(t, "needs_update", itemsByBaronID[changedID].Status)
require.Equal(t, "missing_in_worksmobile", itemsByBaronID[hanmacOnlyID].Status)
require.Equal(t, "missing_in_worksmobile", itemsByBaronID[baronOnlyID].Status)
}
func TestCompareWorksmobileGroupsDoesNotMatchBaronGroupOrganizationInGPDTDCDomain(t *testing.T) {
t.Setenv("GPDTDC_DOMAIN_ID", "1003")
t.Setenv("BARONGROUP_DOMAIN_ID", "1004")
rootID := "038326b6-954a-48a7-a85f-efd83f62b82a"
baronGroupID := "96369f12-6b66-4b2a-a916-d1c99d326f02"
orgID := "32464fd6-da51-473f-844a-ab88603ad1f0"
localTenants := []domain.Tenant{
{ID: rootID, Slug: HanmacFamilyTenantSlug, Name: "한맥가족", Type: domain.TenantTypeCompanyGroup},
{ID: baronGroupID, Slug: "baron-group", Name: "바론그룹", Type: domain.TenantTypeCompanyGroup, ParentID: &rootID},
{ID: orgID, Slug: "rnd-baron", Name: "바론기술개발센터(조직도용)", Type: domain.TenantTypeOrganization, ParentID: &baronGroupID},
}
remoteGroups := []WorksmobileRemoteGroup{
{
ID: "works-rnd-baron-gpdtdc",
ExternalID: orgID,
DisplayName: "바론기술개발센터(조직도용)",
DomainID: 1003,
DomainName: "총괄기획&기술개발센터",
},
}
items := compareWorksmobileGroups(localTenants, remoteGroups, false)
require.Len(t, items, 1)
require.Equal(t, orgID, items[0].BaronID)
require.Equal(t, "missing_in_worksmobile", items[0].Status)
require.Empty(t, items[0].WorksmobileID)
}
func TestCompareWorksmobileGroupsMatchesBaronGroupOrganizationInBaronGroupDomain(t *testing.T) {
t.Setenv("GPDTDC_DOMAIN_ID", "1003")
t.Setenv("BARONGROUP_DOMAIN_ID", "1004")
rootID := "038326b6-954a-48a7-a85f-efd83f62b82a"
baronGroupID := "96369f12-6b66-4b2a-a916-d1c99d326f02"
orgID := "32464fd6-da51-473f-844a-ab88603ad1f0"
localTenants := []domain.Tenant{
{ID: rootID, Slug: HanmacFamilyTenantSlug, Name: "한맥가족", Type: domain.TenantTypeCompanyGroup},
{ID: baronGroupID, Slug: "baron-group", Name: "바론그룹", Type: domain.TenantTypeCompanyGroup, ParentID: &rootID},
{ID: orgID, Slug: "rnd-baron", Name: "바론기술개발센터(조직도용)", Type: domain.TenantTypeOrganization, ParentID: &baronGroupID},
}
remoteGroups := []WorksmobileRemoteGroup{
{
ID: "works-rnd-baron",
ExternalID: orgID,
DisplayName: "바론기술개발센터(조직도용)",
DomainID: 1004,
DomainName: "바론그룹",
},
}
diffOnly := compareWorksmobileGroups(localTenants, remoteGroups, false)
all := compareWorksmobileGroups(localTenants, remoteGroups, true)
require.Empty(t, diffOnly)
require.Len(t, all, 1)
require.Equal(t, orgID, all[0].BaronID)
require.Equal(t, "matched", all[0].Status)
require.Equal(t, int64(1004), all[0].WorksmobileDomainID)
}
func TestWorksmobileSyncServiceRejectsDomainCompanyOrgUnitSync(t *testing.T) {
@@ -733,6 +884,108 @@ func TestWorksmobileSyncServiceTreatsHanmacFamilyChildCompaniesAsDomainRoots(t *
}
}
func TestWorksmobileSyncServiceUsesBaronGroupDomainForBaronGroupChildOrganization(t *testing.T) {
t.Setenv("GPDTDC_DOMAIN_ID", "1003")
t.Setenv("BARONGROUP_DOMAIN_ID", "1004")
rootID := "038326b6-954a-48a7-a85f-efd83f62b82a"
baronGroupID := "96369f12-6b66-4b2a-a916-d1c99d326f02"
orgID := "32464fd6-da51-473f-844a-ab88603ad1f0"
root := domain.Tenant{
ID: rootID,
Slug: HanmacFamilyTenantSlug,
Name: "한맥가족",
Type: domain.TenantTypeCompanyGroup,
}
baronGroup := domain.Tenant{
ID: baronGroupID,
Slug: "baron-group",
Name: "바론그룹",
Type: domain.TenantTypeCompanyGroup,
ParentID: &rootID,
}
organization := domain.Tenant{
ID: orgID,
Slug: "rnd-baron",
Name: "바론기술개발센터(조직도용)",
Type: domain.TenantTypeOrganization,
ParentID: &baronGroupID,
}
outboxRepo := &fakeWorksmobileOutboxRepo{}
service := NewWorksmobileSyncService(
&fakeWorksmobileTenantService{
tenants: map[string]domain.Tenant{
root.ID: root,
baronGroup.ID: baronGroup,
organization.ID: organization,
},
list: []domain.Tenant{root, baronGroup, organization},
},
&fakeWorksmobileUserRepo{},
outboxRepo,
nil,
)
item, err := service.EnqueueOrgUnitSync(context.Background(), rootID, organization.ID)
require.NoError(t, err)
require.NotNil(t, item)
require.Len(t, outboxRepo.created, 1)
request := outboxRepo.created[0].Payload["request"].(WorksmobileOrgUnitPayload)
require.Equal(t, int64(1004), request.DomainID)
require.Equal(t, "rnd-baron@brsw.kr", request.Email)
}
func TestWorksmobileSyncServiceUsesGPDTDCDomainForGPDTDCChildOrganization(t *testing.T) {
t.Setenv("GPDTDC_DOMAIN_ID", "1003")
t.Setenv("BARONGROUP_DOMAIN_ID", "1004")
rootID := "038326b6-954a-48a7-a85f-efd83f62b82a"
gpdtdcID := "5530ca6e-c5e6-4bf0-84d6-76c6a8fb70ee"
orgID := "gpdtdc-child-organization"
root := domain.Tenant{
ID: rootID,
Slug: HanmacFamilyTenantSlug,
Name: "한맥가족",
Type: domain.TenantTypeCompanyGroup,
}
gpdtdc := domain.Tenant{
ID: gpdtdcID,
Slug: "gpdtdc",
Name: "총괄기획&기술개발센터",
Type: domain.TenantTypeOrganization,
ParentID: &rootID,
}
organization := domain.Tenant{
ID: orgID,
Slug: "planning",
Name: "기획",
Type: domain.TenantTypeOrganization,
ParentID: &gpdtdcID,
}
outboxRepo := &fakeWorksmobileOutboxRepo{}
service := NewWorksmobileSyncService(
&fakeWorksmobileTenantService{
tenants: map[string]domain.Tenant{
root.ID: root,
gpdtdc.ID: gpdtdc,
organization.ID: organization,
},
list: []domain.Tenant{root, gpdtdc, organization},
},
&fakeWorksmobileUserRepo{},
outboxRepo,
nil,
)
item, err := service.EnqueueOrgUnitSync(context.Background(), rootID, organization.ID)
require.NoError(t, err)
require.NotNil(t, item)
require.Len(t, outboxRepo.created, 1)
request := outboxRepo.created[0].Payload["request"].(WorksmobileOrgUnitPayload)
require.Equal(t, int64(1003), request.DomainID)
require.Equal(t, "planning@baroncs.co.kr", request.Email)
}
func TestWorksmobileDomainClassificationUsesAncestorCompanyForGPDTDCOrganization(t *testing.T) {
t.Setenv("GPDTDC_DOMAIN_ID", "1003")
rootID := "root-tenant"