From ae0119e2c59fb5531944fc0ff874b5d6dc58770b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Tue, 17 Feb 2026 17:30:35 +0400 Subject: [PATCH] Expire invitations when user is deactivated or switches to SAML source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Émile Ré --- pkg/iam/saml/service.go | 13 +++++++++++++ pkg/iam/scim/service.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/pkg/iam/saml/service.go b/pkg/iam/saml/service.go index 7a4f3a203..341496993 100644 --- a/pkg/iam/saml/service.go +++ b/pkg/iam/saml/service.go @@ -376,6 +376,19 @@ func (s *Service) HandleAssertion( } } + // Expire pending invitations for user (in case source switched to SAML) + invitations := &coredata.Invitations{} + onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending}) + if err := invitations.ExpireByUserID( + ctx, + tx, + coredata.NewScopeFromObjectID(profile.OrganizationID), + profile.ID, + onlyPending, + ); err != nil { + return fmt.Errorf("cannot expire pending invitations: %w", err) + } + return nil }, ) diff --git a/pkg/iam/scim/service.go b/pkg/iam/scim/service.go index bb5bdbd73..b425cdcf5 100644 --- a/pkg/iam/scim/service.go +++ b/pkg/iam/scim/service.go @@ -211,6 +211,21 @@ func (s *Service) CreateUser( } } + if !active { + // Expire pending invitations for user + invitations := &coredata.Invitations{} + onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending}) + if err := invitations.ExpireByUserID( + ctx, + tx, + coredata.NewScopeFromObjectID(profile.OrganizationID), + profile.ID, + onlyPending, + ); err != nil { + return fmt.Errorf("cannot expire pending invitations: %w", err) + } + } + // Check if membership exists membership = &coredata.Membership{} if err := membership.LoadByIdentityIDAndOrganizationID( @@ -450,6 +465,21 @@ func (s *Service) updateUser( return fmt.Errorf("cannot update membership profile: %w", err) } + if shouldDeactivate { + // Expire pending invitations for user + invitations := &coredata.Invitations{} + onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending}) + if err := invitations.ExpireByUserID( + ctx, + tx, + coredata.NewScopeFromObjectID(profile.OrganizationID), + profile.ID, + onlyPending, + ); err != nil { + return fmt.Errorf("cannot expire pending invitations: %w", err) + } + } + needsUpdate := shouldReactivate || shouldDeactivate if active != nil {