Enforce at least one owner

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-01-05 16:15:48 +01:00
parent 9936df64d9
commit 5c64e304e8
4 changed files with 69 additions and 0 deletions

View File

@@ -147,6 +147,18 @@ func (e ErrMembershipManagedBySCIM) Error() string {
return fmt.Sprintf("membership %q is managed by SCIM and cannot be deleted manually", e.MembershipID)
}
type ErrLastActiveOwner struct {
MembershipID gid.GID
}
func NewLastActiveOwnerError(membershipID gid.GID) error {
return &ErrLastActiveOwner{MembershipID: membershipID}
}
func (e ErrLastActiveOwner) Error() string {
return fmt.Sprintf("cannot remove membership %q: last active owner of the organization", e.MembershipID)
}
type ErrOrganizationNotFound struct{ OrganizationID gid.GID }
func NewOrganizationNotFoundError(organizationID gid.GID) error {

View File

@@ -257,6 +257,21 @@ func (s *OrganizationService) RemoveMember(
return NewMembershipManagedBySCIMError(membershipID)
}
if membership.Role == coredata.MembershipRoleOwner && membership.State == coredata.MembershipStateActive {
memberships := coredata.Memberships{}
filter := coredata.NewMembershipFilter().
WithRole(coredata.MembershipRoleOwner).
WithState(coredata.MembershipStateActive)
count, err := memberships.CountByOrganizationID(ctx, tx, scope, organizationID, filter)
if err != nil {
return fmt.Errorf("cannot count active owners: %w", err)
}
if count <= 1 {
return NewLastActiveOwnerError(membershipID)
}
}
err := membership.Delete(ctx, tx, scope, membershipID)
if err != nil {
return fmt.Errorf("cannot delete membership: %w", err)