Overview
Control who can see and do what with role-based access control.
Every workspace member has a role. Use WhenPermission to show or hide UI, and usePermissions() when you need to check permissions in code.
import { Permission, WhenPermission } from '@buildbase/sdk/react';
function Sidebar() {
return (
<nav>
<WhenPermission permission={Permission.WORKSPACE_MEMBERS_INVITE}>
<a href="/team">Team</a>
</WhenPermission>
<WhenPermission permission={Permission.WORKSPACE_BILLING_MANAGE}>
<a href="/billing">Billing</a>
</WhenPermission>
</nav>
);
}Default roles
Every organization starts with three workspace roles, plus the workspace's owner:
| Role | Default permissions |
|---|---|
| owner | Everything, including deleting the workspace. The person who created it; not a role you assign |
admin | Every workspace permission except deleting the workspace |
editor | View settings, members, features, billing and usage, and record usage |
viewer | View settings and members |
Custom roles
Add your own workspace roles in the console under Workspaces > Settings, then set what each one may do in the permission matrix. A role you add can be given to members straight away, by invitation or by changing an existing member's role. Until you set its permissions, a custom role gets the same defaults as editor.
Someone who joins a workspace without being given a role gets viewer. You can pick a different Default role on the same settings page.
The permission matrix works at two levels: the organization's matrix applies to every workspace, and a workspace can override it for itself. For each role the first of these that mentions it decides: the workspace's matrix, the organization's matrix, then the defaults above.
Your own permissions
The permissions above are the ones BuildBase enforces: who may invite a member, who may manage billing. Your application has its own ("may this member export a report"), and it can define them in the console under Workspaces > Settings, beside the permission matrix.
A permission is a key, a label and an optional group.
The key is what your code compares, so it is strict: lowercase letters, digits and . : _ -, starting with a letter or digit, up to 64 characters, no spaces. workspace:, buildbase:, system: and org: are reserved for BuildBase. We suggest app:<area>:<action>:
| Key | Label | Group |
|---|---|---|
app:reports:export | Export reports | Reports |
app:documents:publish | Publish documents | Documents |
Grant them per role in the same matrix. Admin holds every permission, yours included, even one you add after admin's column was last saved; its switches are locked on for that reason. Then your frontend asks the same way it asks about any permission:
const { can } = usePermissions();
{
can('app:reports:export') && <ExportButton />;
}And your backend asks the server, instead of trusting the browser:
const res = await fetch(
`${serverUrl}/api/v1/public/workspaces/${workspaceId}/permissions/me`,
{ headers: { 'x-session-id': sessionId } }
);
const { data } = await res.json(); // { role, isOwner, permissions: string[] }
if (!data.permissions.includes('app:reports:export')) return forbidden();That endpoint answers with the permissions the server resolved itself, so your rules cannot drift from the ones BuildBase applies.
Changing one later
- The label and the group can be edited whenever you like.
- The key cannot be renamed. Every grant points at it by name, so a rename would quietly orphan them. Remove the permission and add the new key instead.
- Removing a permission takes its grants with it, in the organization's matrix and in any workspace that overrode it. A key you delete stops answering
trueeverywhere, rather than lingering in a role nobody is looking at. - Every change is in the change history at the bottom of the settings page, as what it did: a permission added, renamed or deleted, and which role gained or lost which permission. Changes made to one workspace's permissions, and to a member's role, are logged against that workspace.
What your plan allows
How many permissions an organization may define is a plan limit, max-custom-workspace-permissions. The counter beside Add permission shows where you are against it. It counts the catalogue, not the grants: one permission given to five roles is one permission.
Note
Keys you already pass through defaultPermissions on SaaSOSProvider keep
working. Defining them in the console adds a label, puts them in front of the
people who administer the organization, and lets your backend check them.
Components
| Component | What it checks |
|---|---|
WhenPermission | Does the user have a specific permission? |
WhenRoles | Does the user have one of these org-level roles? |
WhenWorkspaceRoles | Does the user have one of these workspace roles? |
import { WhenWorkspaceRoles } from '@buildbase/sdk/react';
<WhenWorkspaceRoles roles={['owner', 'admin']}>
<button onClick={() => openWorkspaceSettings()}>Settings</button>
</WhenWorkspaceRoles>;usePermissions()
For imperative permission checks:
import { Permission, usePermissions } from '@buildbase/sdk/react';
function BillingPage() {
const { can, isOwner, role } = usePermissions();
if (!can(Permission.WORKSPACE_BILLING_MANAGE)) {
return <p>No access to billing.</p>;
}
return <BillingSettings />;
}| Return | Type | Description |
|---|---|---|
can(permission) | function | Check if user has a permission |
permissions | Set | Full set of resolved permissions |
isOwner | boolean | Whether user owns the workspace |
role | string | User's role in the workspace |
Custom permissions
Add app-specific permissions via SaaSOSProvider:
<SaaSOSProvider
defaultPermissions={{
admin: ['app:analytics:view', 'app:reports:export'],
editor: ['app:analytics:view'],
}}
>Then check them: can('app:reports:export').
Next Steps
- Checking Permissions - Permission constants and patterns.
- Conditional Rendering -
WhenPermission,WhenRoles,WhenWorkspaceRoles.