Skip to main content

Access Control List (ACL)

Vivid uses CASL under the hood for access control. You can find the configuration in the src/plugins/casl.ts.

src/plugins/casl.ts
import { PureAbility, type SubjectRawRule } from '@casl/ability';

export type Actions = 'manage' | 'create' | 'read' | 'update' | 'delete';
export type Subjects = 'all' | 'user' | 'other';
export type Rules = SubjectRawRule<Actions, Subjects, unknown>[];

export const ability = new PureAbility<[Actions, Subjects]>([
// Default Ability here
]);
tip

Make sure you read CASL's documentation to understand how it works.

Usage in general

You can directly use the ability object in your components. For example:

src/pages/Profile.tsx
import { ability } from '@casl';

export default function Profile() {
const canUpdate = ability.can('update', 'user');

return (
<div>
{/* ... */}

{canUpdate && <button>Update Profile</button>}
</div>
);
}

Limiting access to routes

You can limit access to specific routes by defining acl options in the Page Handle. For example:

src/pages/Profile.tsx
import type { HandleFunctionResolver } from '@/router';

// ...

export const Handle: HandleFunctionResolver = () => ({
title: 'Profile',
acl: {
action: 'read',
subject: 'user',
},
});
info

Vivid will render NotAvailable layout if the user does not have access to the page.

Updating the ability

If your user has an abilities property, you can use it to update the ability. For example while resolving the user in src/plugins/auth.ts:

src/plugins/auth.ts
import { defineResolve } from '@/lib/core/auth';

export const resolve = defineResolve(async () => {
// mocked user
const res = await axios.get<User>('/me');
const user = res.data;

// Update the ability here
ability.update(user.abilities);

return user;
});