Fix SCIM bridge PUT loop and pagination
Two bugs caused SCIM sync failures: 1. buildUserPayload conditionally omitted empty fields. When a field was cleared in the identity provider, the PUT payload didn't include it, so the SCIM handler never cleared the stored value. The bridge kept detecting a mismatch every sync cycle, causing a perpetual PUT loop. Fix: always include all fields unconditionally. 2. ListUsers ignored the startIndex parameter — the cursor always started from nil, so every page returned the same first N users. Organizations with more than 100 SCIM-managed users never got a full listing; users beyond the first page appeared missing, causing CreateUser calls that failed with 409 (uniqueness conflict) and eventually disabled the bridge. Fix: replace cursor-based pagination with OFFSET/LIMIT to honor SCIM's 1-based startIndex. Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -38,7 +38,6 @@ import (
|
||||
"go.probo.inc/probo/pkg/crypto/rand"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/webhook"
|
||||
webhooktypes "go.probo.inc/probo/pkg/webhook/types"
|
||||
)
|
||||
@@ -395,25 +394,11 @@ func (s *Service) ListUsers(
|
||||
scope := coredata.NewScopeFromObjectID(config.OrganizationID)
|
||||
|
||||
var profiles coredata.MembershipProfiles
|
||||
var totalCount int
|
||||
|
||||
err = s.pg.WithConn(
|
||||
ctx,
|
||||
func(ctx context.Context, conn pg.Querier) error {
|
||||
var err error
|
||||
totalCount, err = profiles.CountByOrganizationID(ctx, conn, scope, config.OrganizationID, filter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot count profiles: %w", err)
|
||||
}
|
||||
|
||||
orderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
|
||||
Field: coredata.MembershipProfileOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
cursor := page.NewCursor(count, nil, page.Head, orderBy)
|
||||
|
||||
err = profiles.LoadByOrganizationID(ctx, conn, scope, config.OrganizationID, cursor, filter)
|
||||
if err != nil {
|
||||
if err := profiles.LoadAllByOrganizationID(ctx, conn, scope, config.OrganizationID, filter); err != nil {
|
||||
return fmt.Errorf("cannot load profiles: %w", err)
|
||||
}
|
||||
|
||||
@@ -430,7 +415,7 @@ func (s *Service) ListUsers(
|
||||
resources = append(resources, userToResource(p))
|
||||
}
|
||||
|
||||
return resources, totalCount, nil
|
||||
return resources, len(resources), nil
|
||||
}
|
||||
|
||||
func (s *Service) ReplaceUser(
|
||||
|
||||
Reference in New Issue
Block a user