Clear conflicting external_id when enrolling manual profile into SCIM

When a SCIM provider sends CreateUser for a user whose email matches an
existing manual profile, but another profile already holds that
external_id (e.g. created by a prior CreateUser with a different email),
clear the conflicting external_id before enrolling the manual profile.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-03-14 12:25:13 +01:00
parent 2f76eaf4ae
commit 76f781ead1
2 changed files with 48 additions and 0 deletions

View File

@@ -1396,6 +1396,42 @@ WHERE
return nil
}
func (p *MembershipProfile) ClearExternalID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
externalID string,
organizationID gid.GID,
) error {
q := `
UPDATE iam_membership_profiles
SET
external_id = NULL,
updated_at = @updated_at
WHERE
%s
AND external_id = @external_id
AND organization_id = @organization_id
AND id != @exclude_id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.NamedArgs{
"external_id": externalID,
"organization_id": organizationID,
"exclude_id": p.ID,
"updated_at": time.Now(),
}
maps.Copy(args, scope.SQLArguments())
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot clear external id: %w", err)
}
return nil
}
func (p *MembershipProfile) Delete(
ctx context.Context,
conn pg.Conn,

View File

@@ -244,6 +244,18 @@ func (s *Service) CreateUser(
return scimerrors.ScimErrorUniqueness
}
if externalIdPtr != nil {
if err := profile.ClearExternalID(
ctx,
tx,
scope,
*externalIdPtr,
config.OrganizationID,
); err != nil {
return fmt.Errorf("cannot clear conflicting external id: %w", err)
}
}
profile.Source = coredata.ProfileSourceSCIM
profile.State = profileState
profile.FullName = attrs.FullName