From f743c743c1442c8b7e09ab6968015b521150307d Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Mon, 20 Apr 2026 12:23:29 +0200 Subject: [PATCH] Only guard owner demotion for active profiles Move profile load before the owner-demotion guard and add an active-state check, matching the RemoveUser pattern. Without this, demoting an inactive owner would be incorrectly blocked. Signed-off-by: Bryan Frimin --- pkg/iam/organization_service.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/iam/organization_service.go b/pkg/iam/organization_service.go index d2b828e3a..4a361ecb0 100644 --- a/pkg/iam/organization_service.go +++ b/pkg/iam/organization_service.go @@ -266,7 +266,12 @@ func (s *OrganizationService) UpdateMempership( return NewMembershipNotFoundError(membership.ID) } - if membership.Role == coredata.MembershipRoleOwner && role != coredata.MembershipRoleOwner { + profile := &coredata.MembershipProfile{} + if err := profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, membership.IdentityID, membership.OrganizationID); err != nil { + return fmt.Errorf("cannot load profile: %w", err) + } + + if membership.Role == coredata.MembershipRoleOwner && role != coredata.MembershipRoleOwner && profile.State == coredata.ProfileStateActive { profiles := coredata.MembershipProfiles{} count, err := profiles.CountActiveOwnerByOrganizationID(ctx, tx, scope, organizationID) if err != nil { @@ -285,11 +290,6 @@ func (s *OrganizationService) UpdateMempership( return fmt.Errorf("cannot update membership: %w", err) } - profile := &coredata.MembershipProfile{} - if err := profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, membership.IdentityID, membership.OrganizationID); err != nil { - return fmt.Errorf("cannot load profile: %w", err) - } - if err := webhook.InsertData(ctx, tx, scope, organizationID, coredata.WebhookEventTypeUserUpdated, webhooktypes.NewUser(profile, &membership)); err != nil { return fmt.Errorf("cannot insert webhook event: %w", err) }