Skip to Content
Welcome to the official DBS Documentation! 📚
FeaturesAccess Control

Access Control

The Access Control page (/dashboard/access) provides administrators a visual interface for managing roles and permissions. Instead of editing seed files, admins can create new roles, adjust what permissions are assigned to each role, and sync permission definitions from code to the database — all without redeployment.

This page requires the roles.manage permission. Only super_admin and admin roles can access it by default.

What You Can Do

  • View all roles — See every role with its full list of assigned permissions
  • Create a custom role — Add a new role (e.g., “Auditor”) with a specific subset of permissions
  • Edit role permissions — Toggle individual permissions on/off for any role
  • Delete a role — Remove a role entirely (users with that role fall back to default)
  • Sync permissions — Push new permission constants from src/lib/rbac/permission.ts to the database without reseeding

API Endpoints

MethodEndpointPermissionDescription
GET/api/access/rolesroles.manageList all roles with permissions
POST/api/access/rolesroles.manageCreate a new role
PUT/api/access/roles/[id]roles.manageUpdate a role’s permissions
DELETE/api/access/roles/[id]roles.manageDelete a role
GET/api/access/permissionsroles.manageList all permissions in the database
POST/api/access/syncroles.manageSync code permission constants → database

Frontend API Client

Use accessApi from src/services/access/api.ts:

import { accessApi } from '@/services/access/api'; // Get all roles with their permissions const { data: roles } = await accessApi.getRoles(); // Get all available permissions const { data: permissions } = await accessApi.getPermissions(); // Create a new role await accessApi.createRole({ name: 'auditor', label: 'Auditor', permissionIds: [3, 7], // IDs of permissions to assign }); // Update a role's permissions await accessApi.updateRole(roleId, { permissionIds: [2, 3, 7, 9], }); // Delete a role await accessApi.deleteRole(roleId); // Sync permission constants to DB await accessApi.syncPermissions();

Fetching Access Data in the UI

'use client'; import { useData } from '@/hooks/use-data'; import { accessApi } from '@/services/access/api'; export function AccessControlPage() { const { data: roles, isLoading: rolesLoading } = useData( 'roles-list', () => accessApi.getRoles() ); const { data: permissions } = useData( 'permissions-list', () => accessApi.getPermissions() ); // Render roles with their permission checkboxes }

Syncing New Permissions

When you add a new permission constant in src/lib/rbac/permission.ts, it won’t be visible in the Access Control UI until it’s synced to the database.

Click the “Sync Permissions” button in the Access Control page header. This calls POST /api/access/sync and inserts any permission keys that don’t yet exist in the database.

The sync operation is additive only — it inserts missing permissions but never deletes existing ones. This means removing a permission constant from code won’t break existing role assignments; you must manually delete deprecated permissions through the UI or a migration.

Custom Role Example

Here’s how to create a read-only “Auditor” role that can view users and logs but cannot write anything:

// Via API or UI await accessApi.createRole({ name: 'auditor', label: 'Auditor', permissionIds: [ permissions.find(p => p.key === 'dashboard.access')!.id, permissions.find(p => p.key === 'user.read')!.id, permissions.find(p => p.key === 'log.read')!.id, permissions.find(p => p.key === 'team.read')!.id, ], });

Then assign this role to users via the Users management page.

Last updated on