forked from baron/baron-sso
네이버 웍스 연동기능 개선
This commit is contained in:
@@ -126,6 +126,13 @@ func TestWorksmobileLiveGPDTDCOrgUnitProvisioning(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestWorksmobileLiveBaronGroupOrgUnitProvisioning(t *testing.T) {
|
||||
if os.Getenv("WORKSMOBILE_LIVE_BARONGROUP_ORGUNIT_PROVISIONING") != "1" {
|
||||
t.Skip("live Worksmobile Baron Group orgunit provisioning is disabled")
|
||||
}
|
||||
runWorksmobileLiveBaronGroupOrgUnitProvisioning(t)
|
||||
}
|
||||
|
||||
func TestWorksmobileLiveSyncHanmacFamilyOrgUnits(t *testing.T) {
|
||||
if os.Getenv("WORKSMOBILE_LIVE_SYNC_HANMAC_FAMILY_ORGUNITS") != "1" {
|
||||
t.Skip("live Worksmobile Hanmac family orgunit sync is disabled")
|
||||
@@ -548,6 +555,142 @@ func runWorksmobileLiveCompanyOrgUnitProvisioning(t *testing.T, companySlug stri
|
||||
}
|
||||
}
|
||||
|
||||
func runWorksmobileLiveBaronGroupOrgUnitProvisioning(t *testing.T) {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
db, err := gorm.Open(postgres.Open(worksmobileLiveDSN()), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
|
||||
tenantRepo := repository.NewTenantRepository(db)
|
||||
userRepo := repository.NewUserRepository(db)
|
||||
userGroupRepo := repository.NewUserGroupRepository(db)
|
||||
tenantService := NewTenantService(tenantRepo, userRepo, userGroupRepo, nil)
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
})
|
||||
|
||||
baronGroup, err := tenantService.GetTenantBySlug(ctx, "baron-group")
|
||||
require.NoError(t, err)
|
||||
tenants, err := listWorksmobileLiveTenantScope(db, baronGroup.ID)
|
||||
require.NoError(t, err)
|
||||
domainID, ok := worksmobileDomainIDFromEnv("BARONGROUP_DOMAIN_ID")
|
||||
require.True(t, ok, "missing BARONGROUP_DOMAIN_ID")
|
||||
mailDomain := getenvDefault("BARONGROUP_MAIL_DOMAIN", getenvDefault("WORKS_DEFAULT_DOMAIN_BARONGROUP", "brsw.kr"))
|
||||
|
||||
tenantByID := worksmobileTenantByID(append([]domain.Tenant{*baronGroup}, tenants...))
|
||||
targets := worksmobileLiveBaronGroupOrgUnitTargets(t, tenants, tenantByID, *baronGroup, domainID, mailDomain)
|
||||
targetByID := map[string]worksmobileLiveOrgUnitTarget{}
|
||||
for _, target := range targets {
|
||||
targetByID[target.Tenant.ID] = target
|
||||
}
|
||||
|
||||
remoteGroups, err := client.ListGroups(ctx)
|
||||
require.NoError(t, err)
|
||||
remoteByExternalID, duplicateExternalKeys := worksmobileLiveRemoteByExternalID(remoteGroups)
|
||||
require.Empty(t, duplicateExternalKeys, "duplicate Worksmobile external keys")
|
||||
|
||||
for _, target := range sortWorksmobileLiveTargetsTopologically(targets, tenantByID) {
|
||||
remote, found := remoteByExternalID[target.Tenant.ID]
|
||||
if found && remote.DomainID != target.Payload.DomainID {
|
||||
t.Logf("REKEY conflicting external key slug=%s external=%s worksID=%s currentDomain=%d expectedDomain=%d", target.Tenant.Slug, target.Tenant.ID, remote.ID, remote.DomainID, target.Payload.DomainID)
|
||||
if err := client.ClearOrgUnitExternalKey(ctx, remote.ID, remote.DomainID); err != nil {
|
||||
legacyPatch := WorksmobileOrgUnitPatchPayload{
|
||||
DomainID: remote.DomainID,
|
||||
OrgUnitExternalKey: "legacy-" + remote.ID,
|
||||
}
|
||||
require.NoError(t, client.PatchOrgUnit(ctx, remote.ID, legacyPatch))
|
||||
}
|
||||
time.Sleep(1100 * time.Millisecond)
|
||||
remoteGroups, err = client.ListGroups(ctx)
|
||||
require.NoError(t, err)
|
||||
remoteByExternalID, duplicateExternalKeys = worksmobileLiveRemoteByExternalID(remoteGroups)
|
||||
require.Empty(t, duplicateExternalKeys, "duplicate Worksmobile external keys")
|
||||
remote, found = remoteByExternalID[target.Tenant.ID]
|
||||
if found && remote.DomainID != target.Payload.DomainID {
|
||||
require.Failf(t, "external key is attached to a different Worksmobile domain after rekey", "slug=%s external=%s currentDomain=%d expectedDomain=%d", target.Tenant.Slug, target.Tenant.ID, remote.DomainID, target.Payload.DomainID)
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
remote, found = findWorksmobileLiveRemoteByPath(remoteGroups, worksmobileLiveRemoteByID(remoteGroups), target.Payload.DomainID, worksmobileLiveTenantOrgPath(target.Tenant, tenantByID))
|
||||
}
|
||||
if found {
|
||||
t.Logf("PATCH orgunit slug=%s id=%s worksID=%s email=%s parent=%s", target.Tenant.Slug, target.Tenant.ID, remote.ID, target.Payload.Email, target.Payload.ParentOrgUnitID)
|
||||
require.NoError(t, patchWorksmobileLiveOrgUnit(ctx, client, remote.ID, target.Payload))
|
||||
} else {
|
||||
t.Logf("CREATE orgunit slug=%s id=%s email=%s parent=%s", target.Tenant.Slug, target.Tenant.ID, target.Payload.Email, target.Payload.ParentOrgUnitID)
|
||||
require.NoError(t, client.UpsertOrgUnit(ctx, target.Payload, target.Tenant.Slug))
|
||||
}
|
||||
time.Sleep(1100 * time.Millisecond)
|
||||
|
||||
remoteGroups, err = client.ListGroups(ctx)
|
||||
require.NoError(t, err)
|
||||
remoteByExternalID, duplicateExternalKeys = worksmobileLiveRemoteByExternalID(remoteGroups)
|
||||
require.Empty(t, duplicateExternalKeys, "duplicate Worksmobile external keys")
|
||||
}
|
||||
|
||||
remoteGroups, err = client.ListGroups(ctx)
|
||||
require.NoError(t, err)
|
||||
remoteByExternalID, duplicateExternalKeys = worksmobileLiveRemoteByExternalID(remoteGroups)
|
||||
require.Empty(t, duplicateExternalKeys, "duplicate Worksmobile external keys")
|
||||
remoteByID := worksmobileLiveRemoteByID(remoteGroups)
|
||||
for _, target := range targets {
|
||||
remote, ok := remoteByExternalID[target.Tenant.ID]
|
||||
require.True(t, ok, "missing Worksmobile orgunit after sync: %s", target.Tenant.Slug)
|
||||
require.Equal(t, target.Payload.DomainID, remote.DomainID, "domain mismatch: %s", target.Tenant.Slug)
|
||||
require.Equal(t, target.Tenant.Name, remote.DisplayName, "name mismatch: %s", target.Tenant.Slug)
|
||||
require.Equal(t, worksmobileMailLocalPart(target.Payload.Email), remote.MailLocalPart, "email local-part mismatch: %s", target.Tenant.Slug)
|
||||
require.Equal(t, strings.ToLower(strings.TrimSpace(target.Payload.Email)), strings.ToLower(strings.TrimSpace(remote.Email)), "email mismatch: %s", target.Tenant.Slug)
|
||||
expectedParentID := ""
|
||||
if parentExternalKey := strings.TrimPrefix(target.Payload.ParentOrgUnitID, "externalKey:"); parentExternalKey != "" && parentExternalKey != target.Payload.ParentOrgUnitID {
|
||||
parentRemote, ok := remoteByExternalID[parentExternalKey]
|
||||
require.True(t, ok, "missing Worksmobile parent for %s", target.Tenant.Slug)
|
||||
expectedParentID = parentRemote.ID
|
||||
parentTarget, ok := targetByID[parentExternalKey]
|
||||
require.True(t, ok, "missing Baron parent target for %s", target.Tenant.Slug)
|
||||
require.Equal(t, worksmobileMailLocalPart(parentTarget.Payload.Email), parentRemote.MailLocalPart, "parent email local-part mismatch: %s", target.Tenant.Slug)
|
||||
}
|
||||
require.Equal(t, expectedParentID, remote.ParentID, "parent mismatch: %s", target.Tenant.Slug)
|
||||
require.Equal(t, worksmobileLiveTenantOrgPath(target.Tenant, tenantByID), worksmobileLiveRemotePath(remoteByID, remote), "path mismatch: %s", target.Tenant.Slug)
|
||||
}
|
||||
|
||||
t.Logf("SUMMARY synced=%d domainID=%d", len(targets), domainID)
|
||||
}
|
||||
|
||||
func worksmobileLiveBaronGroupOrgUnitTargets(t *testing.T, tenants []domain.Tenant, tenantByID map[string]domain.Tenant, root domain.Tenant, domainID int64, mailDomain string) []worksmobileLiveOrgUnitTarget {
|
||||
t.Helper()
|
||||
mailDomain = strings.ToLower(strings.TrimSpace(mailDomain))
|
||||
require.NotEmpty(t, mailDomain, "baron group mail domain is required")
|
||||
targets := make([]worksmobileLiveOrgUnitTarget, 0)
|
||||
seenExternalKeys := map[string]string{}
|
||||
seenEmails := map[string]string{}
|
||||
for index, tenant := range tenants {
|
||||
if !isWorksmobileOrgUnitTenant(tenant, tenantByID) || worksmobileLiveSkipOrgUnitTenant(tenant) {
|
||||
continue
|
||||
}
|
||||
payload, err := BuildWorksmobileOrgUnitPayloadForDomainTenant(tenant, root, root.Config, index+1)
|
||||
require.NoError(t, err, "payload build failed: %s", tenant.Slug)
|
||||
payload = normalizeWorksmobileOrgUnitParent(payload, tenant, tenantByID, root.ID)
|
||||
payload.DomainID = domainID
|
||||
payload.Email = strings.ToLower(strings.TrimSpace(tenant.Slug)) + "@" + mailDomain
|
||||
require.NotEmpty(t, payload.Email, "orgunit email is required: %s", tenant.Slug)
|
||||
if owner, exists := seenExternalKeys[payload.OrgUnitExternalKey]; exists {
|
||||
require.Failf(t, "duplicate Baron external key", "external=%s owner=%s duplicate=%s", payload.OrgUnitExternalKey, owner, tenant.Slug)
|
||||
}
|
||||
seenExternalKeys[payload.OrgUnitExternalKey] = tenant.Slug
|
||||
normalizedEmail := strings.ToLower(strings.TrimSpace(payload.Email))
|
||||
if owner, exists := seenEmails[normalizedEmail]; exists {
|
||||
require.Failf(t, "duplicate Baron orgunit email", "email=%s owner=%s duplicate=%s", normalizedEmail, owner, tenant.Slug)
|
||||
}
|
||||
seenEmails[normalizedEmail] = tenant.Slug
|
||||
targets = append(targets, worksmobileLiveOrgUnitTarget{Tenant: tenant, Payload: payload})
|
||||
}
|
||||
return targets
|
||||
}
|
||||
|
||||
func createWorksmobileLiveOrgUnitIfMissing(t *testing.T, ctx context.Context, client *WorksmobileHTTPClient, tenant domain.Tenant) {
|
||||
t.Helper()
|
||||
payload, err := BuildWorksmobileOrgUnitPayload(tenant, nil, 1)
|
||||
|
||||
Reference in New Issue
Block a user