Skip to main content

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 into global (system admin) and account (per-account) modules. Default role definitions with their permission sets. Plan-based limits.
  • Permission Guards -- lo_graphql::PermissionGuard for 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

RoleSlugColorSystemDescription
Ownerowner#f59e0bYesFull account access. All permissions. Cannot be deleted or assigned to other users.
Administratoradministrator#ef4444NoFull access except account deletion and plan changes (enforced via owner_id check).
Moderatormoderator#22c55eNoChat moderation, event monitoring, Spotify control, read access to most features.
Viewerviewer#6b7280NoRead-only access to events, overlays, notifications, and sessions.

API

GraphQL Queries

QueryReturnsPermission
roles[Role!]!roles:read
role(id: UUID!)RoleDetailroles:read
availablePermissions[AccountPermission!]!roles:read
myPermissions[String!]!AuthGuard

GraphQL Mutations

MutationArgsReturnsPermission
createRoleinput: CreateRoleInput!RoleDetail!roles:edit
updateRoleinput: UpdateRoleInput!RoleDetail!roles:edit
deleteRoleid: UUID!RoleMutationResult!roles:delete

REST Endpoints

All paths live under /v1/roles. Bodies are snake_case and mirror the GraphQL inputs.

MethodPathPermissionDescription
GET/v1/rolesroles:readList roles for the account
GET/v1/roles/{id}roles:readGet a single role with its permissions
POST/v1/rolesroles:editCreate a role
PATCH/v1/roles/{id}roles:editUpdate role name, color, sort order, or permissions
DELETE/v1/roles/{id}roles:deleteDelete a role (system roles cannot be deleted)
GET/v1/roles/permissionsroles:readCatalog of available account permissions

Permissions

Global Permissions (System Admin)

PermissionDescription
admin:accessDashboard-entry gate for the admin app
users:readRead user data
users:editModify user data
users:deleteDelete users
accounts:readRead account data
accounts:editModify account data
accounts:deleteDelete accounts
billing:readRead billing information
billing:editModify billing information
support:readRead support tickets
support:editHandle support tickets
features:readRead feature flags
features:editModify feature flags

Account Permissions

CategoryPermissionsDescription
Eventsevents:read, events:create, events:delete, events:userinfoEvent viewing, creation, deletion, user card access
Overlaysoverlays:read, overlays:create, overlays:edit, overlays:deleteFull overlay CRUD
Spotifyspotify:read, spotify:playback, spotify:queue, spotify:playlist, spotify:device, spotify:workerMusic player state, playback control, queue, playlists, device transfer, worker management
Chatchat:read, chat:write, chat:userinfo, chat:delete, chat:ban, chat:timeout, chat:notes, chat:raid, chat:poll, chat:predictionChat messaging, moderation, user profiles, notes, raids, polls, predictions
Connectionsconnections:read, connections:create, connections:edit, connections:deletePlatform connection management
Settingssettings:read, settings:editAccount settings
Membersmembers:read, members:create, members:edit, members:deleteTeam management and invites
Uploadsuploads:read, uploads:create, uploads:deleteFile upload management
Rewardsrewards:read, rewards:create, rewards:edit, rewards:deleteReward configuration
Tokenstokens:read, tokens:create, tokens:edit, tokens:deletePopout token management
Automationsautomations:read, automations:write, automations:execute, automations:historyAutomation CRUD, execution, history
Accountaccount:read, account:edit, account:deleteAccount settings and deletion
Planplan:read, plan:editPlan viewing and changes
Rolesroles:read, roles:edit, roles:deleteRole management (the createRole mutation is guarded by roles:edit)
Sessionssessions:read, sessions:deleteSession management
OBSobs:read, obs:edit, obs:deleteOBS integration configuration
Copyrightcopyright:read, copyright:edit, copyright:delete, copyright:voteCopyright detection and voting
Bot Modulesbot-modules:read, bot-modules:editBot module configuration
SE Tokensse-tokens:read, se-tokens:create, se-tokens:deleteStreamElements token management
Bot Commandsbot-commands:read, bot-commands:create, bot-commands:edit, bot-commands:deleteBot command management
Bot Connectionsbot-connections:read, bot-connections:create, bot-connections:deleteBot connection management

Plan-Based Limits

LimitFreeProEnterprise
Max overlays3----
Max storage100 MB----
Max upload size5 MB----
Max integrations2----
Chat retention7 days----
Custom botNoYesYes
OBS remoteNoYesYes
Copyright detectionNoYesYes

Database

TableDatabaseDescription
rolesPostgreSQLid, account_id, slug, name, description, color, is_system, sort_order, permissions (text array), created_at, updated_at
account_membershipsPostgreSQLLinks users to accounts with a role_id FK

Data Flow

  1. On account creation, DEFAULT_ROLES (Owner, Administrator, Moderator, Viewer) are inserted with their predefined permission sets.
  2. The account owner is assigned the Owner role automatically.
  3. 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.
  4. GraphQL resolvers check permissions via PermissionGuard::new("permission:action").
  5. REST endpoints check permissions via auth.require_permission("permission:action").
  6. When a role is changed or a member is removed, the Redis cache is invalidated.

Key Files

PathDescription
crates/lo-auth/src/rbac.rsPermission constants, default roles, plan limits
crates/lo-graphql/src/PermissionGuard implementation
crates/lo-api/src/extractors.rsAuth extractor with require_permission()
crates/lo-api/src/middleware/auth.rsPermission cache and invalidation