Add wsl linter and fix

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-05-19 14:51:08 +04:00
parent eedfdcecc8
commit 9156d6a16a
882 changed files with 6068 additions and 574 deletions

View File

@@ -67,6 +67,7 @@ func (s *Bridge) Run(ctx context.Context) (created, updated, deleted, deactivate
}
scimUsersByEmail := make(map[string]*scimclient.User)
for i := range scimUsers {
email := strings.ToLower(scimUsers[i].UserName)
scimUsersByEmail[email] = &scimUsers[i]
@@ -86,6 +87,7 @@ func (s *Bridge) Run(ctx context.Context) (created, updated, deleted, deactivate
errs = append(errs, fmt.Errorf("cannot create user %q: %w", pu.ExternalID, err))
continue
}
created++
} else {
needsUpdate := existingSCIM.Active != pu.Active ||
@@ -107,6 +109,7 @@ func (s *Bridge) Run(ctx context.Context) (created, updated, deleted, deactivate
errs = append(errs, fmt.Errorf("cannot update user %q: %w", pu.ExternalID, err))
continue
}
updated++
} else {
skipped++
@@ -124,7 +127,9 @@ func (s *Bridge) Run(ctx context.Context) (created, updated, deleted, deactivate
errs = append(errs, fmt.Errorf("cannot delete user %q: %w", scimUser.ExternalID, err))
continue
}
deleted++
continue
}
@@ -136,6 +141,7 @@ func (s *Bridge) Run(ctx context.Context) (created, updated, deleted, deactivate
errs = append(errs, fmt.Errorf("cannot deactivate user %q: %w", scimUser.ExternalID, err))
continue
}
deactivated++
}
@@ -148,5 +154,6 @@ func (s *Bridge) isExcluded(email string) bool {
return true
}
}
return false
}

View File

@@ -72,6 +72,7 @@ func NewClient(httpClient *http.Client, endpoint, token string) *Client {
func (c *Client) ListUsers(ctx context.Context) (Users, error) {
var allUsers Users
startIndex := 1
count := 100
@@ -107,6 +108,7 @@ func (c *Client) listUsersPage(ctx context.Context, startIndex, count int) (User
if err != nil {
return nil, 0, fmt.Errorf("cannot fetch users: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
@@ -131,6 +133,7 @@ func (c *Client) CreateUser(ctx context.Context, user *User) error {
}
reqURL := fmt.Sprintf("%s/Users", c.endpoint)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, reqURL, bytes.NewReader(body))
if err != nil {
return fmt.Errorf("cannot create request: %w", err)
@@ -143,6 +146,7 @@ func (c *Client) CreateUser(ctx context.Context, user *User) error {
if err != nil {
return fmt.Errorf("cannot create user: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
@@ -162,6 +166,7 @@ func (c *Client) UpdateUser(ctx context.Context, userID string, user *User) erro
}
reqURL := fmt.Sprintf("%s/Users/%s", c.endpoint, url.PathEscape(userID))
req, err := http.NewRequestWithContext(ctx, http.MethodPut, reqURL, bytes.NewReader(body))
if err != nil {
return fmt.Errorf("cannot create request: %w", err)
@@ -174,6 +179,7 @@ func (c *Client) UpdateUser(ctx context.Context, userID string, user *User) erro
if err != nil {
return fmt.Errorf("cannot update user: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
@@ -244,6 +250,7 @@ func (c *Client) DeactivateUser(ctx context.Context, userID string) error {
}
reqURL := fmt.Sprintf("%s/Users/%s", c.endpoint, url.PathEscape(userID))
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, reqURL, bytes.NewReader(body))
if err != nil {
return fmt.Errorf("cannot create request: %w", err)
@@ -256,6 +263,7 @@ func (c *Client) DeactivateUser(ctx context.Context, userID string) error {
if err != nil {
return fmt.Errorf("cannot deactivate user: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {
@@ -268,6 +276,7 @@ func (c *Client) DeactivateUser(ctx context.Context, userID string) error {
func (c *Client) DeleteUser(ctx context.Context, userID string) error {
reqURL := fmt.Sprintf("%s/Users/%s", c.endpoint, url.PathEscape(userID))
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, reqURL, nil)
if err != nil {
return fmt.Errorf("cannot create request: %w", err)
@@ -279,6 +288,7 @@ func (c *Client) DeleteUser(ctx context.Context, userID string) error {
if err != nil {
return fmt.Errorf("cannot delete user: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusNotFound {

View File

@@ -57,6 +57,7 @@ func TestUser_UnmarshalJSON(t *testing.T) {
}`)
var user scimclient.User
err := json.Unmarshal(data, &user)
require.NoError(t, err)
@@ -96,6 +97,7 @@ func TestUser_UnmarshalJSON(t *testing.T) {
}`)
var user scimclient.User
err := json.Unmarshal(data, &user)
require.NoError(t, err)
@@ -123,6 +125,7 @@ func TestUser_UnmarshalJSON(t *testing.T) {
}`)
var user scimclient.User
err := json.Unmarshal(data, &user)
require.NoError(t, err)

View File

@@ -55,6 +55,7 @@ func (p *Provider) isExcluded(email string) bool {
return true
}
}
return false
}
@@ -65,6 +66,7 @@ func (p *Provider) ListUsers(ctx context.Context) (scimclient.Users, error) {
}
var allUsers scimclient.Users
pageToken := ""
for {
@@ -128,12 +130,16 @@ func (p *Provider) extractOrganizationFields(raw any, user *scimclient.User) {
return
}
var primary *admin.UserOrganization
var first *admin.UserOrganization
var (
primary *admin.UserOrganization
first *admin.UserOrganization
)
for i := range orgs {
if first == nil {
first = &orgs[i]
}
if orgs[i].Primary {
primary = &orgs[i]
break
@@ -144,6 +150,7 @@ func (p *Provider) extractOrganizationFields(raw any, user *scimclient.User) {
if org == nil {
org = first
}
if org == nil {
return
}

View File

@@ -79,6 +79,7 @@ func (p *Provider) isExcluded(email string) bool {
return true
}
}
return false
}
@@ -115,6 +116,7 @@ func (p *Provider) ListUsers(ctx context.Context) (scimclient.Users, error) {
}
var allUsers scimclient.Users
for range graphMaxPages {
users, next, err := p.fetchPage(ctx, endpoint)
if err != nil {
@@ -126,9 +128,11 @@ func (p *Provider) ListUsers(ctx context.Context) (scimclient.Users, error) {
if email == "" {
email = u.UserPrincipalName
}
if email == "" {
continue
}
if p.isExcluded(email) {
continue
}
@@ -151,6 +155,7 @@ func (p *Provider) ListUsers(ctx context.Context) (scimclient.Users, error) {
if next == "" {
return allUsers, nil
}
endpoint = next
}
@@ -177,12 +182,14 @@ func (p *Provider) fetchPage(ctx context.Context, endpoint string) ([]graphUser,
if err != nil {
return nil, "", fmt.Errorf("cannot create graph users request: %w", err)
}
req.Header.Set("Accept", "application/json")
resp, err := p.httpClient.Do(req)
if err != nil {
return nil, "", fmt.Errorf("cannot list graph users: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {

View File

@@ -77,18 +77,23 @@ func NewBridgeRunner(
if cfg.Interval == 0 {
cfg.Interval = 15 * time.Minute
}
if cfg.PollInterval == 0 {
cfg.PollInterval = 30 * time.Second
}
if cfg.SyncTimeout == 0 {
cfg.SyncTimeout = 5 * time.Minute
}
if cfg.MaxBackoff == 0 {
cfg.MaxBackoff = DefaultMaxBackoff
}
if cfg.MaxConsecutiveFailures == 0 {
cfg.MaxConsecutiveFailures = DefaultMaxConsecutiveFailures
}
if cfg.StaleSyncThreshold == 0 {
cfg.StaleSyncThreshold = DefaultStaleSyncThreshold
}
@@ -161,6 +166,7 @@ func (r *BridgeRunner) processBridge(ctx context.Context) error {
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, "sync failed")
return r.transitionToFailed(ctx, bridge, scope, err, duration, logger)
}

View File

@@ -37,6 +37,7 @@ func (r *BridgeRunner) calculateBackoff(consecutiveFailures int) time.Duration {
// Cap the shift exponent to prevent integer overflow from the shift itself.
// Bit 63 is the sign bit, so shifting by 63+ produces negative or zero values.
const maxShift = 62
shiftAmount := min(consecutiveFailures, maxShift)
backoff := r.cfg.Interval * time.Duration(1<<shiftAmount)

View File

@@ -33,8 +33,10 @@ type SyncStats struct {
}
func (r *BridgeRunner) acquireNextBridge(ctx context.Context) (*coredata.SCIMBridge, coredata.Scoper, error) {
var bridge *coredata.SCIMBridge
var scope coredata.Scoper
var (
bridge *coredata.SCIMBridge
scope coredata.Scoper
)
err := r.pg.WithTx(
ctx,
@@ -53,7 +55,6 @@ func (r *BridgeRunner) acquireNextBridge(ctx context.Context) (*coredata.SCIMBri
return bridge.Update(ctx, tx, scope)
},
)
if err != nil {
return nil, nil, err
}
@@ -90,6 +91,7 @@ func (r *BridgeRunner) transitionToSuccess(
"cannot update bridge after successful sync",
log.Error(err),
)
return err
}
@@ -178,6 +180,7 @@ func (r *BridgeRunner) transitionToFailed(
log.String("new_state", string(bridge.State)),
log.Error(err),
)
return err
}

View File

@@ -49,6 +49,7 @@ func (r *BridgeRunner) executeSync(
ctx,
func(ctx context.Context, tx pg.Tx) error {
var err error
idp, token, dbConnector, err = r.prepareSync(
ctx,
tx,
@@ -56,7 +57,6 @@ func (r *BridgeRunner) executeSync(
scope,
logger,
)
if err != nil {
return fmt.Errorf("cannot prepare sync: %w", err)
}
@@ -126,6 +126,7 @@ func (r *BridgeRunner) prepareSync(
}
scimConfig.HashedToken = HashToken(token)
scimConfig.UpdatedAt = time.Now()
if err := scimConfig.Update(ctx, tx, scope); err != nil {
return nil, "", nil, fmt.Errorf("cannot update SCIM configuration token: %w", err)
@@ -192,6 +193,7 @@ func (r *BridgeRunner) createOAuth2BridgeProvider(
}
providerName := dbConnector.Provider.String()
refreshCfg := r.connectorRegistry.GetOAuth2RefreshConfig(providerName)
if refreshCfg == nil {
logger.WarnCtx(
@@ -200,10 +202,12 @@ func (r *BridgeRunner) createOAuth2BridgeProvider(
log.String("connector_id", dbConnector.ID.String()),
log.String("connector_provider", providerName),
)
httpClient, err := oauth2Conn.ClientWithOptions(ctx, httpClientOpts...)
if err != nil {
return nil, fmt.Errorf("cannot create HTTP client: %w", err)
}
return factory(httpClient), nil
}

View File

@@ -64,6 +64,7 @@ func ParseUserFilter(expr scimfilter.Expression) (*coredata.MembershipProfileFil
return nil, scimerrors.ScimErrorBadRequest(
fmt.Sprintf("logical operator '%s' is not supported, only 'and' is supported", e.Operator))
}
stack = append(stack, e.Left, e.Right)
case *scimfilter.NotExpression:

View File

@@ -106,12 +106,13 @@ func (s *Service) ValidateToken(ctx context.Context, token string) (*coredata.SC
if err == coredata.ErrResourceNotFound {
return NewSCIMInvalidTokenError()
}
return fmt.Errorf("cannot load SCIM configuration: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
@@ -128,6 +129,7 @@ func (s *Service) CreateUser(
if attrs.UserName == "" {
return scim.Resource{}, scimerrors.ScimErrorBadRequest("userName is required")
}
if attrs.Email == "" {
return scim.Resource{}, scimerrors.ScimErrorBadRequest("a valid email is required (via emails array or userName)")
}
@@ -136,6 +138,7 @@ func (s *Service) CreateUser(
if err != nil {
return scim.Resource{}, scimerrors.ScimErrorBadRequest("invalid email format")
}
now := time.Now()
profileState := coredata.ProfileStateActive
@@ -148,8 +151,10 @@ func (s *Service) CreateUser(
externalIdPtr = &attrs.ExternalID
}
var membership *coredata.Membership
var profile *coredata.MembershipProfile
var (
membership *coredata.Membership
profile *coredata.MembershipProfile
)
scope := coredata.NewScopeFromObjectID(config.OrganizationID)
@@ -205,6 +210,7 @@ func (s *Service) CreateUser(
// Migrate the existing membership to the new identity
// so the user's role is preserved.
oldIdentityID := profile.IdentityID
existingMembership := &coredata.Membership{}
if err := existingMembership.LoadByIdentityIDAndOrganizationID(
ctx,
@@ -214,6 +220,7 @@ func (s *Service) CreateUser(
config.OrganizationID,
); err == nil {
existingMembership.IdentityID = identity.ID
existingMembership.UpdatedAt = now
if err := existingMembership.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update membership identity: %w", err)
@@ -225,6 +232,7 @@ func (s *Service) CreateUser(
profile.IdentityID = identity.ID
profile.EmailAddress = emailAddr
applyUserAttributes(profile, attrs, externalIdPtr, profileState, now)
if err := profile.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update profile: %w", err)
}
@@ -248,8 +256,10 @@ func (s *Service) CreateUser(
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
return scimerrors.ScimErrorUniqueness
}
return fmt.Errorf("cannot insert profile: %w", err)
}
eventType = coredata.WebhookEventTypeUserCreated
}
} else {
@@ -270,6 +280,7 @@ func (s *Service) CreateUser(
}
applyUserAttributes(profile, attrs, externalIdPtr, profileState, now)
if err := profile.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update profile: %w", err)
}
@@ -277,6 +288,7 @@ func (s *Service) CreateUser(
if !attrs.Active {
invitations := &coredata.Invitations{}
onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending})
if err := invitations.ExpireByUserID(
ctx,
@@ -322,7 +334,6 @@ func (s *Service) CreateUser(
return nil
})
if err != nil {
return scim.Resource{}, err
}
@@ -347,6 +358,7 @@ func (s *Service) GetUser(
if err == coredata.ErrResourceNotFound {
return scimerrors.ScimErrorResourceNotFound(profileID.String())
}
return fmt.Errorf("cannot load profile: %w", err)
}
@@ -357,7 +369,6 @@ func (s *Service) GetUser(
return nil
},
)
if err != nil {
return scim.Resource{}, err
}
@@ -398,7 +409,6 @@ func (s *Service) ListUsers(
return nil
},
)
if err != nil {
return nil, 0, err
}
@@ -418,6 +428,7 @@ func (s *Service) ReplaceUser(
attributes scim.ResourceAttributes,
) (scim.Resource, error) {
attrs := ParseUserFromReplaceAttributes(attributes)
profile, err := s.updateUser(ctx, config, profileID, attrs)
if err != nil {
return scim.Resource{}, err
@@ -504,6 +515,7 @@ func (s *Service) updateUser(
} else {
profile.ExternalID = attrs.ExternalID
}
profile.UpdatedAt = now
}
@@ -513,6 +525,7 @@ func (s *Service) updateUser(
} else {
profile.Kind = attrs.UserType
}
profile.UpdatedAt = now
}
@@ -522,6 +535,7 @@ func (s *Service) updateUser(
} else {
profile.Nickname = attrs.Nickname
}
profile.UpdatedAt = now
}
@@ -531,6 +545,7 @@ func (s *Service) updateUser(
} else {
profile.Locale = attrs.Locale
}
profile.UpdatedAt = now
}
@@ -540,6 +555,7 @@ func (s *Service) updateUser(
} else {
profile.Timezone = attrs.Timezone
}
profile.UpdatedAt = now
}
@@ -549,6 +565,7 @@ func (s *Service) updateUser(
} else {
profile.ProfileUrl = attrs.ProfileUrl
}
profile.UpdatedAt = now
}
@@ -558,6 +575,7 @@ func (s *Service) updateUser(
} else {
profile.PreferredLanguage = attrs.PreferredLanguage
}
profile.UpdatedAt = now
}
@@ -567,6 +585,7 @@ func (s *Service) updateUser(
} else {
profile.GivenName = attrs.GivenName
}
profile.UpdatedAt = now
}
@@ -576,6 +595,7 @@ func (s *Service) updateUser(
} else {
profile.FamilyName = attrs.FamilyName
}
profile.UpdatedAt = now
}
@@ -585,6 +605,7 @@ func (s *Service) updateUser(
} else {
profile.FormattedName = attrs.FormattedName
}
profile.UpdatedAt = now
}
@@ -594,6 +615,7 @@ func (s *Service) updateUser(
} else {
profile.MiddleName = attrs.MiddleName
}
profile.UpdatedAt = now
}
@@ -603,6 +625,7 @@ func (s *Service) updateUser(
} else {
profile.HonorificPrefix = attrs.HonorificPrefix
}
profile.UpdatedAt = now
}
@@ -612,6 +635,7 @@ func (s *Service) updateUser(
} else {
profile.HonorificSuffix = attrs.HonorificSuffix
}
profile.UpdatedAt = now
}
@@ -621,6 +645,7 @@ func (s *Service) updateUser(
} else {
profile.EmployeeNumber = attrs.EmployeeNumber
}
profile.UpdatedAt = now
}
@@ -630,6 +655,7 @@ func (s *Service) updateUser(
} else {
profile.Department = attrs.Department
}
profile.UpdatedAt = now
}
@@ -639,6 +665,7 @@ func (s *Service) updateUser(
} else {
profile.CostCenter = attrs.CostCenter
}
profile.UpdatedAt = now
}
@@ -648,6 +675,7 @@ func (s *Service) updateUser(
} else {
profile.EnterpriseOrganization = attrs.EnterpriseOrganization
}
profile.UpdatedAt = now
}
@@ -657,6 +685,7 @@ func (s *Service) updateUser(
} else {
profile.Division = attrs.Division
}
profile.UpdatedAt = now
}
@@ -666,6 +695,7 @@ func (s *Service) updateUser(
} else {
profile.ManagerValue = attrs.ManagerValue
}
profile.UpdatedAt = now
}
@@ -688,6 +718,7 @@ func (s *Service) updateUser(
if shouldDeactivate {
invitations := &coredata.Invitations{}
onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending})
if err := invitations.ExpireByUserID(
ctx,
@@ -727,7 +758,6 @@ func (s *Service) updateUser(
return nil
},
)
if err != nil {
return nil, err
}
@@ -788,6 +818,7 @@ func (s *Service) DeleteUser(
if errors.Is(err, coredata.ErrResourceNotFound) {
return scimerrors.ScimErrorResourceNotFound(profileID.String())
}
return fmt.Errorf("cannot load profile: %w", err)
}
@@ -796,6 +827,7 @@ func (s *Service) DeleteUser(
}
invitations := &coredata.Invitations{}
onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending})
if err := invitations.ExpireByUserID(
ctx,
@@ -808,6 +840,7 @@ func (s *Service) DeleteUser(
}
var membership *coredata.Membership
m := &coredata.Membership{}
if err := m.LoadByIdentityIDAndOrganizationID(
ctx, tx, scope, profile.IdentityID, config.OrganizationID,
@@ -859,10 +892,10 @@ func (s *Service) LogEvent(
if err != nil {
return fmt.Errorf("cannot insert SCIM event: %w", err)
}
return nil
},
)
if err != nil {
s.logger.ErrorCtx(ctx, "cannot log SCIM event", log.Error(err))
}
@@ -941,6 +974,7 @@ func ParseUserFromAttributes(attributes scim.ResourceAttributes) scimUserAttribu
attrs.HonorificPrefix, _ = name["honorificPrefix"].(string)
attrs.HonorificSuffix, _ = name["honorificSuffix"].(string)
}
attrs.GivenName = givenName
attrs.FamilyName = familyName
@@ -955,6 +989,7 @@ func ParseUserFromAttributes(attributes scim.ResourceAttributes) scimUserAttribu
}
}
}
if attrs.Email == "" {
if emailMap, ok := emails[0].(map[string]any); ok {
if value, ok := emailMap["value"].(string); ok {
@@ -974,6 +1009,7 @@ func ParseUserFromAttributes(attributes scim.ResourceAttributes) scimUserAttribu
if attrs.FullName == "" {
attrs.FullName = strings.TrimSpace(givenName + " " + familyName)
}
if attrs.FullName == "" {
attrs.FullName = attrs.UserName
}
@@ -991,6 +1027,7 @@ func ParseUserFromAttributes(attributes scim.ResourceAttributes) scimUserAttribu
attrs.Department, _ = enterprise["department"].(string)
attrs.CostCenter, _ = enterprise["costCenter"].(string)
attrs.EnterpriseOrganization, _ = enterprise["organization"].(string)
attrs.Division, _ = enterprise["division"].(string)
if manager, ok := enterprise["manager"].(map[string]any); ok {
attrs.ManagerValue, _ = manager["value"].(string)
@@ -1028,25 +1065,31 @@ type scimReplaceAttributes struct {
func ParseUserFromReplaceAttributes(attributes scim.ResourceAttributes) scimReplaceAttributes {
var attrs scimReplaceAttributes
displayName, _ := attributes["displayName"].(string)
var givenName, familyName string
if name, ok := attributes["name"].(map[string]any); ok {
givenName, _ = name["givenName"].(string)
familyName, _ = name["familyName"].(string)
if fn, ok := name["formatted"].(string); ok {
attrs.FormattedName = &fn
}
if mn, ok := name["middleName"].(string); ok {
attrs.MiddleName = &mn
}
if hp, ok := name["honorificPrefix"].(string); ok {
attrs.HonorificPrefix = &hp
}
if hs, ok := name["honorificSuffix"].(string); ok {
attrs.HonorificSuffix = &hs
}
}
attrs.GivenName = &givenName
attrs.FamilyName = &familyName
@@ -1059,6 +1102,7 @@ func ParseUserFromReplaceAttributes(attributes scim.ResourceAttributes) scimRepl
if a, ok := attributes["active"].(bool); ok {
activeVal = a
}
attrs.Active = &activeVal
t, _ := attributes["title"].(string)
@@ -1075,18 +1119,23 @@ func ParseUserFromReplaceAttributes(attributes scim.ResourceAttributes) scimRepl
if ut, ok := attributes["userType"].(string); ok {
attrs.UserType = &ut
}
if nn, ok := attributes["nickName"].(string); ok {
attrs.Nickname = &nn
}
if l, ok := attributes["locale"].(string); ok {
attrs.Locale = &l
}
if tz, ok := attributes["timezone"].(string); ok {
attrs.Timezone = &tz
}
if pu, ok := attributes["profileUrl"].(string); ok {
attrs.ProfileUrl = &pu
}
if pl, ok := attributes["preferredLanguage"].(string); ok {
attrs.PreferredLanguage = &pl
}
@@ -1095,18 +1144,23 @@ func ParseUserFromReplaceAttributes(attributes scim.ResourceAttributes) scimRepl
if en, ok := enterprise["employeeNumber"].(string); ok {
attrs.EmployeeNumber = &en
}
if dept, ok := enterprise["department"].(string); ok {
attrs.Department = &dept
}
if cc, ok := enterprise["costCenter"].(string); ok {
attrs.CostCenter = &cc
}
if org, ok := enterprise["organization"].(string); ok {
attrs.EnterpriseOrganization = &org
}
if div, ok := enterprise["division"].(string); ok {
attrs.Division = &div
}
if manager, ok := enterprise["manager"].(map[string]any); ok {
if mv, ok := manager["value"].(string); ok {
attrs.ManagerValue = &mv
@@ -1118,8 +1172,11 @@ func ParseUserFromReplaceAttributes(attributes scim.ResourceAttributes) scimRepl
}
func ParseUserFromPatchOperations(operations []scim.PatchOperation) scimReplaceAttributes {
var attrs scimReplaceAttributes
var givenName, familyName string
var (
attrs scimReplaceAttributes
givenName, familyName string
)
empty := ""
for _, op := range operations {
@@ -1186,6 +1243,7 @@ func ParseUserFromPatchOperations(operations []scim.PatchOperation) scimReplaceA
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:user:manager.value":
attrs.ManagerValue = &empty
}
continue
}
@@ -1200,72 +1258,94 @@ func ParseUserFromPatchOperations(operations []scim.PatchOperation) scimReplaceA
if a, ok := valueMap["active"].(bool); ok {
attrs.Active = &a
}
if name, ok := valueMap["displayName"].(string); ok {
attrs.FullName = name
}
if nameMap, ok := valueMap["name"].(map[string]any); ok {
if gn, ok := nameMap["givenName"].(string); ok {
givenName = gn
}
if fn, ok := nameMap["familyName"].(string); ok {
familyName = fn
}
if fm, ok := nameMap["formatted"].(string); ok {
attrs.FormattedName = &fm
}
if mn, ok := nameMap["middleName"].(string); ok {
attrs.MiddleName = &mn
}
if hp, ok := nameMap["honorificPrefix"].(string); ok {
attrs.HonorificPrefix = &hp
}
if hs, ok := nameMap["honorificSuffix"].(string); ok {
attrs.HonorificSuffix = &hs
}
}
if un, ok := valueMap["userName"].(string); ok && un != "" {
attrs.UserName = &un
}
if eid, ok := valueMap["externalId"].(string); ok && eid != "" {
attrs.ExternalID = &eid
}
if t, ok := valueMap["title"].(string); ok {
attrs.Title = &t
}
if ut, ok := valueMap["userType"].(string); ok {
attrs.UserType = &ut
}
if nn, ok := valueMap["nickName"].(string); ok {
attrs.Nickname = &nn
}
if l, ok := valueMap["locale"].(string); ok {
attrs.Locale = &l
}
if tz, ok := valueMap["timezone"].(string); ok {
attrs.Timezone = &tz
}
if pu, ok := valueMap["profileUrl"].(string); ok {
attrs.ProfileUrl = &pu
}
if pl, ok := valueMap["preferredLanguage"].(string); ok {
attrs.PreferredLanguage = &pl
}
if enterprise, ok := valueMap["urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"].(map[string]any); ok {
if en, ok := enterprise["employeeNumber"].(string); ok {
attrs.EmployeeNumber = &en
}
if dept, ok := enterprise["department"].(string); ok {
attrs.Department = &dept
}
if cc, ok := enterprise["costCenter"].(string); ok {
attrs.CostCenter = &cc
}
if org, ok := enterprise["organization"].(string); ok {
attrs.EnterpriseOrganization = &org
}
if div, ok := enterprise["division"].(string); ok {
attrs.Division = &div
}
if manager, ok := enterprise["manager"].(map[string]any); ok {
if mv, ok := manager["value"].(string); ok {
attrs.ManagerValue = &mv
@@ -1328,6 +1408,7 @@ func ParseUserFromPatchOperations(operations []scim.PatchOperation) scimReplaceA
}
}
}
continue
}
@@ -1346,19 +1427,24 @@ func ParseUserFromPatchOperations(operations []scim.PatchOperation) scimReplaceA
givenName = gn
attrs.GivenName = &givenName
}
if fn, ok := nameMap["familyName"].(string); ok {
familyName = fn
attrs.FamilyName = &familyName
}
if fm, ok := nameMap["formatted"].(string); ok {
attrs.FormattedName = &fm
}
if mn, ok := nameMap["middleName"].(string); ok {
attrs.MiddleName = &mn
}
if hp, ok := nameMap["honorificPrefix"].(string); ok {
attrs.HonorificPrefix = &hp
}
if hs, ok := nameMap["honorificSuffix"].(string); ok {
attrs.HonorificSuffix = &hs
}
@@ -1430,18 +1516,23 @@ func ParseUserFromPatchOperations(operations []scim.PatchOperation) scimReplaceA
if en, ok := enterprise["employeeNumber"].(string); ok {
attrs.EmployeeNumber = &en
}
if dept, ok := enterprise["department"].(string); ok {
attrs.Department = &dept
}
if cc, ok := enterprise["costCenter"].(string); ok {
attrs.CostCenter = &cc
}
if org, ok := enterprise["organization"].(string); ok {
attrs.EnterpriseOrganization = &org
}
if div, ok := enterprise["division"].(string); ok {
attrs.Division = &div
}
if manager, ok := enterprise["manager"].(map[string]any); ok {
if mv, ok := manager["value"].(string); ok {
attrs.ManagerValue = &mv
@@ -1491,6 +1582,7 @@ func ParseUserFromPatchOperations(operations []scim.PatchOperation) scimReplaceA
if givenName != "" && attrs.GivenName == nil {
attrs.GivenName = &givenName
}
if familyName != "" && attrs.FamilyName == nil {
attrs.FamilyName = &familyName
}