Roles and Permissions
MZAP has three fixed roles. Every user has exactly one role. Permissions are enforced in two places: the web UI hides controls the user cannot use, and the API rejects requests with 401 Unauthorized or 403 Forbidden when the role is insufficient.
Admins have unrestricted access. They can:
- Create, edit, enable/disable, and delete users.
- Change any user’s password and regenerate any user’s API key.
- Enable or disable global authentication.
- Assign players and zones to Operators and Viewers.
- Lock the workspace, forcing all users to log in again.
- Create and delete players; configure audio devices; edit the routing matrix.
- Change application settings, manage jingles, scheduler tasks, and presets.
- Save, load, import, and export workspaces.
Admin always sees every player and zone. The assignment list is ignored for admin users.
Operator
Section titled “Operator”Operators control audio on their assigned resources. They can:
- Play, pause, stop, and seek players assigned to them.
- Adjust player and zone volume, mute, EQ, and compressor on assigned resources.
- Load files and playlists into assigned players.
- Create and edit playlists, jingles, and scheduler tasks.
- Browse the media library and internet radio catalog.
- Subscribe to real-time event and level streams (filtered to their assigned resources).
Operators cannot:
- Create or delete players.
- Add, remove, or reconfigure audio devices.
- Change the routing matrix (which player feeds which zone).
- Manage users or change global settings.
- See or control players and zones that haven’t been assigned to them.
Viewer
Section titled “Viewer”Viewers are read-only. They can:
- See the state of assigned players and zones (current track, state, volume).
- Subscribe to event and level streams for their assigned resources.
Viewers cannot change anything. Every write endpoint returns 403 Forbidden for viewer tokens. Use this role for dashboards, status displays, or kiosk screens that only need to observe.
Permission matrix
Section titled “Permission matrix”| Action | Admin | Operator | Viewer |
|---|---|---|---|
| Log in / log out | yes | yes | yes |
| View assigned players and zones | all | assigned | assigned |
| Play / pause / stop / seek | yes | assigned | no |
| Adjust volume, mute, EQ, compressor | yes | assigned | no |
| Load tracks into a player | yes | assigned | no |
| Create or delete players | yes | no | no |
| Edit the routing matrix | yes | no | no |
| Initialize or remove audio devices | yes | no | no |
| Manage playlists, jingles, scheduler | yes | yes | no |
| Save, load, import, export workspaces | yes | no | no |
| Manage users and API keys | yes | no | no |
| Toggle global authentication | yes | no | no |
| Change application settings | yes | no | no |
| Lock the workspace | yes | no | no |
| Subscribe to event/level SSE streams | all events | filtered | filtered |
“Assigned” means the operation is allowed only on resources in the user’s assignment list (see Player and zone assignments).
UI behavior by role
Section titled “UI behavior by role”The Users tab is only visible to admins. The Devices tab and the Settings save controls are also admin-only. Operators and Viewers see the tabs for day-to-day work — players, zones, playlists, jingles, library, radio, scheduler — but write controls inside those tabs are disabled for Viewers.
When a non-admin is logged in, the players and zones grids render only assigned resources. Assignment changes take effect on the next request; no reload is required.
API behavior by role
Section titled “API behavior by role”Every protected endpoint runs three checks in order:
- Authenticated? No token (or an invalid one) returns
401 Unauthorized. - Role sufficient? A role below the endpoint’s minimum returns
403 Forbidden. - Resource assigned? For endpoints that target a specific player or zone, the ID must be in the user’s assignment list (admins bypass this check). Missing assignment returns
403 Forbidden.
Read-only listing endpoints return a filtered list for Operators and Viewers instead of 403. For example, GET /api/players returns every player for an admin but only assigned players for an operator.
Server-Sent Events from /api/stream/events and /api/stream/levels are filtered the same way: non-admins only receive events for resources assigned to them.