BuildBaseBuildBase

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:

RoleDefault permissions
ownerEverything, including deleting the workspace. The person who created it; not a role you assign
adminEvery workspace permission except deleting the workspace
editorView settings, members, features, billing and usage, and record usage
viewerView 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>:

KeyLabelGroup
app:reports:exportExport reportsReports
app:documents:publishPublish documentsDocuments

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 true everywhere, 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

ComponentWhat it checks
WhenPermissionDoes the user have a specific permission?
WhenRolesDoes the user have one of these org-level roles?
WhenWorkspaceRolesDoes 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 />;
}
ReturnTypeDescription
can(permission)functionCheck if user has a permission
permissionsSetFull set of resolved permissions
isOwnerbooleanWhether user owns the workspace
rolestringUser'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