Roles & Permissions
Overview
The Roles & Permissions module implements a granular Role-Based Access Control (RBAC) system. Every account starts with 4 default roles (Owner, Administrator, Moderator, Viewer), and custom roles can be created. The system defines 80+ permissions across 20+ categories using a category:action naming convention (e.g., chat:read, overlays:edit). Permissions are enforced at the GraphQL layer via PermissionGuard and at the REST layer via Auth::require_permission(). Permission checks are cached in Redis for performance.
Architecture
Backend
- RBAC Constants (
crates/lo-auth/src/rbac.rs) -- All permission constants organized intoglobal(system admin) andaccount(per-account) modules. Default role definitions with their permission sets. Plan-based limits. - Permission Guards --
lo_graphql::PermissionGuardfor GraphQL resolvers.Auth::require_permission()for REST endpoints. Both check the authenticated user's permissions for the active account. - Permission Cache -- Permissions are cached in Redis per user/account pair. Cache is invalidated when roles are changed via
invalidate_permission_cache(). - Database -- Roles and their permissions are stored in PostgreSQL. Default roles are created on account creation.
Default Roles
| Role | Slug | Color | System | Description |
|---|---|---|---|---|
| Owner | owner | #f59e0b | Yes | Full account access. All permissions. Cannot be deleted or assigned to other users. |
| Administrator | administrator | #ef4444 | No | Full access except account deletion and plan changes (enforced via owner_id check). |
| Moderator | moderator | #22c55e | No | Chat moderation, event monitoring, Spotify control, read access to most features. |
| Viewer | viewer | #6b7280 | No | Read-only access to events, overlays, notifications, and sessions. |
API
GraphQL Queries
| Query | Returns | Permission |
|---|---|---|
roles | [Role!]! | roles:read |
role(id: UUID!) | RoleDetail | roles:read |
availablePermissions | [AccountPermission!]! | roles:read |
myPermissions | [String!]! | AuthGuard |
GraphQL Mutations
| Mutation | Args | Returns | Permission |
|---|---|---|---|
createRole | input: CreateRoleInput! | RoleDetail! | roles:edit |
updateRole | input: UpdateRoleInput! | RoleDetail! | roles:edit |
deleteRole | id: UUID! | RoleMutationResult! | roles:delete |
REST Endpoints
All paths live under /v1/roles. Bodies are snake_case and mirror the GraphQL inputs.
| Method | Path | Permission | Description |
|---|---|---|---|
GET | /v1/roles | roles:read | List roles for the account |
GET | /v1/roles/{id} | roles:read | Get a single role with its permissions |
POST | /v1/roles | roles:edit | Create a role |
PATCH | /v1/roles/{id} | roles:edit | Update role name, color, sort order, or permissions |
DELETE | /v1/roles/{id} | roles:delete | Delete a role (system roles cannot be deleted) |
GET | /v1/roles/permissions | roles:read | Catalog of available account permissions |
Permissions
Global Permissions (System Admin)
| Permission | Description |
|---|---|
admin:access | Dashboard-entry gate for the admin app |
users:read | Read user data |
users:edit | Modify user data |
users:delete | Delete users |
accounts:read | Read account data |
accounts:edit | Modify account data |
accounts:delete | Delete accounts |
billing:read | Read billing information |
billing:edit | Modify billing information |
support:read | Read support tickets |
support:edit | Handle support tickets |
features:read | Read feature flags |
features:edit | Modify feature flags |
Account Permissions
| Category | Permissions | Description |
|---|---|---|
| Events | events:read, events:create, events:delete, events:userinfo | Event viewing, creation, deletion, user card access |
| Overlays | overlays:read, overlays:create, overlays:edit, overlays:delete | Full overlay CRUD |
| Spotify | spotify:read, spotify:playback, spotify:queue, spotify:playlist, spotify:device, spotify:worker | Music player state, playback control, queue, playlists, device transfer, worker management |
| Chat | chat:read, chat:write, chat:userinfo, chat:delete, chat:ban, chat:timeout, chat:notes, chat:raid, chat:poll, chat:prediction | Chat messaging, moderation, user profiles, notes, raids, polls, predictions |
| Connections | connections:read, connections:create, connections:edit, connections:delete | Platform connection management |
| Settings | settings:read, settings:edit | Account settings |
| Members | members:read, members:create, members:edit, members:delete | Team management and invites |
| Uploads | uploads:read, uploads:create, uploads:delete | File upload management |
| Rewards | rewards:read, rewards:create, rewards:edit, rewards:delete | Reward configuration |
| Tokens | tokens:read, tokens:create, tokens:edit, tokens:delete | Popout token management |
| Automations | automations:read, automations:write, automations:execute, automations:history | Automation CRUD, execution, history |
| Account | account:read, account:edit, account:delete | Account settings and deletion |
| Plan | plan:read, plan:edit | Plan viewing and changes |
| Roles | roles:read, roles:edit, roles:delete | Role management (the createRole mutation is guarded by roles:edit) |
| Sessions | sessions:read, sessions:delete | Session management |
| OBS | obs:read, obs:edit, obs:delete | OBS integration configuration |
| Copyright | copyright:read, copyright:edit, copyright:delete, copyright:vote | Copyright detection and voting |
| Bot Modules | bot-modules:read, bot-modules:edit | Bot module configuration |
| SE Tokens | se-tokens:read, se-tokens:create, se-tokens:delete | StreamElements token management |
| Bot Commands | bot-commands:read, bot-commands:create, bot-commands:edit, bot-commands:delete | Bot command management |
| Bot Connections | bot-connections:read, bot-connections:create, bot-connections:delete | Bot connection management |
Plan-Based Limits
| Limit | Free | Pro | Enterprise |
|---|---|---|---|
| Max overlays | 3 | -- | -- |
| Max storage | 100 MB | -- | -- |
| Max upload size | 5 MB | -- | -- |
| Max integrations | 2 | -- | -- |
| Chat retention | 7 days | -- | -- |
| Custom bot | No | Yes | Yes |
| OBS remote | No | Yes | Yes |
| Copyright detection | No | Yes | Yes |
Database
| Table | Database | Description |
|---|---|---|
roles | PostgreSQL | id, account_id, slug, name, description, color, is_system, sort_order, permissions (text array), created_at, updated_at |
account_memberships | PostgreSQL | Links users to accounts with a role_id FK |
Data Flow
- On account creation,
DEFAULT_ROLES(Owner, Administrator, Moderator, Viewer) are inserted with their predefined permission sets. - The account owner is assigned the Owner role automatically.
- When a user makes an API request, the auth middleware resolves their permissions:
- Check Redis cache for the user/account pair.
- If not cached, query the user's role and its permissions from PostgreSQL.
- Cache the result in Redis.
- GraphQL resolvers check permissions via
PermissionGuard::new("permission:action"). - REST endpoints check permissions via
auth.require_permission("permission:action"). - When a role is changed or a member is removed, the Redis cache is invalidated.
Key Files
| Path | Description |
|---|---|
crates/lo-auth/src/rbac.rs | Permission constants, default roles, plan limits |
crates/lo-graphql/src/ | PermissionGuard implementation |
crates/lo-api/src/extractors.rs | Auth extractor with require_permission() |
crates/lo-api/src/middleware/auth.rs | Permission cache and invalidation |