plotpress/dashboards/{dashboard}/users.yaml
users.yaml lives inside each dashboard folder. It defines the roles referenced by that dashboard’s connections.yaml. A user qualifies for a role through a static email list, an OIDC claim, or both.
Schema
Section titled “Schema”<role_name>: description: string # optional members: [string] # static email list from_claim: string # OIDC claim name match: [string] # values that grant the roleA role can use members, from_claim, or both — the union grants the role.
Static membership
Section titled “Static membership”exec: description: C-suite + finance leads members: - cfo@example.com - ceo@example.com - finance-lead@example.comGood for small, slow-changing roles.
Claim-based membership
Section titled “Claim-based membership”analysts: description: Data analysts (synced from IdP) from_claim: groups match: - data-analytics - data-engineeringWhen the user’s OIDC token includes "groups": ["data-analytics", ...], they hold analysts on this dashboard. Match values are exact strings.
ops: description: SREs + on-call rotation members: - oncall-extern@example.com from_claim: groups match: [sre]The on-call vendor stays in via members; everyone else is synced from the IdP.
Resolution
Section titled “Resolution”On every authenticated request the backend rebuilds the user’s role set for the dashboard being viewed:
- Start with
{}. - For each role whose
membersincludes the user’s email, add the role name. - For each role with
from_claim, look up the claim in the user’s session token; if any value matches, add the role name.
The resolved set is cached for the session lifetime (default 24h). Force a refresh with POST /admin/refresh-users.
Per-dashboard, not workspace-wide
Section titled “Per-dashboard, not workspace-wide”A user holding analysts on dashboards/sales does not automatically hold analysts on dashboards/ops. Each dashboard’s users.yaml is evaluated independently.
Example
Section titled “Example”analysts: from_claim: groups match: [data-analytics, data-engineering]
ops: from_claim: groups match: [sre]
exec: members: - cfo@example.com - ceo@example.com
everyone: description: Anyone authenticated. Use sparingly. from_claim: sub match: ["*"] # special: matches any non-empty value