ra-core
Version:
Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React
118 lines • 4.59 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const useAuthProvider_1 = __importDefault(require("./useAuthProvider.cjs"));
const useLogout_1 = __importDefault(require("./useLogout.cjs"));
const notification_1 = require("../notification/index.cjs");
const useNavigate_1 = require("../routing/useNavigate.cjs");
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 = (0, useAuthProvider_1.default)();
const logout = (0, useLogout_1.default)();
const notify = (0, notification_1.useNotify)();
const navigate = (0, useNavigate_1.useNavigate)();
const handleRedirect = (0, react_1.useCallback)((url) => {
if (url.startsWith('http')) {
window.location.href = url;
}
else {
navigate(url);
}
}, [navigate]);
const logoutIfAccessDenied = (0, react_1.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;
exports.default = useLogoutIfAccessDenied;
module.exports = exports.default;
//# sourceMappingURL=useLogoutIfAccessDenied.js.map