1
0
forked from baron/baron-sso

merge: integrate origin dev into dev

Includes Worksmobile SSOT sync comparison updates, UUID import conflict resolution, and Playwright route mock stabilization.
This commit is contained in:
2026-06-01 17:48:39 +09:00
91 changed files with 2173 additions and 1268 deletions

View File

@@ -778,7 +778,7 @@ type WorksmobileUserPatchPayload struct {
DomainID int64 `json:"domainId"`
Email string `json:"email,omitempty"`
UserExternalKey string `json:"userExternalKey,omitempty"`
UserName WorksmobileUserName `json:"userName,omitempty"`
UserName WorksmobileUserName `json:"userName"`
CellPhone string `json:"cellPhone,omitempty"`
EmployeeNumber string `json:"employeeNumber,omitempty"`
AliasEmails []string `json:"aliasEmails,omitempty"`
@@ -797,23 +797,26 @@ type WorksmobileOrgUnitPatchPayload struct {
}
type WorksmobileRemoteUser struct {
ID string `json:"id"`
ExternalID string `json:"externalId"`
UserName string `json:"userName"`
Email string `json:"email"`
DisplayName string `json:"displayName"`
LevelID string `json:"levelId"`
LevelName string `json:"levelName"`
Task string `json:"task"`
DomainID int64 `json:"domainId"`
DomainName string `json:"domainName"`
PrimaryOrgUnitID string `json:"primaryOrgUnitId"`
PrimaryOrgUnitName string `json:"primaryOrgUnitName"`
PrimaryOrgUnitPositionID string `json:"primaryOrgUnitPositionId"`
PrimaryOrgUnitPositionName string `json:"primaryOrgUnitPositionName"`
PrimaryOrgUnitIsManager *bool `json:"primaryOrgUnitIsManager,omitempty"`
OrgUnitManagers map[string]*bool `json:"orgUnitManagers,omitempty"`
Active bool `json:"active"`
ID string `json:"id"`
ExternalID string `json:"externalId"`
UserName string `json:"userName"`
Email string `json:"email"`
DisplayName string `json:"displayName"`
CellPhone string `json:"cellPhone,omitempty"`
EmployeeNumber string `json:"employeeNumber,omitempty"`
LevelID string `json:"levelId"`
LevelName string `json:"levelName"`
Task string `json:"task"`
DomainID int64 `json:"domainId"`
DomainName string `json:"domainName"`
PrimaryOrgUnitID string `json:"primaryOrgUnitId"`
PrimaryOrgUnitName string `json:"primaryOrgUnitName"`
PrimaryOrgUnitPositionID string `json:"primaryOrgUnitPositionId"`
PrimaryOrgUnitPositionName string `json:"primaryOrgUnitPositionName"`
PrimaryOrgUnitIsManager *bool `json:"primaryOrgUnitIsManager,omitempty"`
OrgUnitManagers map[string]*bool `json:"orgUnitManagers,omitempty"`
Organizations []WorksmobileUserOrganization `json:"organizations,omitempty"`
Active bool `json:"active"`
}
type WorksmobileRemoteGroup struct {
@@ -935,10 +938,18 @@ func parseWorksmobileDirectoryUser(resource map[string]any) WorksmobileRemoteUse
UserName: email,
Email: email,
DisplayName: parseWorksmobileDirectoryUserName(resource),
LevelID: parseWorksmobileUserLevelID(resource),
LevelName: parseWorksmobileUserLevelName(resource),
Task: firstStringFromMap(resource, "task", "job", "jobDescription"),
Active: true,
CellPhone: firstStringFromMap(resource, "cellPhone", "phoneNumber", "phone", "mobile", "mobilePhone"),
EmployeeNumber: firstStringFromMap(
resource,
"employeeNumber",
"employeeNo",
"employeeId",
"employeeID",
),
LevelID: parseWorksmobileUserLevelID(resource),
LevelName: parseWorksmobileUserLevelName(resource),
Task: firstStringFromMap(resource, "task", "job", "jobDescription"),
Active: true,
}
if active, ok := resource["active"].(bool); ok {
user.Active = active
@@ -950,6 +961,7 @@ func parseWorksmobileDirectoryUser(resource map[string]any) WorksmobileRemoteUse
user.PrimaryOrgUnitPositionName = primaryOrgUnit.PositionName
user.PrimaryOrgUnitIsManager = primaryOrgUnit.IsManager
user.OrgUnitManagers = parseWorksmobileOrgUnitManagers(resource)
user.Organizations = parseWorksmobileUserOrganizations(resource)
return user
}
@@ -1072,6 +1084,84 @@ func parseWorksmobilePrimaryOrgUnitDetail(resource map[string]any) worksmobileOr
return worksmobileOrgUnitDetail{}
}
func parseWorksmobileUserOrganizations(resource map[string]any) []WorksmobileUserOrganization {
if organizations := parseWorksmobileUserOrganizationList(resource["organizations"]); len(organizations) > 0 {
return organizations
}
for key, raw := range resource {
if !strings.Contains(strings.ToLower(key), "works") {
continue
}
if values, ok := raw.(map[string]any); ok {
if organizations := parseWorksmobileUserOrganizationList(values["organizations"]); len(organizations) > 0 {
return organizations
}
}
}
return nil
}
func parseWorksmobileUserOrganizationList(raw any) []WorksmobileUserOrganization {
values, ok := raw.([]any)
if !ok {
return nil
}
organizations := make([]WorksmobileUserOrganization, 0, len(values))
for _, item := range values {
organization, ok := item.(map[string]any)
if !ok {
continue
}
orgUnits := parseWorksmobileUserOrgUnitList(organization["orgUnits"])
if len(orgUnits) == 0 {
continue
}
organizations = append(organizations, WorksmobileUserOrganization{
DomainID: int64FromMap(organization, "domainId"),
Email: firstStringFromMap(organization, "email"),
Primary: boolFromMap(organization, "primary"),
OrgUnits: orgUnits,
})
}
return organizations
}
func parseWorksmobileUserOrgUnitList(raw any) []WorksmobileUserOrgUnit {
values, ok := raw.([]any)
if !ok {
return nil
}
orgUnits := make([]WorksmobileUserOrgUnit, 0, len(values))
for _, item := range values {
orgUnit, ok := item.(map[string]any)
if !ok {
continue
}
id := firstStringFromMap(orgUnit, "orgUnitExternalKey", "externalKey")
if id != "" {
id = "externalKey:" + id
} else {
id = firstStringFromMap(orgUnit, "orgUnitId", "id", "value")
}
if id == "" {
if nested := parseWorksmobileUserOrgUnitList(orgUnit["orgUnits"]); len(nested) > 0 {
orgUnits = append(orgUnits, nested...)
}
continue
}
orgUnits = append(orgUnits, WorksmobileUserOrgUnit{
OrgUnitID: id,
Primary: boolFromMap(orgUnit, "primary"),
PositionID: firstStringFromMap(orgUnit, "positionId"),
IsManager: boolPointerFromMap(orgUnit, "isManager", "manager"),
})
if nested := parseWorksmobileUserOrgUnitList(orgUnit["orgUnits"]); len(nested) > 0 {
orgUnits = append(orgUnits, nested...)
}
}
return orgUnits
}
func parseWorksmobileOrgUnitManagers(resource map[string]any) map[string]*bool {
result := map[string]*bool{}
collectWorksmobileOrgUnitManagers(resource["organizations"], result)
@@ -1101,7 +1191,13 @@ func collectWorksmobileOrgUnitManagers(raw any, result map[string]*bool) {
if !ok {
continue
}
if id := firstStringFromMap(orgUnit, "orgUnitId", "id", "value"); id != "" {
id := firstStringFromMap(orgUnit, "orgUnitExternalKey", "externalKey")
if id != "" {
id = "externalKey:" + id
} else {
id = firstStringFromMap(orgUnit, "orgUnitId", "id", "value")
}
if id != "" {
result[id] = boolPointerFromMap(orgUnit, "isManager", "manager")
}
collectWorksmobileOrgUnitManagers(orgUnit["organizations"], result)
@@ -1194,6 +1290,19 @@ func boolFromMap(values map[string]any, key string) bool {
return value
}
func int64FromMap(values map[string]any, key string) int64 {
switch value := values[key].(type) {
case int:
return int64(value)
case int64:
return value
case float64:
return int64(value)
default:
return 0
}
}
func boolPointerFromMap(values map[string]any, keys ...string) *bool {
for _, key := range keys {
if value, ok := values[key].(bool); ok {