Skip to content

Support adding users to user groups at invitation time (AddOrganizationMemberUser / AddProjectMemberUser usergroups) - #9858

Open
nishantmonu51 wants to merge 3 commits into
mainfrom
invite_groups
Open

Support adding users to user groups at invitation time (AddOrganizationMemberUser / AddProjectMemberUser usergroups)#9858
nishantmonu51 wants to merge 3 commits into
mainfrom
invite_groups

Conversation

@nishantmonu51

Copy link
Copy Markdown
Collaborator

Admins can now assign user groups when inviting a user, instead of inviting, waiting for acceptance, and then adding them to groups. Follows the pattern used for invite-time attributes in #9797. The org_invites.usergroup_ids column and its application on signup already existed; this PR exposes it through the APIs, CLI, and UI.

Backend

  • AddOrganizationMemberUser and AddProjectMemberUser accept usergroups (group names). For a pending signup they are stored on the org invite and merged additively on re-invite; for an existing user they are applied immediately in the same transaction (ON CONFLICT DO NOTHING, so it is safe inside the tx).
  • A shared resolveUsergroupsForMembership validates groups (exist, not managed, admin-role guard) and is reused by AddUsergroupMemberUser, so the rules cannot drift.
  • OrganizationInvite exposes usergroups; ListUsergroupMemberUsers includes pending invitees with pending_acceptance; RemoveUsergroupMemberUser handles pending invitees; DeleteUsergroup scrubs the group from pending invites.
  • No migration needed. Tests added in rbac_test.go and postgres_test.go.

CLI

  • rill user add --group is repeatable and is sent with the org or project invite in a single call. The interactive fallback no longer drops --attribute values.
  • rill user list shows groups and attributes on pending invites, and a status column for group members.

Frontend

  • UserGroupsMultiSelect in the Add users and Add guests dialogs.
  • Pending rows show their invite groups; a new ManageUserGroupsDialog is reachable from a "Manage groups" action on every row of the users and guests tables.
  • The Create and Edit group dialogs list pending invitees and can add them via search.

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

Admins can now pick user groups when inviting a user, instead of waiting for
the invite to be accepted and adding the user to groups afterwards.

Backend:
- `AddOrganizationMemberUser` and `AddProjectMemberUser` accept `usergroups`.
  For a pending signup the groups are stored on the org invite (additively
  merged on re-invite) and applied on acceptance; for an existing user they are
  applied immediately in the same transaction.
- A shared resolver validates groups (exist, not managed, admin-role guard) and
  is reused by `AddUsergroupMemberUser`.
- `OrganizationInvite` exposes `usergroups`; `ListUsergroupMemberUsers` lists
  pending invitees with `pending_acceptance`; `RemoveUsergroupMemberUser` works
  on pending invitees; deleting a group scrubs it from pending invites.

CLI:
- `rill user add --group` is repeatable and rides along with the org or project
  invite in one call; the interactive fallback keeps attributes.
- `rill user list` shows groups and attributes on pending invites and a status
  column on group member listings.

Frontend:
- Group multi-select in the Add users and Add guests dialogs.
- Pending rows show their groups; a Manage groups action on every user row.
- The Create and Edit group dialogs list and can add pending invitees.
@nishantmonu51 nishantmonu51 added Type:Feature New feature request Size:L Large change: 500-1,999 lines labels Sep 4, 2026
Backend:
- `AddOrganizationMemberUser` checks membership up front and applies the
  requested groups to an existing member in one transaction, reporting the
  conflict only after the commit; the seat quota is skipped for existing members.
- `DeleteUsergroup` scrubs the group from pending invites in the same
  transaction as the delete.
- Group member counts include pending invitees, matching the member listing.
- `AddUsergroupMemberUser` and `RemoveUsergroupMemberUser` share the group
  resolver and its permission and managed-group checks.

CLI:
- `rill user add --group` treats AlreadyExists as success when the server has
  applied the groups, and rejects attributes on the groups-only path.

Frontend:
- Manage groups dialog snapshots the target user and changes before saving and
  locks the dialog while requests are in flight, so a save can no longer apply
  to a different user.
- Add users dialog treats a 409 with selected groups as a partial success:
  caches are refreshed and the notice says the members were added to the groups.
- Group changes invalidate every variant of the per-user groups query and the
  member lists of the affected groups, so the table dropdown no longer goes stale.
- Pending rows are tagged explicitly instead of relying on invitedBy, and the
  invite coercion is shared between the users and guests pages.
- The group multi-select stops paging after a failed page.

Claude-Session: https://claude.ai/code/session_01UYzyaaSjA9gNrGJXDsCeTs
The paginated group member listing orders by the database collation, which sorts
`_` before `-` on CI while Go's byte order does the opposite. Compare the pages
against a single unpaginated listing instead of asserting byte-order increase.

Claude-Session: https://claude.ai/code/session_01UYzyaaSjA9gNrGJXDsCeTs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Size:L Large change: 500-1,999 lines Type:Feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants