import {
UseMutateAsyncFunction,
useMutation,
UseMutationOptions,
} from '@tanstack/react-query';
import useAuthProvider from './useAuthProvider';
import { HintedString } from '../types';
import { useMemo } from 'react';
/**
* A hook that returns a function you can call to determine whether user has access to the given resource
*
* @example
* import { Datagrid, List, TextField, useCanAccessCallback } from 'react-admin';
*
* const UserList = () => {
* const checkAccess = useCanAccessCallback();
*
* const handleRowClick = (id: Identifier, resource: string, record: Record) => {
* try {
* const canAccess = checkAccess({ resource: 'users', action: 'edit', record });
* return canAccess ? "edit" : "show";
* } catch (error) {
* console.error(error);
* }
* };
*
* return (
*
*
*
*
*
*
*
* );
* };
*/
export const useCanAccessCallback = <
RecordType extends Record = Record,
ErrorType = Error,
>(
options: Omit<
UseMutationOptions<
UseCanAccessCallbackResult,
ErrorType,
UseCanAccessCallbackOptions
>,
'mutationFn'
> = {}
) => {
const authProvider = useAuthProvider();
const authProviderHasCanAccess = !!authProvider?.canAccess;
const { mutateAsync } = useMutation<
UseCanAccessCallbackResult,
ErrorType,
UseCanAccessCallbackOptions
>({
mutationFn: async (
params: UseCanAccessCallbackOptions
): Promise => {
if (!authProvider || !authProvider.canAccess) {
return true;
}
return authProvider.canAccess(params);
},
retry: false,
...options,
});
return useMemo(
() => (authProviderHasCanAccess ? mutateAsync : () => true),
[authProviderHasCanAccess, mutateAsync]
);
};
export type UseCanAccessCallback<
RecordType extends Record = Record,
ErrorType = Error,
> = UseMutateAsyncFunction<
UseCanAccessCallbackResult,
ErrorType,
UseCanAccessCallbackOptions,
unknown
>;
export type UseCanAccessCallbackOptions<
RecordType extends Record = Record,
> = {
resource: string;
action: HintedString<'list' | 'create' | 'edit' | 'show' | 'delete'>;
record?: RecordType;
};
export type UseCanAccessCallbackResult = boolean;