Skip to main content

User Roles (Admin)

The User Roles section lets admins manage the third RBAC layer in Lumio — the set of user-scope permissions that controls what authenticated users can do across community features like the Ideas Hub. This is distinct from the account-scope roles (which control dashboard access within a streaming account) and from admin roles (which control access to the admin panel itself).

Where to Find It

Admin sidebar → User Roles (/user-roles). The whole role editor is a dialog on that one page — there are no /user-roles/\{id\} detail routes. Per-user role assignments and permission overrides are managed from the user detail page at /users/\{id\}. Per-account permission overrides are managed from the account detail page at /accounts/\{id\}.

Role List

The list at /user-roles shows all user roles.

Columns

ColumnDescription
NameRole display name, with the description underneath
PermissionsCount of permissions assigned to the role
TypeSystem, Default, or Custom badge
ActionsEdit (pencil) button, shown when the caller holds user-roles:edit

The slug is not a list column — it appears in the edit dialog header under the role name.

Three roles are seeded as system roles (is_system = true) and cannot be deleted:

SlugNamePermissions
memberMemberThe default role for every user: ideas:read, ideas:create, ideas:edit, ideas:delete, ideas:vote, ideas:comment_read, ideas:comment_create, ideas:comment_edit, ideas:comment_delete, ideas:comment_vote
restrictedRestrictedRead-only: ideas:read, ideas:comment_read
moderatorModeratorEverything member has, plus ideas:moderate_status, ideas:moderate_edit, ideas:moderate_delete, ideas:moderate_comment

member is also flagged is_default, so it carries the Default badge.

Role Editor

Clicking a row (or the pencil) opens the Edit Role dialog. There is no read-only detail view — the dialog is the only editor.

Creating a Custom Role

Click Create Role (requires user-roles:create). The dialog fields are:

FieldRequiredNotes
NameYesDisplay name, max 100 characters
SlugYesAuto-derived from the name; editable before saving
DescriptionNoShown under the name in the role list
PermissionsNoCheckbox picker grouped by category (see Permission Categories)

Save to create the role. It becomes immediately available in the per-user role picker.

Editing a Role

The dialog exposes name, description, the permission picker, a Members section, and a Danger Zone. Save Changes stays disabled until something actually changed, and it sends only the changed fields as a PATCH.

For system roles the dialog opens read-only: an italic note reads "System roles are read-only and cannot be modified", the name/description inputs are disabled, and Save is disabled. The pencil is still shown — the block happens inside the dialog, not on the row.

Deleting a Custom Role

The Danger Zone block at the bottom of the edit dialog carries Delete Role, gated on user-roles:delete and rendered only for non-system roles. A confirmation dialog follows. The server also refuses to delete a system role.

Members

The edit dialog contains a Members section: a list of the users holding this role (name, email, avatar), a debounced user search to add more, and a remove button per member. The list is served by GET /api/user-roles/\{id\}/members (backed by the userRoleMembers query, gated on user-roles:read); adding and removing members go through PUT / DELETE /api/user-roles/\{id\}/members/\{userId\} (backed by assignUserRole / removeUserRole, gated on user-roles:edit). The search field and the per-member remove button are gated on user-roles:edit. You can also assign and remove roles from the Roles card on the user detail page.

Permission Categories

The role editor's permission picker offers a fixed set of user-scope permissions, grouped into two categories:

CategoryPermissions
Ideasideas:read, ideas:create, ideas:edit, ideas:delete, ideas:vote
Commentsideas:comment_read, ideas:comment_create, ideas:comment_edit, ideas:comment_delete, ideas:comment_vote

Each category header has a tri-state checkbox that selects or clears the whole group.

The ideas:moderate_* permissions are not offered by the picker: idea moderation is an admin-scope capability and cannot be assigned to a custom user role. The seeded moderator system role carries them server-side (it is immutable and not edited through this picker).

Per-User Role Assignments

From the user detail page at /users/\{id\}, the Roles card lists the user's assignments. A user can hold several roles, and the card mixes both RBAC layers:

  • User roles — badged User, plus System / Default badges where applicable. Removing one requires user-roles:edit.
  • Admin roles — badged Admin. Removing one requires admin-roles:edit.

A single grouped dropdown at the bottom of the card assigns either kind, with User Roles and Admin Roles option groups.

Per-User Permission Overrides

From the user detail page, the Permission Overrides card shows all explicit overrides for that user.

Each override row shows:

  • The permission string (e.g., ideas:create).
  • Status — a Granted or Denied badge.
  • Reason — the free-text reason recorded with the override, or .
  • Set — when the override was created.
  • A remove button.

To add an override, use the Add Override form under the table: pick a permission from the dropdown (populated from /api/assignable-permissions, which mirrors the backend permission registry so the picker cannot drift), choose grant or deny, optionally give a reason, and save.

Overrides layer on top of the role: granting a permission gives it to the user even if their role does not include it; denying removes it even if the role does include it. Per-user overrides are applied before account-level overrides in the resolution chain.

Per-user overrides are gated on user-roles:read (list) and user-roles:edit (set / remove) — not on the per-account override permissions (accounts:overrides-read / accounts:overrides-edit).

Per-Account Permission Overrides

From the account detail page at /accounts/\{id\}, the Permission Overrides card shows the user-scope overrides applied to all users who have that account as their active account when making requests.

The interface mirrors the per-user override UI: each row shows the permission, granted/denied state, and a remove button. Add new overrides via Add Override.

Account overrides are the last layer in the permission resolution chain — they can grant permissions that the user's role and individual overrides do not provide, or deny permissions that they would otherwise have.

Reading the overrides requires accounts:overrides-read; setting or removing them requires accounts:overrides-edit.

Effective Permissions View

The user detail page renders an Effective Permissions card directly (no button, no modal). It shows the fully-resolved permission set for that user — role permissions merged with user overrides and account overrides — grouped by permission category. Any permission that an override contributed is highlighted in amber with an Overridden badge, which makes it easy to see why a user has (or lacks) access.

Permissions

All actions in this section require admin:access (the dashboard-entry gate). In addition:

ActionPermission
View role list, role members, user override lists, resolved permissionsuser-roles:read
Create a role (UI button gate)user-roles:create
Delete a role (UI button gate)user-roles:delete
Create / update / delete roles, assign & unassign roles, set & remove per-user permission overrides (server-side gate)user-roles:edit
Read per-account permission overridesaccounts:overrides-read
Set or remove per-account permission overridesaccounts:overrides-edit

user-roles:create and user-roles:delete exist in the admin permission registry and gate the corresponding buttons in the admin UI, but the API enforces user-roles:edit on every user-role mutation, including create and delete. Grant user-roles:edit alongside them.

System admins implicitly have all permissions.

API

User-role endpoints are not under the /v1/admin prefix — they sit at the /v1 root and are guarded by admin permissions.

UI ActionGraphQLREST
List user rolesuserRolesGET /v1/user-roles
Create rolecreateUserRole(input: CreateUserRoleInput!)POST /v1/user-roles
Update roleupdateUserRole(id: UUID!, input: UpdateUserRoleInput!)PATCH /v1/user-roles/\{id\}
Delete roledeleteUserRole(id: UUID!)DELETE /v1/user-roles/\{id\}
List a user's role assignmentsuserRoleAssignments(userId: UUID!)GET /v1/users/\{user_id\}/roles
Assign user roleassignUserRole(userId, roleId)POST /v1/users/\{user_id\}/roles
Remove user roleremoveUserRole(userId, roleId)DELETE /v1/users/\{user_id\}/roles/\{role_id\}
List user overridesuserPermissionOverrides(userId)GET /v1/users/\{user_id\}/permission-overrides
Set user overridesetUserPermissionOverride(userId, permission, granted, reason)PUT /v1/users/\{user_id\}/permission-overrides
Remove user overrideremoveUserPermissionOverride(userId, permission)DELETE /v1/users/\{user_id\}/permission-overrides/\{permission\}
Resolved permissionsresolvedUserPermissions(userId)GET /v1/users/\{user_id\}/permissions/resolved
List account overridesadminAccountPermissionOverrides(accountId)GET /v1/admin/accounts/\{id\}/permission-overrides
Set account overrideadminSetAccountPermissionOverride(accountId, permission, granted, reason)PUT /v1/admin/accounts/\{id\}/permission-overrides
Remove account overrideadminRemoveAccountPermissionOverride(accountId, permission)DELETE /v1/admin/accounts/\{id\}/permission-overrides/\{permission\}

The admin app does not call these directly — it goes through its own Next.js proxy routes (/api/user-roles/*, /api/users/\{id\}/roles, /api/users/\{id\}/permission-overrides, /api/users/\{id\}/effective-permissions), which execute the GraphQL operations above.