1
0
forked from baron/baron-sso
Files
baron-sso/backend/internal/service/worksmobile_mapper_test.go

384 lines
12 KiB
Go

package service
import (
"baron-sso-backend/internal/domain"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestBuildWorksmobileOrgUnitPayloadUsesTenantExternalKeyAndEnvDomainClassification(t *testing.T) {
t.Setenv("SAMAN_DOMAIN_ID", "1001")
parentID := "11111111-1111-1111-1111-111111111111"
tenant := domain.Tenant{
ID: "22222222-2222-2222-2222-222222222222",
Slug: "tech-dev-center",
Name: "Saman Engineering",
ParentID: &parentID,
Domains: []domain.TenantDomain{
{Domain: "samaneng.com"},
},
}
rootConfig := domain.JSONMap{
"worksmobile": map[string]any{
"domainMappings": map[string]any{
"samaneng.com": float64(9999),
},
},
}
payload, err := BuildWorksmobileOrgUnitPayload(tenant, rootConfig, 7)
require.NoError(t, err)
require.Equal(t, int64(1001), payload.DomainID)
require.Equal(t, "Saman Engineering", payload.OrgUnitName)
require.Equal(t, "tech-dev-center@samaneng.com", payload.Email)
require.Equal(t, tenant.ID, payload.OrgUnitExternalKey)
require.Equal(t, "externalKey:"+parentID, payload.ParentOrgUnitID)
require.Equal(t, 7, payload.DisplayOrder)
}
func TestBuildWorksmobileOrgUnitPayloadUsesWorksmobileMailDomainForBarongroup(t *testing.T) {
t.Setenv("BARONGROUP_DOMAIN_ID", "1004")
tenant := domain.Tenant{
ID: "11111111-1111-1111-1111-111111111111",
Slug: "jangheon",
Name: "(주)장헌",
Type: domain.TenantTypeCompany,
Domains: []domain.TenantDomain{{Domain: "jangheon.com"}},
}
payload, err := BuildWorksmobileOrgUnitPayloadForDomainTenant(tenant, tenant, nil, 1)
require.NoError(t, err)
require.Equal(t, int64(1004), payload.DomainID)
require.Equal(t, "jangheon@brsw.kr", payload.Email)
}
func TestBuildWorksmobileOrgUnitPayloadDefaultsDisplayOrderToOne(t *testing.T) {
t.Setenv("SAMAN_DOMAIN_ID", "1001")
tenant := domain.Tenant{
ID: "11111111-1111-1111-1111-111111111111",
Slug: "tech-dev-center",
Name: "기술개발센터",
Domains: []domain.TenantDomain{{Domain: "samaneng.com"}},
}
payload, err := BuildWorksmobileOrgUnitPayload(tenant, nil, 0)
require.NoError(t, err)
require.Equal(t, 1, payload.DisplayOrder)
}
func TestNormalizeRootChildWorksmobileOrgUnitParentClearsCrossDomainParent(t *testing.T) {
rootID := "038326b6-954a-48a7-a85f-efd83f62b82a"
payload := WorksmobileOrgUnitPayload{ParentOrgUnitID: "externalKey:" + rootID}
tenant := domain.Tenant{ParentID: &rootID}
normalized := normalizeWorksmobileOrgUnitParent(payload, tenant, nil, rootID)
require.Empty(t, normalized.ParentOrgUnitID)
}
func TestBuildWorksmobileUserPayloadMapsBaronUserAndPrimaryTenant(t *testing.T) {
t.Setenv("SAMAN_DOMAIN_ID", "1001")
tenantID := "33333333-3333-3333-3333-333333333333"
user := domain.User{
ID: "44444444-4444-4444-4444-444444444444",
Email: "john1@samaneng.com",
Name: "John Doe",
Phone: "+19144812222",
Position: "Manager",
JobTitle: "Sales management",
TenantID: &tenantID,
Metadata: domain.JSONMap{
"employee_id": "AB001",
},
}
tenant := domain.Tenant{
ID: tenantID,
Slug: "saman",
Name: "Saman",
Domains: []domain.TenantDomain{{Domain: "samaneng.com"}},
}
rootConfig := domain.JSONMap{
"worksmobile": map[string]any{
"domainMappings": map[string]any{
"samaneng.com": int64(9999),
},
},
}
payload, err := BuildWorksmobileUserPayload(user, tenant, rootConfig)
require.NoError(t, err)
require.Equal(t, int64(1001), payload.DomainID)
require.Equal(t, "john1@samaneng.com", payload.Email)
require.Equal(t, user.ID, payload.UserExternalKey)
require.Equal(t, "John Doe", payload.UserName.LastName)
require.Equal(t, "+19144812222", payload.CellPhone)
require.Equal(t, "AB001", payload.EmployeeNumber)
require.Equal(t, "Sales management", payload.Task)
require.Empty(t, payload.PrivateEmail)
require.Empty(t, payload.AliasEmails)
require.Equal(t, "ko_KR", payload.Locale)
require.Equal(t, "ADMIN", payload.PasswordConfig.PasswordCreationType)
require.Len(t, payload.PasswordConfig.Password, 16)
require.True(t, containsAny(payload.PasswordConfig.Password, "0123456789"))
require.True(t, containsAny(payload.PasswordConfig.Password, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))
require.True(t, containsAny(payload.PasswordConfig.Password, "!@#$%^&*()-_=+[]{}"))
require.Len(t, payload.Organizations, 1)
require.Equal(t, int64(1001), payload.Organizations[0].DomainID)
require.True(t, payload.Organizations[0].Primary)
require.Equal(t, "externalKey:"+tenantID, payload.Organizations[0].OrgUnits[0].OrgUnitID)
}
func TestBuildWorksmobileUserPayloadMapsAdditionalAppointmentsToOrgUnits(t *testing.T) {
t.Setenv("SAMAN_DOMAIN_ID", "1001")
t.Setenv("HANMAC_DOMAIN_ID", "1002")
primaryTenantID := "33333333-3333-3333-3333-333333333333"
secondaryTenantID := "55555555-5555-5555-5555-555555555555"
user := domain.User{
ID: "44444444-4444-4444-4444-444444444444",
Email: "john1@samaneng.com",
Name: "John Doe",
Phone: "+19144812222",
TenantID: &primaryTenantID,
Metadata: domain.JSONMap{
"additionalAppointments": []any{
map[string]any{
"tenantId": secondaryTenantID,
"isPrimary": false,
"isOwner": true,
"jobTitle": "PM",
"position": "팀장",
},
map[string]any{
"tenantId": primaryTenantID,
"isPrimary": true,
"isOwner": false,
"jobTitle": "Engineering",
"position": "책임",
},
},
},
}
primaryTenant := domain.Tenant{
ID: primaryTenantID,
Slug: "saman",
Name: "Saman",
Domains: []domain.TenantDomain{{Domain: "samaneng.com"}},
}
secondaryTenant := domain.Tenant{
ID: secondaryTenantID,
Slug: "hanmac",
Name: "Hanmac",
Domains: []domain.TenantDomain{{Domain: "hanmaceng.co.kr"}},
}
payload, err := BuildWorksmobileUserPayloadForDomainTenants(
user,
primaryTenant,
map[string]domain.Tenant{
primaryTenantID: primaryTenant,
secondaryTenantID: secondaryTenant,
},
nil,
)
require.NoError(t, err)
require.Equal(t, "Engineering", payload.Task)
require.Len(t, payload.Organizations, 2)
require.Equal(t, int64(1001), payload.Organizations[0].DomainID)
require.True(t, payload.Organizations[0].Primary)
require.Equal(t, "externalKey:"+primaryTenantID, payload.Organizations[0].OrgUnits[0].OrgUnitID)
require.True(t, payload.Organizations[0].OrgUnits[0].Primary)
require.NotNil(t, payload.Organizations[0].OrgUnits[0].IsManager)
require.False(t, *payload.Organizations[0].OrgUnits[0].IsManager)
require.Equal(t, int64(1002), payload.Organizations[1].DomainID)
require.False(t, payload.Organizations[1].Primary)
require.Equal(t, "externalKey:"+secondaryTenantID, payload.Organizations[1].OrgUnits[0].OrgUnitID)
require.False(t, payload.Organizations[1].OrgUnits[0].Primary)
require.NotNil(t, payload.Organizations[1].OrgUnits[0].IsManager)
require.True(t, *payload.Organizations[1].OrgUnits[0].IsManager)
}
func TestResolveWorksmobileDomainIDFromTenantIgnoresRootDomainMappings(t *testing.T) {
t.Setenv("SAMAN_DOMAIN_ID", "1001")
rootConfig := domain.JSONMap{
"worksmobile": map[string]any{
"domainMappings": map[string]any{
"samaneng.com": int64(9999),
},
},
}
got, err := ResolveWorksmobileDomainIDFromTenant(
domain.Tenant{
Slug: "saman",
Name: "삼안",
Domains: []domain.TenantDomain{{Domain: "samaneng.com"}},
},
rootConfig,
)
require.NoError(t, err)
require.Equal(t, int64(1001), got)
}
func TestResolveWorksmobileDomainIDFromTenantRequiresFamilyDomainEnv(t *testing.T) {
t.Setenv("SAMAN_DOMAIN_ID", "")
rootConfig := domain.JSONMap{
"worksmobile": map[string]any{
"domainMappings": map[string]any{
"samaneng.com": int64(9999),
},
},
}
_, err := ResolveWorksmobileDomainIDFromTenant(
domain.Tenant{
Slug: "saman",
Name: "삼안",
Domains: []domain.TenantDomain{{Domain: "samaneng.com"}},
},
rootConfig,
)
require.Error(t, err)
require.Contains(t, err.Error(), "SAMAN_DOMAIN_ID")
}
func TestResolveWorksmobileDomainIDUsesEnvFamilyFallbacks(t *testing.T) {
t.Setenv("SAMAN_DOMAIN_ID", "1001")
t.Setenv("HANMAC_DOMAIN_ID", "1002")
t.Setenv("GPDTDC_DOMAIN_ID", "1003")
t.Setenv("BARONGROUP_DOMAIN_ID", "1004")
tests := []struct {
name string
tenant domain.Tenant
want int64
}{
{
name: "saman",
tenant: domain.Tenant{Slug: "saman", Domains: []domain.TenantDomain{{Domain: "samaneng.com"}}},
want: 1001,
},
{
name: "hanmac",
tenant: domain.Tenant{Slug: "hanmac", Domains: []domain.TenantDomain{{Domain: "hanmaceng.co.kr"}}},
want: 1002,
},
{
name: "gpdtdc",
tenant: domain.Tenant{Slug: "gpdtdc", Name: "총괄기획&기술개발센터"},
want: 1003,
},
{
name: "barongroup fallback",
tenant: domain.Tenant{Slug: "family-company", Name: "기타 가족사"},
want: 1004,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ResolveWorksmobileDomainIDFromTenant(tt.tenant, nil)
require.NoError(t, err)
require.Equal(t, tt.want, got)
})
}
}
func TestBuildWorksmobileUserPayloadAddsHanmacEmployeeAlias(t *testing.T) {
t.Setenv("HANMAC_DOMAIN_ID", "1002")
tenantID := "33333333-3333-3333-3333-333333333333"
user := domain.User{
ID: "44444444-4444-4444-4444-444444444444",
Email: "main@hanmaceng.co.kr",
Name: "Hanmac User",
TenantID: &tenantID,
Metadata: domain.JSONMap{
"employee_id": "HM001",
"personal_email": "private@example.com",
},
}
tenant := domain.Tenant{
ID: tenantID,
Slug: "hanmac",
Name: "한맥",
Domains: []domain.TenantDomain{{Domain: "hanmaceng.co.kr"}},
}
payload, err := BuildWorksmobileUserPayload(user, tenant, nil)
require.NoError(t, err)
require.Equal(t, int64(1002), payload.DomainID)
require.Equal(t, []string{"hm001@hanmaceng.co.kr"}, payload.AliasEmails)
require.Empty(t, payload.PrivateEmail)
require.Equal(t, "ko_KR", payload.Locale)
}
func TestBuildWorksmobileUserPayloadAddsMultipleMetadataAliases(t *testing.T) {
t.Setenv("SAMAN_DOMAIN_ID", "1001")
tenantID := "33333333-3333-3333-3333-333333333333"
user := domain.User{
ID: "44444444-4444-4444-4444-444444444444",
Email: "main@samaneng.com",
Name: "Saman User",
TenantID: &tenantID,
Metadata: domain.JSONMap{
"aliasEmails": []any{"alias1@samaneng.com", "alias2@samaneng.com", "main@samaneng.com"},
},
}
tenant := domain.Tenant{
ID: tenantID,
Slug: "saman",
Name: "삼안",
Domains: []domain.TenantDomain{{Domain: "samaneng.com"}},
}
payload, err := BuildWorksmobileUserPayload(user, tenant, nil)
require.NoError(t, err)
require.Equal(t, []string{"alias1@samaneng.com", "alias2@samaneng.com"}, payload.AliasEmails)
}
func TestValidateWorksmobileAliasLocalPartsRejectsPrimaryAndAliasCollisions(t *testing.T) {
err := ValidateWorksmobileAliasLocalParts(
"main@samaneng.com",
[]string{"main@hanmaceng.co.kr"},
map[string]string{},
)
require.Error(t, err)
require.Contains(t, err.Error(), "local-part")
err = ValidateWorksmobileAliasLocalParts(
"main@samaneng.com",
[]string{"alias@hanmaceng.co.kr"},
map[string]string{"alias": "existing-user"},
)
require.Error(t, err)
require.Contains(t, err.Error(), "이미 사용 중")
}
func containsAny(value string, candidates string) bool {
return strings.ContainsAny(value, candidates)
}
func TestWorksmobileUserStatusAction(t *testing.T) {
require.Equal(t, WorksmobileUserActionUpsert, WorksmobileUserStatusAction(domain.UserStatusActive))
require.Equal(t, WorksmobileUserActionSuspend, WorksmobileUserStatusAction(domain.UserStatusInactive))
require.Equal(t, WorksmobileUserActionSuspend, WorksmobileUserStatusAction(domain.UserStatusSuspended))
require.Equal(t, WorksmobileUserActionSuspend, WorksmobileUserStatusAction(domain.UserStatusLeaveOfAbsence))
}
func TestValidateWorksmobileExternalKeyRejectsUnsupportedCharacters(t *testing.T) {
require.NoError(t, ValidateWorksmobileExternalKey("44444444-4444-4444-4444-444444444444"))
require.Error(t, ValidateWorksmobileExternalKey("user/with/slash"))
require.Error(t, ValidateWorksmobileExternalKey("user#with-hash"))
}