@availity/mui-authorize 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
+
5
+ ## 0.1.0 (2024-05-10)
6
+
7
+ ### Dependency Updates
8
+
9
+ * `mui-block-ui` updated to version `0.1.0`
10
+
11
+ ### Features
12
+
13
+ * **mui-authorize:** add authorize package ([ff64501](https://github.com/Availity/element/commit/ff6450141021d74657e53e85213ce00b638a6465))
package/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # @availity/mui-authorize
2
+
3
+ > Availity MUI Authorize component to be used with @availity/element design system.
4
+
5
+ [![Version](https://img.shields.io/npm/v/@availity/mui-authorize.svg?style=for-the-badge)](https://www.npmjs.com/package/@availity/mui-authorize)
6
+ [![NPM Downloads](https://img.shields.io/npm/dt/@availity/mui-authorize.svg?style=for-the-badge)](https://www.npmjs.com/package/@availity/mui-authorize)
7
+ [![Dependency Status](https://img.shields.io/librariesio/release/npm/@availity/mui-authorize?style=for-the-badge)](https://github.com/Availity/element/blob/main/packages/mui-authorize/package.json)
8
+
9
+ ## Documentation
10
+
11
+ This package extends the MUI Authorize component: [MUI Authorize Docs](https://mui.com/components/authorize/)
12
+
13
+ Live demo and documentation in our [Storybook](https://availity.github.io/element/?path=/docs/components-authorize-introduction--docs)
14
+
15
+ Availity standards for design and usage can be found in the [Availity Design Guide](https://zeroheight.com/2e36e50c7)
16
+
17
+ ## Installation
18
+
19
+ ### Import Through @availity/element (Recommended)
20
+
21
+ #### NPM
22
+
23
+ ```bash
24
+ npm install @availity/element
25
+ ```
26
+
27
+ #### Yarn
28
+
29
+ ```bash
30
+ yarn add @availity/element
31
+ ```
32
+
33
+ ### Direct Import
34
+
35
+ #### NPM
36
+
37
+ _This package has a few peer dependencies. Add `@mui/material` & `@emotion/react` to your project if not already installed._
38
+
39
+ ```bash
40
+ npm install @availity/mui-authorize
41
+ ```
42
+
43
+ #### Yarn
44
+
45
+ ```bash
46
+ yarn add @availity/mui-authorize
47
+ ```
48
+
49
+ ### Usage
50
+
51
+ #### Import through @availity/element
52
+
53
+ ```tsx
54
+ import { Authorize } from '@availity/element';
55
+ ```
56
+
57
+ #### Direct import
58
+
59
+ ```tsx
60
+ import { Authorize } from '@availity/mui-authorize';
61
+ ```
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from 'react';
2
+ import { UseAuthorizeProps } from '@availity/authorize';
3
+
4
+ type AuthorizeProps = {
5
+ /** The content that renders when the user does have the permissions required. */
6
+ children?: ReactNode;
7
+ /** When true, BlockUi is used when loading the permissions. When a node, that node is rendered instead of BlockUi when loading the permissions. When false, nothing is rendered when loading the permissions. Default: true. */
8
+ loader?: boolean | ReactNode;
9
+ /** Negate the authorization. If the user does have the permissions specified, they are considered "unauthorized" (shown the unauthorized prop content). If the user does not have the permissions specified, they are considered "authorized" (shown the children prop content) */
10
+ negate?: boolean;
11
+ /** The content that renders when the user does not have the permissions required. */
12
+ unauthorized?: ReactNode;
13
+ } & UseAuthorizeProps;
14
+ /** Component for showing content based on the user's permissions. Wrap this component around content you only want specific users to see.
15
+ *
16
+ * The `useAuthorize` hook utilizes [react-query](https://tanstack.com/query/v4/docs/framework/react/overview) to handle data fetching.
17
+ * This means you must add a [QueryClientProvider](https://tanstack.com/query/v4/docs/framework/react/reference/QueryClientProvider)
18
+ * to your app if you do not already have one.
19
+ *
20
+ * The default setup should cover most use-cases. However, there are 2 query options we recommend looking into
21
+ * in order to determine what is correct for your app. These settings are `refetchOnWindowFocus` and
22
+ * `staleTime`. The first option sets whether the to refetch the query when the window is focused, and
23
+ * the other is the default marker for how long the query is valid.
24
+ */
25
+ declare const Authorize: ({ loader, negate, children, unauthorized, permissions, parameters, queryOptions }: AuthorizeProps) => JSX.Element | null;
26
+
27
+ export { Authorize, type AuthorizeProps };
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from 'react';
2
+ import { UseAuthorizeProps } from '@availity/authorize';
3
+
4
+ type AuthorizeProps = {
5
+ /** The content that renders when the user does have the permissions required. */
6
+ children?: ReactNode;
7
+ /** When true, BlockUi is used when loading the permissions. When a node, that node is rendered instead of BlockUi when loading the permissions. When false, nothing is rendered when loading the permissions. Default: true. */
8
+ loader?: boolean | ReactNode;
9
+ /** Negate the authorization. If the user does have the permissions specified, they are considered "unauthorized" (shown the unauthorized prop content). If the user does not have the permissions specified, they are considered "authorized" (shown the children prop content) */
10
+ negate?: boolean;
11
+ /** The content that renders when the user does not have the permissions required. */
12
+ unauthorized?: ReactNode;
13
+ } & UseAuthorizeProps;
14
+ /** Component for showing content based on the user's permissions. Wrap this component around content you only want specific users to see.
15
+ *
16
+ * The `useAuthorize` hook utilizes [react-query](https://tanstack.com/query/v4/docs/framework/react/overview) to handle data fetching.
17
+ * This means you must add a [QueryClientProvider](https://tanstack.com/query/v4/docs/framework/react/reference/QueryClientProvider)
18
+ * to your app if you do not already have one.
19
+ *
20
+ * The default setup should cover most use-cases. However, there are 2 query options we recommend looking into
21
+ * in order to determine what is correct for your app. These settings are `refetchOnWindowFocus` and
22
+ * `staleTime`. The first option sets whether the to refetch the query when the window is focused, and
23
+ * the other is the default marker for how long the query is valid.
24
+ */
25
+ declare const Authorize: ({ loader, negate, children, unauthorized, permissions, parameters, queryOptions }: AuthorizeProps) => JSX.Element | null;
26
+
27
+ export { Authorize, type AuthorizeProps };
package/dist/index.js ADDED
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ Authorize: () => Authorize
24
+ });
25
+ module.exports = __toCommonJS(src_exports);
26
+
27
+ // src/lib/Authorize.tsx
28
+ var import_mui_block_ui = require("@availity/mui-block-ui");
29
+ var import_authorize = require("@availity/authorize");
30
+ var import_jsx_runtime = require("react/jsx-runtime");
31
+ var Authorize = ({
32
+ loader = true,
33
+ negate = false,
34
+ children = null,
35
+ unauthorized = null,
36
+ permissions,
37
+ parameters = {},
38
+ queryOptions
39
+ }) => {
40
+ const { authorized, isLoading } = (0, import_authorize.useAuthorize)(permissions, parameters, queryOptions);
41
+ if (isLoading) {
42
+ if (loader)
43
+ return loader === true ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_mui_block_ui.BlockUi, { blocking: true }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: loader });
44
+ return null;
45
+ }
46
+ if ((authorized || negate) && !(authorized && negate)) {
47
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
48
+ }
49
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: unauthorized });
50
+ };
51
+ // Annotate the CommonJS export names for ESM import in node:
52
+ 0 && (module.exports = {
53
+ Authorize
54
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,27 @@
1
+ // src/lib/Authorize.tsx
2
+ import { BlockUi } from "@availity/mui-block-ui";
3
+ import { useAuthorize } from "@availity/authorize";
4
+ import { Fragment, jsx } from "react/jsx-runtime";
5
+ var Authorize = ({
6
+ loader = true,
7
+ negate = false,
8
+ children = null,
9
+ unauthorized = null,
10
+ permissions,
11
+ parameters = {},
12
+ queryOptions
13
+ }) => {
14
+ const { authorized, isLoading } = useAuthorize(permissions, parameters, queryOptions);
15
+ if (isLoading) {
16
+ if (loader)
17
+ return loader === true ? /* @__PURE__ */ jsx(BlockUi, { blocking: true }) : /* @__PURE__ */ jsx(Fragment, { children: loader });
18
+ return null;
19
+ }
20
+ if ((authorized || negate) && !(authorized && negate)) {
21
+ return /* @__PURE__ */ jsx(Fragment, { children });
22
+ }
23
+ return /* @__PURE__ */ jsx(Fragment, { children: unauthorized });
24
+ };
25
+ export {
26
+ Authorize
27
+ };
@@ -0,0 +1,7 @@
1
+ import { Markdown } from '@storybook/blocks';
2
+ import { Meta } from '@storybook/addon-docs';
3
+ import ReadMe from './README.md?raw';
4
+
5
+ <Meta title="Components/Authorize/Introduction" />
6
+
7
+ <Markdown>{ReadMe}</Markdown>
package/jest.config.js ADDED
@@ -0,0 +1,7 @@
1
+ const global = require('../../jest.config.global');
2
+
3
+ module.exports = {
4
+ ...global,
5
+ displayName: 'authorize',
6
+ coverageDirectory: '../../coverage/authorize'
7
+ };
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@availity/mui-authorize",
3
+ "version": "0.1.0",
4
+ "description": "Availity Authorize Component - part of the @availity/element design system",
5
+ "keywords": [
6
+ "react",
7
+ "typescript",
8
+ "availity",
9
+ "mui"
10
+ ],
11
+ "homepage": "https://availity.github.io/element/?path=/docs/components-authorize-introduction--docs",
12
+ "bugs": {
13
+ "url": "https://github.com/Availity/element/issues"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/Availity/element.git",
18
+ "directory": "packages/authorize"
19
+ },
20
+ "license": "MIT",
21
+ "author": "Availity Developers <AVOSS@availity.com>",
22
+ "browser": "./dist/index.js",
23
+ "main": "./dist/index.js",
24
+ "module": "./dist/index.mjs",
25
+ "types": "./dist/index.d.ts",
26
+ "scripts": {
27
+ "build": "tsup src/index.ts --format esm,cjs --dts",
28
+ "dev": "tsup src/index.ts --format esm,cjs --watch --dts",
29
+ "clean": "rm -rf dist",
30
+ "clean:nm": "rm -rf node_modules",
31
+ "publish": "yarn npm publish --tolerate-republish --access public",
32
+ "publish:canary": "yarn npm publish --access public --tag canary"
33
+ },
34
+ "dependencies": {
35
+ "@availity/authorize": "^4.1.0",
36
+ "@availity/mui-block-ui": "^0.1.10",
37
+ "@tanstack/react-query": "^4.36.1"
38
+ },
39
+ "devDependencies": {
40
+ "@mui/material": "^5.15.15",
41
+ "react": "18.2.0",
42
+ "react-dom": "18.2.0",
43
+ "tsup": "^8.0.2",
44
+ "typescript": "^5.4.5"
45
+ },
46
+ "peerDependencies": {
47
+ "@mui/material": "^5.11.9",
48
+ "react": ">=16.3.0"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ }
53
+ }
package/project.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "mui-authorize",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "packages/authorize/src",
5
+ "projectType": "library",
6
+ "tags": [],
7
+ "targets": {
8
+ "lint": {
9
+ "executor": "@nx/eslint:lint",
10
+ "options": {
11
+ "eslintConfig": ".eslintrc.json",
12
+ "lintFilePatterns": ["packages/authorize/**/*.{js,ts}"],
13
+ "silent": false,
14
+ "fix": false,
15
+ "cache": true,
16
+ "cacheLocation": "./node_modules/.cache/authorize/.eslintcache",
17
+ "maxWarnings": -1,
18
+ "quiet": false,
19
+ "noEslintrc": false,
20
+ "hasTypeAwareRules": true,
21
+ "cacheStrategy": "metadata"
22
+ }
23
+ },
24
+ "test": {
25
+ "executor": "@nx/jest:jest",
26
+ "outputs": ["{workspaceRoot}/coverage/authorize"],
27
+ "options": {
28
+ "jestConfig": "packages/authorize/jest.config.js",
29
+ "passWithNoTests": true
30
+ }
31
+ },
32
+ "version": {
33
+ "executor": "@jscutlery/semver:version",
34
+ "options": {
35
+ "preset": "conventional",
36
+ "commitMessageFormat": "chore({projectName}): release version ${version} [skip ci]",
37
+ "tagPrefix": "@availity/{projectName}@",
38
+ "trackDeps": true,
39
+ "skipCommitTypes": ["docs"]
40
+ }
41
+ }
42
+ }
43
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './lib/Authorize';
@@ -0,0 +1,61 @@
1
+ // Each exported component in the package should have its own stories file
2
+
3
+ import type { Meta, StoryObj } from '@storybook/react';
4
+ import { Authorize, AuthorizeProps } from '..';
5
+ import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
6
+ import Alert from '@mui/material/Alert';
7
+
8
+ const meta: Meta<typeof Authorize> = {
9
+ title: 'Components/Authorize/Authorize',
10
+ component: Authorize,
11
+ tags: ['autodocs'],
12
+ decorators: [
13
+ (Story: () => JSX.Element) => (
14
+ <QueryClientProvider client={new QueryClient()}>
15
+ <Story />
16
+ </QueryClientProvider>
17
+ ),
18
+ ],
19
+ args: {
20
+ permissions: ['1234'],
21
+ parameters: {
22
+ organizationId: '1111',
23
+ region: true,
24
+ },
25
+ queryOptions: {
26
+ refetchOnWindowFocus: false,
27
+ },
28
+ unauthorized: 'You are not authorized to see this content.',
29
+ children: 'You are authorized to see this content.',
30
+ negate: false,
31
+ loader: true,
32
+ },
33
+ argTypes: {
34
+ children: {
35
+ control: 'text',
36
+ },
37
+ unauthorized: {
38
+ control: 'text',
39
+ },
40
+ },
41
+ };
42
+
43
+ export default meta;
44
+
45
+ export const _Authorize: StoryObj<typeof Authorize> = {
46
+ render: ({children, unauthorized, ...args}: AuthorizeProps) => (
47
+ <div>
48
+ <p>
49
+ For this demo, the following permissions are granted: 1234, 2345, 3456, 4567, 5678, 6789. You can use the knobs
50
+ to see what the component will do when you set the required permissions to various things.
51
+ </p>
52
+ <hr />
53
+ <Authorize
54
+ unauthorized={<Alert severity="error">{unauthorized}</Alert>}
55
+ {...args}
56
+ >
57
+ <Alert severity="success">{children}</Alert>
58
+ </Authorize>
59
+ </div>
60
+ ),
61
+ };
@@ -0,0 +1,196 @@
1
+ import React from 'react';
2
+ import { render, screen, waitFor } from '@testing-library/react';
3
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4
+ // eslint-disable-next-line @nx/enforce-module-boundaries
5
+ import { server } from '@availity/mock/src/lib/server';
6
+ import { Authorize } from './Authorize';
7
+
8
+ describe('Authorize', () => {
9
+ const queryClient = new QueryClient();
10
+
11
+ // start msw server
12
+ beforeAll(() => server.listen());
13
+
14
+ // clear cache and reset msw handlers
15
+ afterEach(() => {
16
+ queryClient.clear();
17
+ server.resetHandlers();
18
+ });
19
+
20
+ // terminate the server
21
+ afterAll(() => server.close());
22
+
23
+ test('should render authorized content', async () => {
24
+ render(
25
+ <QueryClientProvider client={queryClient}>
26
+ <Authorize permissions={['1234']} loader>
27
+ You have permission to see this
28
+ </Authorize>
29
+ </QueryClientProvider>
30
+ );
31
+
32
+ await waitFor(() => {
33
+ expect(screen.getByText('You have permission to see this')).toBeDefined();
34
+ });
35
+ });
36
+
37
+ test('should render unauthorized content', async () => {
38
+ render(
39
+ <QueryClientProvider client={queryClient}>
40
+ <Authorize permissions={['12345']} unauthorized="You do not have permission to see this" />
41
+ </QueryClientProvider>
42
+ );
43
+
44
+ await waitFor(() => {
45
+ expect(screen.getByText('You do not have permission to see this')).toBeDefined();
46
+ });
47
+ });
48
+
49
+ test('should render authorized with array of permissions', async () => {
50
+ render(
51
+ <QueryClientProvider client={queryClient}>
52
+ <Authorize
53
+ permissions={['1234', '2345', ['3456', '4567']]}
54
+ unauthorized="You do not have permission to see this"
55
+ >
56
+ You have permission to see this
57
+ </Authorize>
58
+ </QueryClientProvider>
59
+ );
60
+
61
+ await waitFor(() => {
62
+ expect(screen.getByText('You have permission to see this')).toBeDefined();
63
+ });
64
+ });
65
+
66
+ test('should render negate permissions', async () => {
67
+ render(
68
+ <QueryClientProvider client={queryClient}>
69
+ <Authorize permissions={['1234']} negate unauthorized="You do not have permission to see this">
70
+ You have permission to see this
71
+ </Authorize>
72
+ </QueryClientProvider>
73
+ );
74
+
75
+ await waitFor(() => {
76
+ expect(screen.getByText('You do not have permission to see this')).toBeDefined();
77
+ });
78
+ });
79
+
80
+ test('should render authorized with correct organizationId', async () => {
81
+ render(
82
+ <QueryClientProvider client={queryClient}>
83
+ <Authorize permissions={['1234']} parameters={{organizationId:"1111"}} unauthorized="You do not have permission to see this">
84
+ You have permission to see this
85
+ </Authorize>
86
+ </QueryClientProvider>
87
+ );
88
+
89
+ await waitFor(() => {
90
+ expect(screen.getByText('You have permission to see this')).toBeDefined();
91
+ });
92
+ });
93
+
94
+ test('should render unauthorized with incorrect organizationId', async () => {
95
+ render(
96
+ <QueryClientProvider client={queryClient}>
97
+ <Authorize permissions={['1234']} parameters={{organizationId:"1112"}} unauthorized="You do not have permission to see this">
98
+ You have permission to see this
99
+ </Authorize>
100
+ </QueryClientProvider>
101
+ );
102
+
103
+ await waitFor(() => {
104
+ expect(screen.getByText('You do not have permission to see this')).toBeDefined();
105
+ });
106
+ });
107
+
108
+ test('should render authorized with correct customerId', async () => {
109
+ render(
110
+ <QueryClientProvider client={queryClient}>
111
+ <Authorize permissions={['1234']} parameters={{customerId:"1194"}} unauthorized="You do not have permission to see this">
112
+ You have permission to see this
113
+ </Authorize>
114
+ </QueryClientProvider>
115
+ );
116
+
117
+ await waitFor(() => {
118
+ expect(screen.getByText('You have permission to see this')).toBeDefined();
119
+ });
120
+ });
121
+
122
+ test('should render unauthorized with incorrect customerId', async () => {
123
+ render(
124
+ <QueryClientProvider client={queryClient}>
125
+ <Authorize permissions={['1234']} parameters={{customerId:"1193"}} unauthorized="You do not have permission to see this">
126
+ You have permission to see this
127
+ </Authorize>
128
+ </QueryClientProvider>
129
+ );
130
+
131
+ await waitFor(() => {
132
+ expect(screen.getByText('You do not have permission to see this')).toBeDefined();
133
+ });
134
+ });
135
+
136
+ test('should render authorized with correct resources', async () => {
137
+ render(
138
+ <QueryClientProvider client={queryClient}>
139
+ <Authorize
140
+ permissions={['1234']}
141
+ parameters={{customerId:"1194", resources: ['2']}}
142
+ unauthorized="You do not have permission to see this"
143
+ >
144
+ You have permission to see this
145
+ </Authorize>
146
+ </QueryClientProvider>
147
+ );
148
+
149
+ await waitFor(() => {
150
+ expect(screen.getByText('You have permission to see this')).toBeDefined();
151
+ });
152
+ });
153
+
154
+ test('should render unauthorized with incorrect resources', async () => {
155
+ render(
156
+ <QueryClientProvider client={queryClient}>
157
+ <Authorize
158
+ permissions={['1234']}
159
+ parameters={{customerId:"1194", resources: ['5']}}
160
+ unauthorized="You do not have permission to see this"
161
+ >
162
+ You have permission to see this
163
+ </Authorize>
164
+ </QueryClientProvider>
165
+ );
166
+
167
+ await waitFor(() => {
168
+ expect(screen.getByText('You do not have permission to see this')).toBeDefined();
169
+ });
170
+ });
171
+
172
+ test('shows BlockUi while fetching permissions', async () => {
173
+ render(
174
+ <QueryClientProvider client={queryClient}>
175
+ <Authorize permissions={['1234']} loader>
176
+ You have permission to see this
177
+ </Authorize>
178
+ </QueryClientProvider>
179
+ );
180
+ const loadingElements = screen.getAllByText('loading');
181
+
182
+ // Filter out the visible one
183
+ const visibleLoadingElement = loadingElements.find((element) => {
184
+ // Get computed style of the element
185
+ const style = window.getComputedStyle(element);
186
+
187
+ // Return true if the element is visible
188
+ return style && style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';
189
+ });
190
+ expect(visibleLoadingElement).toBeInTheDocument();
191
+
192
+ // Once data has been fetched, the BlockUi component should no longer be visible
193
+ await waitFor(() => expect(visibleLoadingElement).not.toBeVisible());
194
+ await waitFor(() => expect(screen.getByText('You have permission to see this')).toBeInTheDocument());
195
+ });
196
+ });
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import type { ReactNode } from 'react';
3
+ import { BlockUi } from '@availity/mui-block-ui';
4
+
5
+ import { useAuthorize, UseAuthorizeProps } from '@availity/authorize';
6
+
7
+ export type AuthorizeProps = {
8
+ /** The content that renders when the user does have the permissions required. */
9
+ children?: ReactNode;
10
+ /** When true, BlockUi is used when loading the permissions. When a node, that node is rendered instead of BlockUi when loading the permissions. When false, nothing is rendered when loading the permissions. Default: true. */
11
+ loader?: boolean | ReactNode;
12
+ /** Negate the authorization. If the user does have the permissions specified, they are considered "unauthorized" (shown the unauthorized prop content). If the user does not have the permissions specified, they are considered "authorized" (shown the children prop content) */
13
+ negate?: boolean;
14
+ /** The content that renders when the user does not have the permissions required. */
15
+ unauthorized?: ReactNode;
16
+ // } & Pick<UseAuthorizeProps, 'permissions' | 'queryOptions'> & UseAuthorizeProps['parameters'];
17
+ } & UseAuthorizeProps;
18
+
19
+ /** Component for showing content based on the user's permissions. Wrap this component around content you only want specific users to see.
20
+ *
21
+ * The `useAuthorize` hook utilizes [react-query](https://tanstack.com/query/v4/docs/framework/react/overview) to handle data fetching.
22
+ * This means you must add a [QueryClientProvider](https://tanstack.com/query/v4/docs/framework/react/reference/QueryClientProvider)
23
+ * to your app if you do not already have one.
24
+ *
25
+ * The default setup should cover most use-cases. However, there are 2 query options we recommend looking into
26
+ * in order to determine what is correct for your app. These settings are `refetchOnWindowFocus` and
27
+ * `staleTime`. The first option sets whether the to refetch the query when the window is focused, and
28
+ * the other is the default marker for how long the query is valid.
29
+ */
30
+ export const Authorize = ({
31
+ loader = true,
32
+ negate = false,
33
+ children = null,
34
+ unauthorized = null,
35
+ permissions,
36
+ parameters = {},
37
+ queryOptions
38
+ }: AuthorizeProps): JSX.Element | null => {
39
+ const { authorized, isLoading } = useAuthorize(permissions, parameters, queryOptions);
40
+
41
+ if (isLoading) {
42
+ if (loader) return loader === true ? <BlockUi blocking /> : <>{loader}</>;
43
+ return null;
44
+ }
45
+
46
+ // show children when authorized or negate is exclusively true
47
+ if ((authorized || negate) && !(authorized && negate)) {
48
+ return <>{children}</>;
49
+ }
50
+
51
+ return <>{unauthorized}</>;
52
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "include": ["."],
4
+ "exclude": ["dist", "build", "node_modules"]
5
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "types": ["jest", "node", "@testing-library/jest-dom"],
7
+ "allowJs": true
8
+ },
9
+ "include": ["**/*.test.js", "**/*.test.ts", "**/*.test.tsx", "**/*.d.ts"]
10
+ }