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 react-admin.

Usage

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, DeleteButton } from 'react-admin';

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" />;
};

Parameters

useCanAccess expects a single parameter object with the following properties:

Name Required Type Default Description
action Required string - The action to check, e.g. ‘read’, ‘list’, ‘export’, ‘delete’, etc.
resource Options string ResourceContext value The resource to check, e.g. ‘users’, ‘comments’, ‘posts’, etc.
record Optional object RecordContext value The 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" }

Callback Version

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 { Datagrid, List, TextField, useCanAccessCallback } from 'react-admin';

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 (
        <List>
            <Datagrid onClick={handleRowClick}>
                <TextField source="id" />
                <TextField source="name" />
                <TextField source="email" />
            </Datagrid>
        </List>
    );
};

Multiple Resources

useCanAccessResources can check the access to several resources in parallel (e.g. all the columns of a <Datagrid>) 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, SimpleList } from 'react-admin';

const UserList = () => {
    const { isPending, canAccess } = useCanAccessResources({
        action: 'delete',
        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 : ''}
         />
    );
};

Logout on Failure

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 'react-admin';

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