forked from baron/baron-sso
feat: improve Worksmobile tenant sync handling
This commit is contained in:
@@ -494,6 +494,70 @@ func TestWorksmobileSyncServiceOverviewKeepsSafeRecentJobChangeLogPayload(t *tes
|
||||
}, orgPayload["requestSummary"])
|
||||
}
|
||||
|
||||
func TestWorksmobileSyncServiceEnqueueTenantUpsertReflectsChangedParentOrgUnit(t *testing.T) {
|
||||
t.Setenv("SAMAN_DOMAIN_ID", "1001")
|
||||
rootID := "root-tenant"
|
||||
companyID := "saman-tenant"
|
||||
newParentID := "new-parent-org"
|
||||
childID := "child-org"
|
||||
root := domain.Tenant{
|
||||
ID: rootID,
|
||||
Slug: HanmacFamilyTenantSlug,
|
||||
Name: "한맥가족",
|
||||
Type: domain.TenantTypeCompanyGroup,
|
||||
}
|
||||
company := domain.Tenant{
|
||||
ID: companyID,
|
||||
Slug: "saman",
|
||||
Name: "삼안",
|
||||
Type: domain.TenantTypeCompany,
|
||||
ParentID: &rootID,
|
||||
Domains: []domain.TenantDomain{{Domain: "samaneng.com"}},
|
||||
}
|
||||
newParent := domain.Tenant{
|
||||
ID: newParentID,
|
||||
Slug: "planning",
|
||||
Name: "총괄기획",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
ParentID: &companyID,
|
||||
}
|
||||
child := domain.Tenant{
|
||||
ID: childID,
|
||||
Slug: "people-growth",
|
||||
Name: "인재성장",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
ParentID: &newParentID,
|
||||
}
|
||||
outboxRepo := &fakeWorksmobileOutboxRepo{}
|
||||
service := NewWorksmobileSyncService(
|
||||
&fakeWorksmobileTenantService{
|
||||
tenants: map[string]domain.Tenant{
|
||||
rootID: root,
|
||||
companyID: company,
|
||||
newParentID: newParent,
|
||||
childID: child,
|
||||
},
|
||||
list: []domain.Tenant{root, company, newParent, child},
|
||||
},
|
||||
&fakeWorksmobileUserRepo{},
|
||||
outboxRepo,
|
||||
nil,
|
||||
)
|
||||
|
||||
err := service.EnqueueTenantUpsertIfInScope(context.Background(), child)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, outboxRepo.created, 1)
|
||||
require.Equal(t, domain.WorksmobileResourceOrgUnit, outboxRepo.created[0].ResourceType)
|
||||
require.Equal(t, domain.WorksmobileActionUpsert, outboxRepo.created[0].Action)
|
||||
require.Equal(t, childID, outboxRepo.created[0].ResourceID)
|
||||
request, ok := outboxRepo.created[0].Payload["request"].(WorksmobileOrgUnitPayload)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, childID, request.OrgUnitExternalKey)
|
||||
require.Equal(t, "externalKey:"+newParentID, request.ParentOrgUnitID)
|
||||
require.Equal(t, "people-growth", outboxRepo.created[0].Payload["matchLocalPart"])
|
||||
}
|
||||
|
||||
func TestCompareWorksmobileGroupsUsesOrganizationsAndBarongroupChildCompanies(t *testing.T) {
|
||||
parentID := "root-tenant"
|
||||
root := domain.Tenant{
|
||||
@@ -1085,10 +1149,34 @@ func TestWorksmobileSyncServiceRejectsProtectedDomainRootOrgUnitDelete(t *testin
|
||||
require.Empty(t, outboxRepo.created)
|
||||
}
|
||||
|
||||
func TestWorksmobileSyncServiceDeletesPendingJobsForTenantRoot(t *testing.T) {
|
||||
rootID := "root-tenant"
|
||||
root := domain.Tenant{
|
||||
ID: rootID,
|
||||
Slug: HanmacFamilyTenantSlug,
|
||||
Name: "한맥가족",
|
||||
}
|
||||
outboxRepo := &fakeWorksmobileOutboxRepo{deletedPendingCount: 2}
|
||||
service := NewWorksmobileSyncService(
|
||||
&fakeWorksmobileTenantService{tenants: map[string]domain.Tenant{rootID: root}, list: []domain.Tenant{root}},
|
||||
&fakeWorksmobileUserRepo{},
|
||||
outboxRepo,
|
||||
nil,
|
||||
)
|
||||
|
||||
result, err := service.DeletePendingJobs(context.Background(), rootID)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, result.DeletedCount)
|
||||
require.Equal(t, rootID, outboxRepo.deletedPendingTenantRootID)
|
||||
}
|
||||
|
||||
func TestWorksmobileSyncServiceTreatsHanmacFamilyChildCompaniesAsDomainRoots(t *testing.T) {
|
||||
t.Setenv("SAMAN_DOMAIN_ID", "1001")
|
||||
t.Setenv("HANMAC_DOMAIN_ID", "1002")
|
||||
t.Setenv("GPDTDC_DOMAIN_ID", "1003")
|
||||
t.Setenv("HALLA_DOMAIN_ID", "1005")
|
||||
t.Setenv("WORKS_DEFAULT_DOMAIN_HALLA", "hallasanup.com")
|
||||
t.Setenv("BARONGROUP_DOMAIN_ID", "1004")
|
||||
rootID := "root-tenant"
|
||||
root := domain.Tenant{
|
||||
@@ -1177,6 +1265,43 @@ func TestWorksmobileSyncServiceTreatsHanmacFamilyChildCompaniesAsDomainRoots(t *
|
||||
wantDomainID: 1004,
|
||||
wantEmail: "baron-planning@brsw.kr",
|
||||
},
|
||||
{
|
||||
name: "halla",
|
||||
company: domain.Tenant{
|
||||
ID: "company-halla",
|
||||
Slug: "halla",
|
||||
Name: "한라산업개발",
|
||||
Type: domain.TenantTypeCompany,
|
||||
ParentID: &rootID,
|
||||
Domains: []domain.TenantDomain{{Domain: "hallasanup.com"}},
|
||||
},
|
||||
organization: domain.Tenant{
|
||||
ID: "org-halla-planning",
|
||||
Slug: "halla-planning",
|
||||
Name: "한라 기획팀",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
},
|
||||
wantDomainID: 1005,
|
||||
wantEmail: "halla-planning@hallasanup.com",
|
||||
},
|
||||
{
|
||||
name: "hanlla legacy slug",
|
||||
company: domain.Tenant{
|
||||
ID: "company-hanlla",
|
||||
Slug: "hanlla",
|
||||
Name: "한라산업개발",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
ParentID: &rootID,
|
||||
},
|
||||
organization: domain.Tenant{
|
||||
ID: "org-hanlla-construction-sites",
|
||||
Slug: "hanlla-construction-sites",
|
||||
Name: "시공현장",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
},
|
||||
wantDomainID: 1005,
|
||||
wantEmail: "hanlla-construction-sites@hallasanup.com",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -1467,6 +1592,181 @@ func TestWorksmobileSyncServiceBackfillDryRunSkipsArchivedUsers(t *testing.T) {
|
||||
require.Equal(t, 1, outboxRepo.created[0].Payload["userCount"])
|
||||
}
|
||||
|
||||
func TestWorksmobileSyncServiceBackfillDryRunSkipsWorksmobileExcludedSubtree(t *testing.T) {
|
||||
rootID := "root-tenant"
|
||||
excludedCompanyID := "excluded-company"
|
||||
excludedOrgID := "excluded-org"
|
||||
includedCompanyID := "included-company"
|
||||
includedOrgID := "included-org"
|
||||
root := domain.Tenant{
|
||||
ID: rootID,
|
||||
Slug: HanmacFamilyTenantSlug,
|
||||
Name: "한맥가족",
|
||||
}
|
||||
excludedCompany := domain.Tenant{
|
||||
ID: excludedCompanyID,
|
||||
Slug: "saman",
|
||||
Name: "삼안",
|
||||
Type: domain.TenantTypeCompany,
|
||||
ParentID: &rootID,
|
||||
Config: domain.JSONMap{"worksmobileExcluded": true},
|
||||
}
|
||||
excludedOrg := domain.Tenant{
|
||||
ID: excludedOrgID,
|
||||
Slug: "excluded-team",
|
||||
Name: "제외팀",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
ParentID: &excludedCompanyID,
|
||||
}
|
||||
includedCompany := domain.Tenant{
|
||||
ID: includedCompanyID,
|
||||
Slug: "halla",
|
||||
Name: "한라산업개발",
|
||||
Type: domain.TenantTypeCompany,
|
||||
ParentID: &rootID,
|
||||
}
|
||||
includedOrg := domain.Tenant{
|
||||
ID: includedOrgID,
|
||||
Slug: "included-team",
|
||||
Name: "연동팀",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
ParentID: &includedCompanyID,
|
||||
}
|
||||
excludedUser := domain.User{
|
||||
ID: "excluded-user",
|
||||
Email: "excluded@samaneng.com",
|
||||
Name: "Excluded User",
|
||||
TenantID: &excludedOrgID,
|
||||
Status: domain.UserStatusActive,
|
||||
}
|
||||
includedUser := domain.User{
|
||||
ID: "included-user",
|
||||
Email: "included@hallasanup.com",
|
||||
Name: "Included User",
|
||||
TenantID: &includedOrgID,
|
||||
Status: domain.UserStatusActive,
|
||||
}
|
||||
outboxRepo := &fakeWorksmobileOutboxRepo{}
|
||||
service := NewWorksmobileSyncService(
|
||||
&fakeWorksmobileTenantService{
|
||||
tenants: map[string]domain.Tenant{
|
||||
rootID: root,
|
||||
excludedCompanyID: excludedCompany,
|
||||
excludedOrgID: excludedOrg,
|
||||
includedCompanyID: includedCompany,
|
||||
includedOrgID: includedOrg,
|
||||
},
|
||||
list: []domain.Tenant{root, excludedCompany, excludedOrg, includedCompany, includedOrg},
|
||||
},
|
||||
&fakeWorksmobileUserRepo{byTenant: []domain.User{excludedUser, includedUser}},
|
||||
outboxRepo,
|
||||
nil,
|
||||
)
|
||||
|
||||
dryRun, err := service.EnqueueBackfillDryRun(context.Background(), rootID)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, dryRun.OrgUnitCount)
|
||||
require.Equal(t, 1, dryRun.UserCount)
|
||||
require.Len(t, outboxRepo.created, 1)
|
||||
require.ElementsMatch(t, []string{includedOrgID}, outboxRepo.created[0].Payload["tenantIds"])
|
||||
require.Equal(t, 1, outboxRepo.created[0].Payload["userCount"])
|
||||
}
|
||||
|
||||
func TestWorksmobileSyncServiceRejectsExcludedOrgUnitSync(t *testing.T) {
|
||||
rootID := "root-tenant"
|
||||
excludedCompanyID := "excluded-company"
|
||||
excludedOrgID := "excluded-org"
|
||||
root := domain.Tenant{
|
||||
ID: rootID,
|
||||
Slug: HanmacFamilyTenantSlug,
|
||||
Name: "한맥가족",
|
||||
}
|
||||
excludedCompany := domain.Tenant{
|
||||
ID: excludedCompanyID,
|
||||
Slug: "saman",
|
||||
Name: "삼안",
|
||||
Type: domain.TenantTypeCompany,
|
||||
ParentID: &rootID,
|
||||
Config: domain.JSONMap{"worksmobileExcluded": true},
|
||||
}
|
||||
excludedOrg := domain.Tenant{
|
||||
ID: excludedOrgID,
|
||||
Slug: "excluded-team",
|
||||
Name: "제외팀",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
ParentID: &excludedCompanyID,
|
||||
}
|
||||
outboxRepo := &fakeWorksmobileOutboxRepo{}
|
||||
service := NewWorksmobileSyncService(
|
||||
&fakeWorksmobileTenantService{
|
||||
tenants: map[string]domain.Tenant{rootID: root, excludedCompanyID: excludedCompany, excludedOrgID: excludedOrg},
|
||||
list: []domain.Tenant{root, excludedCompany, excludedOrg},
|
||||
},
|
||||
&fakeWorksmobileUserRepo{},
|
||||
outboxRepo,
|
||||
nil,
|
||||
)
|
||||
|
||||
item, err := service.EnqueueOrgUnitSync(context.Background(), rootID, excludedOrgID)
|
||||
|
||||
require.Nil(t, item)
|
||||
require.ErrorContains(t, err, "excluded from Worksmobile sync")
|
||||
require.Empty(t, outboxRepo.created)
|
||||
}
|
||||
|
||||
func TestWorksmobileSyncServiceSkipsExcludedTenantAndUserEventSync(t *testing.T) {
|
||||
rootID := "root-tenant"
|
||||
excludedCompanyID := "excluded-company"
|
||||
excludedOrgID := "excluded-org"
|
||||
root := domain.Tenant{
|
||||
ID: rootID,
|
||||
Slug: HanmacFamilyTenantSlug,
|
||||
Name: "한맥가족",
|
||||
}
|
||||
excludedCompany := domain.Tenant{
|
||||
ID: excludedCompanyID,
|
||||
Slug: "saman",
|
||||
Name: "삼안",
|
||||
Type: domain.TenantTypeCompany,
|
||||
ParentID: &rootID,
|
||||
Config: domain.JSONMap{"worksmobileExcluded": true},
|
||||
}
|
||||
excludedOrg := domain.Tenant{
|
||||
ID: excludedOrgID,
|
||||
Slug: "excluded-team",
|
||||
Name: "제외팀",
|
||||
Type: domain.TenantTypeOrganization,
|
||||
ParentID: &excludedCompanyID,
|
||||
}
|
||||
user := domain.User{
|
||||
ID: "excluded-user",
|
||||
Email: "excluded@samaneng.com",
|
||||
Name: "Excluded User",
|
||||
TenantID: &excludedOrgID,
|
||||
Status: domain.UserStatusActive,
|
||||
}
|
||||
outboxRepo := &fakeWorksmobileOutboxRepo{}
|
||||
service := NewWorksmobileSyncService(
|
||||
&fakeWorksmobileTenantService{
|
||||
tenants: map[string]domain.Tenant{rootID: root, excludedCompanyID: excludedCompany, excludedOrgID: excludedOrg},
|
||||
list: []domain.Tenant{root, excludedCompany, excludedOrg},
|
||||
},
|
||||
&fakeWorksmobileUserRepo{byID: map[string]domain.User{user.ID: user}},
|
||||
outboxRepo,
|
||||
nil,
|
||||
)
|
||||
|
||||
require.NoError(t, service.EnqueueTenantUpsertIfInScope(context.Background(), excludedOrg))
|
||||
require.NoError(t, service.EnqueueTenantDeleteIfInScope(context.Background(), excludedOrg))
|
||||
require.NoError(t, service.EnqueueUserUpsertIfInScope(context.Background(), user))
|
||||
item, err := service.EnqueueUserSync(context.Background(), rootID, user.ID, "")
|
||||
|
||||
require.Nil(t, item)
|
||||
require.ErrorContains(t, err, "excluded from Worksmobile sync")
|
||||
require.Empty(t, outboxRepo.created)
|
||||
}
|
||||
|
||||
func TestCompareWorksmobileUsersMarksManagerChangeNeedsUpdate(t *testing.T) {
|
||||
tenantID := "tenant-leaf"
|
||||
user := domain.User{
|
||||
@@ -1751,7 +2051,23 @@ func (f *fakeWorksmobileUserRepo) CountByCompanyCodes(ctx context.Context, codes
|
||||
|
||||
func (f *fakeWorksmobileUserRepo) FindByTenantIDs(ctx context.Context, tenantIDs []string) ([]domain.User, error) {
|
||||
f.requestedTenantIDs = append([]string(nil), tenantIDs...)
|
||||
return f.byTenant, nil
|
||||
if len(tenantIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
allowed := make(map[string]bool, len(tenantIDs))
|
||||
for _, tenantID := range tenantIDs {
|
||||
allowed[tenantID] = true
|
||||
}
|
||||
users := make([]domain.User, 0, len(f.byTenant))
|
||||
for _, user := range f.byTenant {
|
||||
if user.TenantID == nil {
|
||||
continue
|
||||
}
|
||||
if allowed[*user.TenantID] {
|
||||
users = append(users, user)
|
||||
}
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (f *fakeWorksmobileUserRepo) FindByCompanyCodes(ctx context.Context, codes []string) ([]domain.User, error) {
|
||||
|
||||
Reference in New Issue
Block a user