useCanAccess

This hook, part of the ra-rbac module, calls the authProvider.getPermissions() to get the role definitions, then checks whether the requested action and resource are allowed for the current user.

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

import { useCanAccess } from '@react-admin/ra-rbac';
import { useRecordContext, DeleteButton } from 'react-admin';

const DeleteUserButton = () => {
    const record = useRecordContext();
    const { loading, canAccess } = useCanAccess({ action: 'delete', resource: 'users', record });
    if (loading || !canAccess) return null;
    return <DeleteButton record={record} resource="users" />;
};

When checking if a user can access a resource, ra-rbac grabs the permissions corresponding to his roles. If at least one of these permissions allows him to access the resource, the user is granted access. Otherwise, the user is denied.

const authProvider= {
    // ...
    getPermissions: () => Promise.resolve({
        permissions: [
            { action: ["read", "create", "edit", "export"], resource: "companies" },
            { action: ["read", "create", "edit"], resource: "people" },
            { action: ["read", "create", "edit", "export"], resource: "deals" },
            { action: ["read", "create"], resource: "comments" },
            { action: ["read", "create", "edit", "delete"], resource: "tasks" },
            { action: ["read", "write"], resource: "sales", record: { "id": "123" } },
        ],
    }),
};

const { canAccess: canReadCompanies } = useCanAccess({ action: "read", resource: "companies" }); // canReadCompanies is true
const { canAccess: canCreatePeople } = useCanAccess({ action: "create", resource: "people" }); // canCreatePeople is true
const { canAccess: canExportPeople } = useCanAccess({ action: "export", resource: "people" }); // canExportPeople is false
const { canAccess: canEditDeals } = useCanAccess({ action: "edit", resource: "deals" }); // canEditDeals is true
const { canAccess: canDeleteComments } = useCanAccess({ action: "delete", resource: "tasks" }); // canDeleteComments is true
const { canAccess: canReadSales } = useCanAccess({ action: "read", resource: "sales" }); // canReadSales is false
const { canAccess: canReadSelfSales } = useCanAccess({ action: "read", resource: "sales" }, { id: "123" }); // canReadSelfSales is true

Tip: The order of permissions as returned by the authProvider isn’t significant. As soon as at least one permission grants access to an action on a resource, the user will be able to perform it.

Tip: useCanAccess is asynchronous, because it calls usePermissions internally. If you have to use useCanAccess several times in a component, the rendered result will “blink” as the multiple calls to authProvider.getPermissions() resolve. To avoid that behavior, you can use the usePermissions hook once, then call the canAccess helper.