UNPKG

@cerbos/react

Version:

A collection of React hooks for interacting with Cerbos policy decision points

200 lines 5.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useCheckResource = useCheckResource; exports.useCheckResources = useCheckResources; exports.useIsAllowed = useIsAllowed; const react_1 = require("react"); const use_deep_compare_effect_1 = require("use-deep-compare-effect"); const use_cerbos_1 = require("./use-cerbos"); function useCerbosRequest(method, request, options) { const [isLoading, setIsLoading] = (0, react_1.useState)(true); const [data, setData] = (0, react_1.useState)(); const [error, setError] = (0, react_1.useState)(); const client = (0, use_cerbos_1.useCerbos)(); const requestMemo = (0, use_deep_compare_effect_1.useDeepCompareMemoize)(request); const optionsMemo = (0, use_deep_compare_effect_1.useDeepCompareMemoize)(options); const load = (0, react_1.useCallback)(async (signal) => // @ts-expect-error -- https://github.com/microsoft/TypeScript/issues/30581 await client[method](requestMemo, { ...optionsMemo, signal, }), [client, method, optionsMemo, requestMemo]); const bundle = activeEmbeddedBundle(client); (0, react_1.useEffect)(() => { setIsLoading(true); setData(undefined); setError(undefined); const abortController = new AbortController(); load(abortController.signal) .then((data) => { if (!abortController.signal.aborted) { setIsLoading(false); setData(data); setError(undefined); } }) .catch((error) => { if (!abortController.signal.aborted) { setIsLoading(false); setData(undefined); setError(error instanceof Error ? error : new Error("An unexpected error occurred", { cause: error })); } }); return () => { abortController.abort(); }; }, [load, bundle]); return { isLoading, data, error }; } function activeEmbeddedBundle({ client }) { return "loader" in client && typeof client.loader === "object" && client.loader && "_active" in client.loader ? client.loader._active : undefined; } /** * Check the principal's permissions on a resource. * * @example * ```typescript * import { useCheckResource } from "@cerbos/react"; * * function SomeComponent() { * const check = useCheckResource({ * resource: { * kind: "document", * id: "1", * attr: { owner: "user@example.com" }, * }, * actions: ["view", "edit"], * }); * * if (check.isLoading) { * // show spinner * return "Loading..."; * } * * if (check.error) { * // handle error * return "Error..."; * } * * return ( * <div> * {check.data.allAllowed() && <button>a button</button>} * {check.data.isAllowed("view") && <button>another button</button>} * </div> * ); * } * ``` * @public */ function useCheckResource(request, options) { return useCerbosRequest("checkResource", request, options); } /** * Check the principal's permissions on a set of resources. * * @example * ```typescript * import { useCheckResources } from "@cerbos/react"; * * function SomeComponent() { * const check = useCheckResources({ * resources: [ * { * resource: { * kind: "document", * id: "1", * attr: { owner: "user@example.com" }, * }, * actions: ["view", "edit"], * }, * { * resource: { * kind: "document", * id: "2", * attr: { owner: "another-user@example.com" }, * }, * actions: ["view", "edit"], * }, * ], * }); * * if (check.isLoading) { * // show spinner * return "Loading..."; * } * * if (check.error) { * // handle error * return "Error..."; * } * * return ( * <div> * {check.data.allAllowed({ * kind: "document", * id: "1", * }) && <button>a button document 1</button>} * {check.data.allAllowed({ * kind: "document", * id: "2", * }) && <button>a button document 2</button>} * {check.data.isAllowed({ * resource: { kind: "document", id: "1" }, * action: "edit", * }) && <button>another button for document 1</button>} * {check.data.isAllowed({ * resource: { kind: "document", id: "2" }, * action: "edit", * }) && <button>another button for document 2</button>} * </div> * ); * } * ``` * @public */ function useCheckResources(request, options) { return useCerbosRequest("checkResources", request, options); } /** * Check if the principal is allowed to perform an action on a resource. * * @example * ```typescript * import { useIsAllowed } from "@cerbos/react"; * * function SomeComponent() { * const check = useIsAllowed({ * resource: { * kind: "document", * id: "1", * attr: { owner: "user@example.com" }, * }, * action: "view", * }); * * if (check.isLoading) { * // show spinner * return "Loading..."; * } * * if (check.error) { * // handle error * return "Error..."; * } * * return <div>{check.data && <button>a button document 1</button>}</div>; * } * ``` * @public */ function useIsAllowed(request, options) { return useCerbosRequest("isAllowed", request, options); } //# sourceMappingURL=use-cerbos-request.js.map