Skip to content

fix: align organization role display and invite authorization with membership owner role#1642

Open
DaveMiscampbell wants to merge 4 commits intoCapSoftware:mainfrom
DaveMiscampbell:fix/org-owner-membership-invite-role
Open

fix: align organization role display and invite authorization with membership owner role#1642
DaveMiscampbell wants to merge 4 commits intoCapSoftware:mainfrom
DaveMiscampbell:fix/org-owner-membership-invite-role

Conversation

@DaveMiscampbell
Copy link

@DaveMiscampbell DaveMiscampbell commented Mar 3, 2026

Summary

  • align invite authorization with membership ownership by checking organization_members.role = owner in sendOrganizationInvites
  • display member role in the Members table from organization_members.role instead of inferring ownership from organizations.ownerId
  • derive owner-capability in org invite entry points from membership role to avoid false "non-owner" blocks when ownerId and membership data drift:
    • billing/members settings page
    • navbar member avatar quick-invite

Why

Ownership currently exists in two sources (organizations.ownerId and organization_members.role). In self-hosted or manually migrated databases these can drift, causing inconsistent behavior:

  • owner-role users shown as Member in the members table
  • owner-role users blocked from invite actions because UI/server checks use ownerId

This PR makes invite permissions and role rendering consistent with membership role ownership.

Validation

  • pnpm exec biome check --write on touched org files (passes for edited files except a pre-existing lint in MemberAvatars unrelated to this change)
  • pnpm typecheck remains failing repo-wide on existing test/type issues, but no errors were emitted for the touched files in filtered output

Files Changed

  • apps/web/actions/organization/send-invites.ts
  • apps/web/app/(org)/dashboard/settings/organization/components/MembersCard.tsx
  • apps/web/app/(org)/dashboard/settings/organization/billing/page.tsx
  • apps/web/app/(org)/dashboard/_components/Navbar/MemberAvatars.tsx

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 3, 2026

Additional Comments (1)

apps/web/app/(org)/dashboard/settings/organization/components/MembersCard.tsx
The "Remove member" and "Delete Invite" actions still gate on isOwner (derived from organizations.ownerId), while the "Invite users" button now gates on canInviteUsers (derived from organizationMembers.role).

In the drift scenario this PR addresses — where a user's membership role is "owner" but they are not the ownerId — they can invite users but cannot remove members or delete pending invites. This leaves the inconsistency only partially fixed.

Consider applying the same membership-role check to these actions:

  • handleDeleteInvite guard (line 52)
  • Remove-member button (lines 227, 239)
  • Delete-invite button (lines 262, 268)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/app/(org)/dashboard/settings/organization/components/MembersCard.tsx
Line: 52

Comment:
The "Remove member" and "Delete Invite" actions still gate on `isOwner` (derived from `organizations.ownerId`), while the "Invite users" button now gates on `canInviteUsers` (derived from `organizationMembers.role`). 

In the drift scenario this PR addresses — where a user's membership `role` is `"owner"` but they are not the `ownerId` — they can invite users but cannot remove members or delete pending invites. This leaves the inconsistency only partially fixed.

Consider applying the same membership-role check to these actions:
- `handleDeleteInvite` guard (line 52)
- Remove-member button (lines 227, 239)
- Delete-invite button (lines 262, 268)

How can I resolve this? If you propose a fix, please make it concise.

@DaveMiscampbell DaveMiscampbell force-pushed the fix/org-owner-membership-invite-role branch from 81adcc6 to db2c812 Compare March 3, 2026 17:53
@DaveMiscampbell
Copy link
Author

DaveMiscampbell commented Mar 3, 2026

Addressed review feedback in two follow-up commits:

  • Unified owner-role authorization for member-management actions by checking organization membership role "owner" in removeOrganizationInvite and removeOrganizationMember (instead of organizations.ownerId).
  • Aligned UI permission gating under canManageMembers in billing/members screens so invite/remove/delete all share the same role-based gate.
  • Applied remaining minor nits in MemberAvatars and MembersCard.

I also resolved all outdated review threads.

@DaveMiscampbell
Copy link
Author

Resolves #1641

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant