Expire invitations on SAML sign up and invitation accept

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-01-09 10:31:19 +01:00
committed by Bryan Frimin
parent 53bfc36bff
commit bbdea575d1
5 changed files with 17 additions and 45 deletions

View File

@@ -25,6 +25,8 @@ const createSAMLConfigurationMutation = graphql`
domainVerificationToken domainVerificationToken
domainVerifiedAt domainVerifiedAt
testLoginUrl testLoginUrl
canUpdate: permission(action: "iam:saml-configuration:update")
canDelete: permission(action: "iam:saml-configuration:delete")
} }
} }
} }

View File

@@ -164,39 +164,6 @@ WHERE
return nil return nil
} }
func (i *Invitations) AcceptByEmailAndOrganization(
ctx context.Context,
conn pg.Conn,
scope Scoper,
email mail.Addr,
organizationID gid.GID,
filter *InvitationFilter,
) error {
q := `
UPDATE iam_invitations SET accepted_at = NOW()
WHERE
email = @email
AND organization_id = @organization_id
AND %s
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.StrictNamedArgs{
"email": email,
"organization_id": organizationID,
}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
if _, err := conn.Exec(ctx, q, args); err != nil {
return fmt.Errorf("cannot accept invitations: %w", err)
}
return nil
}
func (i *Invitations) ExpireByEmailAndOrganization( func (i *Invitations) ExpireByEmailAndOrganization(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
@@ -206,7 +173,10 @@ func (i *Invitations) ExpireByEmailAndOrganization(
filter *InvitationFilter, filter *InvitationFilter,
) error { ) error {
q := ` q := `
UPDATE iam_invitations SET expires_at = NOW() UPDATE
iam_invitations
SET
expires_at = NOW()
WHERE WHERE
email = @email email = @email
AND organization_id = @organization_id AND organization_id = @organization_id

View File

@@ -303,7 +303,7 @@ func (s *AccountService) AcceptInvitation(
// Accept other pending invitations for email in organization // Accept other pending invitations for email in organization
invitations := &coredata.Invitations{} invitations := &coredata.Invitations{}
onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending}) onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending})
if err := invitations.AcceptByEmailAndOrganization( if err := invitations.ExpireByEmailAndOrganization(
ctx, ctx,
tx, tx,
coredata.NewScopeFromObjectID(invitation.OrganizationID), coredata.NewScopeFromObjectID(invitation.OrganizationID),
@@ -311,7 +311,7 @@ func (s *AccountService) AcceptInvitation(
invitation.OrganizationID, invitation.OrganizationID,
onlyPending, onlyPending,
); err != nil { ); err != nil {
return fmt.Errorf("cannot accept pending invitations by email: %w", err) return fmt.Errorf("cannot expire pending invitations by email: %w", err)
} }
return nil return nil

View File

@@ -326,10 +326,10 @@ func (s *Service) HandleAssertion(
return fmt.Errorf("cannot insert membership profile: %w", err) return fmt.Errorf("cannot insert membership profile: %w", err)
} }
// Accept all pending invitations for email in organization // Expire all pending invitations for email in organization
invitations := &coredata.Invitations{} invitations := &coredata.Invitations{}
onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending}) onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending})
if err := invitations.AcceptByEmailAndOrganization( if err := invitations.ExpireByEmailAndOrganization(
ctx, ctx,
tx, tx,
coredata.NewScopeFromObjectID(config.OrganizationID), coredata.NewScopeFromObjectID(config.OrganizationID),
@@ -337,7 +337,7 @@ func (s *Service) HandleAssertion(
config.OrganizationID, config.OrganizationID,
onlyPending, onlyPending,
); err != nil { ); err != nil {
return fmt.Errorf("cannot accept pending invitations by email: %w", err) return fmt.Errorf("cannot expire pending invitations by email: %w", err)
} }
} }

View File

@@ -173,10 +173,10 @@ func (s *Service) CreateUser(
return fmt.Errorf("cannot insert membership profile: %w", err) return fmt.Errorf("cannot insert membership profile: %w", err)
} }
// Accept all pending invitations for email in organization // Expire all pending invitations for email in organization
invitations := &coredata.Invitations{} invitations := &coredata.Invitations{}
onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending}) onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending})
err := invitations.AcceptByEmailAndOrganization( err := invitations.ExpireByEmailAndOrganization(
ctx, ctx,
tx, tx,
coredata.NewScopeFromObjectID(config.OrganizationID), coredata.NewScopeFromObjectID(config.OrganizationID),
@@ -186,7 +186,7 @@ func (s *Service) CreateUser(
) )
if err != nil { if err != nil {
return fmt.Errorf("cannot accept pending invitations by email") return fmt.Errorf("cannot expire pending invitations by email")
} }
} else if err != nil { } else if err != nil {
return fmt.Errorf("cannot load membership: %w", err) return fmt.Errorf("cannot load membership: %w", err)
@@ -375,10 +375,10 @@ func (s *Service) updateUser(
membership.Role = coredata.MembershipRoleEmployee membership.Role = coredata.MembershipRoleEmployee
needsUpdate = true needsUpdate = true
// Accept all pending invitations for email in organization // Expire all pending invitations for email in organization
invitations := &coredata.Invitations{} invitations := &coredata.Invitations{}
onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending}) onlyPending := coredata.NewInvitationFilter([]coredata.InvitationStatus{coredata.InvitationStatusPending})
if err := invitations.AcceptByEmailAndOrganization( if err := invitations.ExpireByEmailAndOrganization(
ctx, ctx,
tx, tx,
coredata.NewScopeFromObjectID(config.OrganizationID), coredata.NewScopeFromObjectID(config.OrganizationID),
@@ -386,7 +386,7 @@ func (s *Service) updateUser(
config.OrganizationID, config.OrganizationID,
onlyPending, onlyPending,
); err != nil { ); err != nil {
return fmt.Errorf("cannot accept pending invitations by email: %w", err) return fmt.Errorf("cannot expire pending invitations by email: %w", err)
} }
} else if !*active && membership.State == coredata.MembershipStateActive { } else if !*active && membership.State == coredata.MembershipStateActive {
membership.State = coredata.MembershipStateInactive membership.State = coredata.MembershipStateInactive