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;
});