Skip to content

useCanAccess

This hook controls access to a resource and action (and, optionally, a record). It calls the authProvider.canAccess() method on mount and returns an object containing a canAccess boolean set to true if users can access the resource and action.

It is part of the Access Control mechanism in ra-core.

useCanAccess takes an object { action, resource, record } as argument. It returns an object describing the state of the request. As calls to the authProvider are asynchronous, the hook returns a isPending state in addition to the canAccess key.

import { useCanAccess, useRecordContext } from 'ra-core';
import { DeleteButton } from './DeleteButton';
const DeleteUserButton = () => {
const record = useRecordContext();
const { isPending, canAccess, error } = useCanAccess({
action: 'delete',
resource: 'users',
record
});
if (isPending || !canAccess) return null;
if (error) return <div>{error.message}</div>
return <DeleteButton record={record} resource="users" />;
};

useCanAccess expects a single parameter object with the following properties:

NameRequiredTypeDefaultDescription
actionRequiredstring-The action to check, e.g. ‘read’, ‘list’, ‘export’, ‘delete’, etc.
resourceOptionsstringResourceContext valueThe resource to check, e.g. ‘users’, ‘comments’, ‘posts’, etc.
recordOptionalobjectRecordContext valueThe record to check. If passed, the child only renders if the user has permissions for that record, e.g. { id: 123, firstName: "John", lastName: "Doe" }

useCanAccessCallback allows to check access to a resource and action on an event instead of on mount. It returns a checkAccess async function that you can call in an event handler.

The checkAccess function expects an argument with the shape { action, resource, record }. This function resolves to a boolean indicating whether users can access the provided resource and action.

import { useCanAccessCallback, ListBase } from 'ra-core';
import { DataTable } from './DataTable';
export const UserList = () => {
const checkAccess = useCanAccessCallback();
const handleRowClick = async (id: Identifier, resource: string, record: Record) => {
try {
const canAccess = await checkAccess({ resource: 'users', action: 'edit', record });
return canAccess ? "edit" : "show";
} catch (error) {
console.error(error);
}
};
return (
<ListBase>
<DataTable onClick={handleRowClick}>
<DataTable.Col source="id" />
<DataTable.Col source="name" />
<DataTable.Col source="email" />
</DataTable>
</ListBase>
);
};

useCanAccessResources can check the access to several resources in parallel (e.g. all the columns of a <DataTable>) instead of just one for useCanAccess.

It takes an object { action, resources, record } as argument. The resources parameter is an array of resource names for which to check the access permission. In addition to react-query result properties, it returns a canAccess object with a property for each provided resource, determining whether the user can access it.

import { useCanAccessResources } from 'ra-core';
import { SimpleList } from './SimpleList';
const UserList = () => {
const { isPending, canAccess } = useCanAccessResources({
action: 'read',
resources: ['users.id', 'users.name', 'users.email'],
});
if (isPending) {
return null;
}
return (
<SimpleList
primaryText={record => canAccess['users.name'] ? record.name : ''}
secondaryText={record => canAccess['users.email'] ? record.email : ''}
tertiaryText={record => canAccess['users.id'] ? record.id : ''}
/>
);
};

useRequireAccess is an alternative to useCanAccess that logs out the user if the access check fails. It takes the same parameters as useCanAccess.

For instance, here’s how you can protect a custom route for editing users settings:

import { useRequireAccess } from 'ra-core';
export export const SettingsPage = () => {
const { isPending } = useRequireAccess({
action: 'edit',
resource: 'settings',
});
if (isPending) return null;
return <p>Protected content</p>;
};