UNPKG

ra-core

Version:

Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React

112 lines 4.18 kB
import { useCallback } from 'react'; import useAuthProvider from "./useAuthProvider.js"; import useLogout from "./useLogout.js"; import { useNotify } from "../notification/index.js"; import { useNavigate } from "../routing/useNavigate.js"; let timer; /** * Returns a callback used to call the authProvider.checkError() method * and an error from the dataProvider. If the authProvider rejects the call, * the hook logs the user out and shows a logged out notification. * * Used in the useDataProvider hook to check for access denied responses * (e.g. 401 or 403 responses) and trigger a logout. * * @see useLogout * @see useDataProvider * * @returns {Function} logoutIfAccessDenied callback * * @example * * import { useLogoutIfAccessDenied, useNotify, DataProviderContext } from 'react-admin'; * * const FetchRestrictedResource = () => { * const dataProvider = useContext(DataProviderContext); * const logoutIfAccessDenied = useLogoutIfAccessDenied(); * const notify = useNotify() * useEffect(() => { * dataProvider.getOne('secret', { id: 123 }) * .catch(error => { * logoutIfAccessDenied(error); * notify('server error', { type: 'error' }); * }) * }, []); * // ... * } */ const useLogoutIfAccessDenied = () => { const authProvider = useAuthProvider(); const logout = useLogout(); const notify = useNotify(); const navigate = useNavigate(); const handleRedirect = useCallback((url) => { if (url.startsWith('http')) { window.location.href = url; } else { navigate(url); } }, [navigate]); const logoutIfAccessDenied = useCallback(async (errorFromCheckAuth) => { if (!authProvider) { return logoutIfAccessDeniedWithoutProvider(); } try { await authProvider.checkError(errorFromCheckAuth); return false; } catch (errorFromCheckError) { const logoutUser = errorFromCheckError?.logoutUser ?? true; // manual debounce if (timer) { return true; // side effects already triggered in this tick, exit } timer = setTimeout(() => { timer = undefined; }, 0); const redirectTo = errorFromCheckError && errorFromCheckError.redirectTo != null ? errorFromCheckError.redirectTo : errorFromCheckAuth && errorFromCheckAuth.redirectTo ? errorFromCheckAuth.redirectTo : undefined; const shouldNotify = !((errorFromCheckError && errorFromCheckError.message === false) || (errorFromCheckAuth && errorFromCheckAuth.message === false) || redirectTo?.startsWith('http')); if (shouldNotify) { try { // notify only if not yet logged out await authProvider.checkAuth({}); if (logoutUser) { notify(getErrorMessage(errorFromCheckError, 'ra.notification.logged_out'), { type: 'error' }); } else { notify(getErrorMessage(errorFromCheckError, 'ra.notification.not_authorized'), { type: 'error' }); } } catch { // ignore } } if (logoutUser) { logout({}, redirectTo); } else if (redirectTo) { handleRedirect(redirectTo); } return true; } }, [authProvider, logout, notify, handleRedirect]); return logoutIfAccessDenied; }; const logoutIfAccessDeniedWithoutProvider = async () => false; const getErrorMessage = (error, defaultMessage) => typeof error === 'string' ? error : typeof error === 'undefined' || !error.message ? defaultMessage : error.message; export default useLogoutIfAccessDenied; //# sourceMappingURL=useLogoutIfAccessDenied.js.map