RBAC Playground | Dashforge-UI
DocsStarter Kits
v0.1.0-alpha

RBAC Lab

Interactive playground for experimenting with role-based access control. Edit permissions live and see the RBAC engine respond in real-time.

Interactive RBAC Lab

Switch roles and toggle permissions to see how the RBAC engine evaluates access checks in real-time. This playground demonstrates the core RBAC library behavior.

A. Role & Subject

Select Role

Current Subject

{
  "id": "playground-user",
  "roles": [
    "viewer"
  ]
}
B. Permission Matrix Editor

Toggle permissions for the viewer role:

C. Live Preview

Raw Permission Checks (useCan hook)

can({ action: 'read', resource: 'booking' })

ALLOWED

can({ action: 'update', resource: 'booking' })

DENIED

can({ action: 'delete', resource: 'booking' })

DENIED

can({ action: 'manage', resource: 'booking' })

DENIED

can({ action: 'read', resource: 'user' })

ALLOWED

can({ action: 'update', resource: 'user' })

DENIED

Native HTML Elements

Input (hidden when no 'manage booking' permission)

[Hidden - no permission]

Input (disabled when no 'update booking' permission)

Input (readonly when no 'update user' permission)

Button (hidden when no 'delete booking' permission)

[Hidden - no permission]

Button (disabled when no 'update user' permission)

Dashforge Component (access prop)

TextField with access control (hides when no 'manage booking' permission)

[Hidden - no 'manage booking' permission]

ℹ️

Live editing: Toggle permissions in the matrix editor above and watch all permission checks, native HTML elements, and Dashforge components update instantly. The RBAC engine re-evaluates everything automatically.


How It Works

Understanding live permission editing and RBAC evaluation

This playground demonstrates the core RBAC library in action. Here's what happens when you interact with it:

  1. Role selection determines subject.roles: When you select a role, the subject's roles array updates to contain that role name
  2. Permission matrix mutates the active role definition: Each toggle in the matrix adds or removes a permission from the current role's permission array in the policy
  3. RbacProvider re-renders and re-evaluates checks: When the policy or subject changes, React re-renders all components inside RbacProvider, and the RBAC engine re-evaluates all permission checks
  4. Native HTML and Dashforge previews reflect the same RBAC engine: Both native elements (using useCan hook) and Dashforge components (using access prop) query the same underlying RBAC engine, so they always stay in sync

Here's the actual code pattern powering this playground:

import { useState, useMemo } from 'react';
import { RbacProvider, useCan, type RbacPolicy, type Subject } from '@dashforge/rbac';

function RbacLab() {
  const [selectedRole, setSelectedRole] = useState('viewer');
  const [permissions, setPermissions] = useState({
    'booking.read': true,
    'booking.update': false,
    'booking.delete': false,
  });

  // Build subject from role
  const subject: Subject = useMemo(() => ({
    id: 'user',
    roles: [selectedRole]
  }), [selectedRole]);

  // Build policy from permission state
  const policy: RbacPolicy = useMemo(() => ({
    roles: [{
      name: selectedRole,
      permissions: Object.entries(permissions)
        .filter(([_, enabled]) => enabled)
        .map(([key, _]) => {
          const [resource, action] = key.split('.');
          return { action, resource, effect: 'allow' };
        })
    }]
  }), [selectedRole, permissions]);

  return (
    <RbacProvider policy={policy} subject={subject}>
      {/* Raw checks */}
      <PermissionCheck />
      
      {/* Native HTML */}
      <NativeElements />
      
      {/* Dashforge components */}
      <DashforgeComponents />
    </RbacProvider>
  );
}

function PermissionCheck() {
  // Hook re-runs when policy/subject changes
  const canRead = useCan({ action: 'read', resource: 'booking' });
  return <div>Can read: {canRead ? 'YES' : 'NO'}</div>;
}

function NativeElements() {
  const canUpdate = useCan({ action: 'update', resource: 'booking' });
  return <input disabled={!canUpdate} />;
}

Key insight: The RBAC engine is reactive. When you toggle permissions, the policy object changes, causing RbacProvider to re-render. All useCan hooks and access props re-evaluate automatically, and UI updates immediately.

On This Page