From dfc2d3979b922aefc71cc54ef5bb1bdb35ec2418 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:21:00 +0100 Subject: [PATCH 01/25] Update AccordionForm documentation --- docs/AccordionForm.md | 350 +++++++++++++++++++++++++++++++++++------- 1 file changed, 297 insertions(+), 53 deletions(-) diff --git a/docs/AccordionForm.md b/docs/AccordionForm.md index 82431935392..895ec642d16 100644 --- a/docs/AccordionForm.md +++ b/docs/AccordionForm.md @@ -84,10 +84,13 @@ Here are all the props you can set on the `` component: | Prop | Required | Type | Default | Description | | ------------------------- | -------- | ----------------- | ------- | ---------------------------------------------------------------------------- | +| `authorizationError` | Optional | `ReactNode` | `null` | The content to display when authorization checks fail | | `autoClose` | Optional | `boolean` | - | Set to `true` to close the current accordion when opening another one. | | `children` | Required | `ReactNode` | - | A list of `` elements. | | `defaultValues` | Optional | `object|function` | - | The default values of the record. | +| `enableAccessControl` | Optional | `boolean` | `false` | Enable checking authorization rights for each panel and input | | `id` | Optional | `string` | - | The id of the underlying `
` tag. | +| `loading` | Optional | `ReactNode` | | The content to display when checking authorizations | | `noValidate` | Optional | `boolean` | - | Set to `true` to disable the browser's default validation. | | `onSubmit` | Optional | `function` | `save` | A callback to call when the form is submitted. | | `sanitize EmptyValues` | Optional | `boolean` | - | Set to `true` to remove empty values from the form state. | @@ -98,6 +101,48 @@ Here are all the props you can set on the `` component: Additional props are passed to `react-hook-form`'s [`useForm` hook](https://react-hook-form.com/docs/useform). +## `authorizationError` + +Content displayed when `enableAccessControl` is set to `true` and an error occurs while checking for users permissions. Defaults to `null`: + +{% raw %} +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { AccordionForm } from '@react-admin/ra-form-layout'; +import { Alert } from '@mui/material'; + +const CustomerEdit = () => ( + + + An error occurred while loading your permissions + + } + > + + + + + + + + + + + + + + + +); +``` +{% endraw %} + ## `autoClose` When setting the `` prop, only one accordion remains open at a time. The first accordion is open by default, and when a user opens another one, the current open accordion closes. @@ -165,6 +210,47 @@ export const PostCreate = () => ( **Tip**: React-admin also allows to define default values at the input level. See the [Setting default Values](./Forms.md#default-values) section. +## `enableAccessControl` + +When set to `true`, React-admin will call the `authProvider.canAccess` method for each panel with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.panel.PANEL_ID_OR_LABEL`. For instance: `customers.panel.identity` +- `record`: The current record + +For each panel, react-admin will also call the `authProvider.canAccess` method for each input with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.INPUT_SOURCE`. For instance: `customers.first_name` +- `record`: The current record + +**Tip**: `` direct children that don't have a `source` will always be displayed. + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { AccordionForm } from '@react-admin/ra-form-layout'; + +const CustomerEdit = () => ( + + + + + + + + + + + + + + + + + +); +``` + +**Tip**: If you only want access control for the panels but not for the inputs, set the `enableAccessControl` prop to `false` on the ``. + ## `id` Normally, a submit button only works when placed inside a `` tag. However, you can place a submit button outside the form if the submit button `form` matches the form `id`. @@ -186,6 +272,43 @@ export const PostCreate = () => ( ); ``` +## `loading` + +Content displayed when `enableAccessControl` is set to `true` while checking for users permissions. Defaults to `Loading` from `react-admin`: + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { AccordionForm } from '@react-admin/ra-form-layout'; +import { Typography } from '@mui/material'; + +const CustomerEdit = () => ( + + + Loading your permissions... + + } + > + + + + + + + + + + + + + + + +); +``` + ## `noValidate` The `` attribute prevents the browser from validating the form. This is useful if you don't want to use the browser's default validation, or if you want to customize the error messages. To set this attribute on the underlying `` tag, set the `noValidate` prop to `true`. @@ -377,11 +500,14 @@ Here are all the props you can set on the `` component: | Prop | Required | Type | Default | Description | | ----------------- | -------- | ----------------------- | ------- | ------------------------------------------------------------------------------------------------ | +| `authorizationError` | Optional | `ReactNode` | `null` | The content to display when authorization checks fail | | `children` | Required | `ReactNode` | - | A list of `` elements | | `defaultExpanded` | Optional | `boolean` | `false` | Set to true to have the accordion expanded by default (except if autoClose = true on the parent) | | `disabled` | Optional | `boolean` | `false` | If true, the accordion will be displayed in a disabled state. | +| `enableAccessControl` | Optional | `boolean` | `false` | Enable checking authorization rights for this panel's inputs | | `id` | Optional | `string` | - | An id for this Accordion to be used in the [`useFormGroup`](./Upgrade.md#useformgroup-hook-returned-state-has-changed) hook and for CSS classes. | | `label` | Required | `string` or `ReactNode` | - | The main label used as the accordion summary. Appears in red when the accordion has errors | +| `loading` | Optional | `ReactNode` | | The content to display when checking authorizations | | `secondary` | Optional | `string` or `ReactNode` | - | The secondary label used as the accordion summary | | `square` | Optional | `boolean` | `false` | If true, rounded corners are disabled. | | `sx` | Optional | `Object` | - | An object containing the MUI style overrides to apply to the root component. | @@ -433,6 +559,8 @@ Here are all the props you can set on the `` component: | Prop | Required | Type | Default | Description | | ------------------ | -------- | ----------------------- | ------- | ------------------------------------------------------------- | +| `accessDenied` | Optional | `Component` | - | The component to use when users don't have the permissions required to access this section. | +| `authorizationError` | Optional | `Component` | - | The component to use when an error occurs while checking permissions. | | `Accordion` | Optional | `Component` | - | The component to use as the accordion. | | `AccordionDetails` | Optional | `Component` | - | The component to use as the accordion details. | | `AccordionSummary` | Optional | `Component` | - | The component to use as the accordion summary. | @@ -440,9 +568,11 @@ Here are all the props you can set on the `` component: | `className` | Optional | `string` | - | A class name to style the underlying `` | | `defaultExpanded` | Optional | `boolean` | `false` | Set to true to have the accordion expanded by default | | `disabled` | Optional | `boolean` | `false` | If true, the accordion will be displayed in a disabled state. | +| `enableAccessControl` | Optional | `boolean` | - | Enable access control to the section and its inputs | | `fullWidth` | Optional | `boolean` | `false` | If true, the Accordion takes the entire form width. | | `id` | Optional | `string` | - | An id for this Accordion to be used for CSS classes. | | `label` | Required | `string` or `ReactNode` | - | The main label used as the accordion summary. | +| `loading` | Optional | `Component` | - | The component to use while checking permissions. | | `secondary` | Optional | `string` or `ReactNode` | - | The secondary label used as the accordion summary | | `square` | Optional | `boolean` | `false` | If true, rounded corners are disabled. | @@ -491,6 +621,173 @@ const CustomerEdit = () => ( ); ``` +### `accessDenied` + +Content displayed when `enableAccessControl` is set to `true` and users don't have access to the section. Defaults to `null`: + +{% raw %} +```tsx +import { ReactNode } from 'react'; +import { ArrayInput, BooleanInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { AccordionSection } from '@react-admin/ra-form-layout'; +import { Alert } from '@mui/material'; + +const AccessDenied = ({ children }: { children: ReactNode }) => ( + + Upgrade to Premium + + } + > + {children} + +) + +const CustomerEdit = () => ( + + + + + You don't have access to the preferences section} + > + + + + + + +); +``` +{% endraw %} + + +### `authorizationError` + +Content displayed when `enableAccessControl` is set to `true` and an error occurs while checking for users permissions. Defaults to `null`: + +{% raw %} +```tsx +import { ArrayInput, BooleanInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { AccordionSection } from '@react-admin/ra-form-layout'; +import { Alert } from '@mui/material'; + +const AuthorizationError = () => ( + + An error occurred while loading your permissions + +); + +const CustomerEdit = () => ( + + + + + }> + + + + + + +); +``` +{% endraw %} + +### `enableAccessControl` + +When set to `true`, React-admin will call the `authProvider.canAccess` method the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.section.PANEL_ID_OR_LABEL`. For instance: `customers.section.identity` +- `record`: The current record + +React-admin will also call the `authProvider.canAccess` method for each input with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.INPUT_SOURCE`. For instance: `customers.first_name` +- `record`: The current record + +```tsx +import { ArrayInput, BooleanInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { AccordionSection } from '@react-admin/ra-form-layout'; + +const CustomerEdit = () => ( + + + + + + + + + + + + + + +); +``` + +**Tip**: `` direct children that don't have a `source` will always be displayed. + +### `loading` + +Content displayed when `enableAccessControl` is set to `true` while checking for users permissions. Defaults to `Loading` from `react-admin`: + +```tsx +import { ArrayInput, BooleanInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { AccordionSection } from '@react-admin/ra-form-layout'; +import { Typography } from '@mui/material'; + +const AuthorizationLoading = () => ( + + Loading your permissions... + +); + +const CustomerEdit = () => ( + + + + + + + + }> + + + + + + +); +``` + + ## AutoSave In forms where users may spend a lot of time, it's a good idea to save the form automatically after a few seconds of inactivity. You turn on this feature by using [the `` component](./AutoSave.md). @@ -532,56 +829,3 @@ Note that you **must** set the `` prop to `{ keepDir If you're using it in an `` page, you must also use a `pessimistic` or `optimistic` [`mutationMode`](https://marmelab.com/react-admin/Edit.html#mutationmode) - `` doesn't work with the default `mutationMode="undoable"`. Check [the `` component](./AutoSave.md) documentation for more details. - -## Role-Based Access Control (RBAC) - -Fine-grained permissions control can be added by using the [``](./AuthRBAC.md#accordionform), [``](./AuthRBAC.md#accordionform) and [``](./AuthRBAC.md#accordionsection) components provided by the `@react-admin/ra-enterprise` package. - -{% raw %} -```tsx -import { AccordionForm } from '@react-admin/ra-enterprise'; - -const authProvider = { - checkAuth: () => Promise.resolve(), - login: () => Promise.resolve(), - logout: () => Promise.resolve(), - checkError: () => Promise.resolve(), - getPermissions: () =>Promise.resolve([ - // 'delete' is missing - { action: ['list', 'edit'], resource: 'products' }, - { action: 'write', resource: 'products.reference' }, - { action: 'write', resource: 'products.width' }, - { action: 'write', resource: 'products.height' }, - // 'products.description' is missing - { action: 'write', resource: 'products.thumbnail' }, - // 'products.image' is missing - { action: 'write', resource: 'products.panel.description' }, - { action: 'write', resource: 'products.panel.images' }, - // 'products.panel.stock' is missing - ]), -}; - -const ProductEdit = () => ( - - - - - - - - - - - - - - - - { /* delete button not displayed */ } - - -); -``` -{% endraw %} - -Check [the RBAC `` component](./AuthRBAC.md#accordionform) documentation for more details. From 33ae7f588194be8bd5ee76123fde0c67d3ac3712 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:21:20 +0100 Subject: [PATCH 02/25] Update LongForm documentation --- docs/LongForm.md | 296 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 239 insertions(+), 57 deletions(-) diff --git a/docs/LongForm.md b/docs/LongForm.md index f1129a54f80..d3ca5da4515 100644 --- a/docs/LongForm.md +++ b/docs/LongForm.md @@ -88,9 +88,12 @@ Here are all the props you can set on the `` component: | Prop | Required | Type | Default | Description | | ------------------------ | -------- | ----------------- | ------- | ---------------------------------------------------------- | +| `authorizationError` | Optional | `ReactNode` | `null` | The content to display when authorization checks fail | | `children` | Required | `ReactNode` | - | A list of `` elements. | | `defaultValues` | Optional | `object|function` | - | The default values of the record. | +| `enableAccessControl` | Optional | `boolean` | `false` | Enable checking authorization rights for each section and input | | `id` | Optional | `string` | - | The id of the underlying `` tag. | +| `loading` | Optional | `ReactNode` | | The content to display when checking authorizations | | `noValidate` | Optional | `boolean` | - | Set to `true` to disable the browser's default validation. | | `onSubmit` | Optional | `function` | `save` | A callback to call when the form is submitted. | | `sanitizeEmptyValues` | Optional | `boolean` | - | Set to `true` to remove empty values from the form state. | @@ -102,6 +105,48 @@ Here are all the props you can set on the `` component: Additional props are passed to `react-hook-form`'s [`useForm` hook](https://react-hook-form.com/docs/useform). +## `authorizationError` + +Used when `enableAccessControl` is set to `true` and an error occurs while checking for users permissions. Defaults to `null`: + +{% raw %} +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { LongForm } from '@react-admin/ra-form-layout'; +import { Alert } from '@mui/material'; + +const CustomerEdit = () => ( + + + An error occurred while loading your permissions + + } + > + + + + + + + + + + + + + + + +); +``` +{% endraw %} + ## `children` The children of `` must be [`` elements](#longformsection). @@ -149,6 +194,45 @@ export const PostCreate = () => ( **Tip**: React-admin also allows to define default values at the input level. See the [Setting default Values](./Forms.md#default-values) section. +## `enableAccessControl` + +When set to `true`, React-admin will call the `authProvider.canAccess` method for each section with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.section.SECTION_ID_OR_LABEL`. For instance: `customers.section.identity` +- `record`: The current record + +For each section, react-admin will also call the `authProvider.canAccess` method for each input with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.INPUT_SOURCE`. For instance: `customers.first_name` +- `record`: The current record + +**Tip**: `` direct children that don't have a `source` will always be displayed. + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { LongForm } from '@react-admin/ra-form-layout'; + +const CustomerEdit = () => ( + + + + + + + + + + + + + + + + + +); +``` + ## `id` Normally, a submit button only works when placed inside a `` tag. However, you can place a submit button outside the form if the submit button `form` matches the form `id`. @@ -170,6 +254,43 @@ export const PostCreate = () => ( ); ``` +## `loading` + +Used when `enableAccessControl` is set to `true` while checking for users permissions. Defaults to `Loading` from `react-admin`: + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { LongForm } from '@react-admin/ra-form-layout'; +import { Typography } from '@mui/material'; + +const CustomerEdit = () => ( + + + Loading your permissions... + + } + > + + + + + + + + + + + + + + + +); +``` + ## `noValidate` The `` attribute prevents the browser from validating the form. This is useful if you don't want to use the browser's default validation, or if you want to customize the error messages. To set this attribute on the underlying `` tag, set the `noValidate` prop to `true`. @@ -363,10 +484,52 @@ It accepts the following props: | Prop | Required | Type | Default | Description | | ----------------- | -------- | ----------- | ------- | ------------------------------------------------------------------------------------ | -| `label` | Required | `string` | - | The main label used as the section title. Appears in red when the section has errors | -| `children` | Required | `ReactNode` | - | A list of `` elements | -| `cardinality` | Optional | `number` | - | A number to be displayed next to the label in TOC, to quantify it | -| `sx` | Optional | `object` | - | An object containing the Material UI style overrides to apply to the root component | +| `authorizationError` | Optional | `ReactNode` | - | The content to display when authorization checks fail | +| `cardinality` | Optional | `number` | - | A number to be displayed next to the label in TOC, to quantify it | +| `children` | Required | `ReactNode` | - | A list of `` elements | +| `enableAccessControl` | Optional | `ReactNode` | - | Enable authorization checks | +| `label` | Required | `string` | - | The main label used as the section title. Appears in red when the section has errors | +| `loading` | Optional | `ReactNode` | - | The content to display while checking authorizations | +| `sx` | Optional | `object` | - | An object containing the Material UI style overrides to apply to the root component | + +#### `authorizationError` + +Used when `enableAccessControl` is set to `true` and an error occurs while checking for users permissions. Defaults to `null`: + +{% raw %} +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { LongForm } from '@react-admin/ra-form-layout'; +import { Alert } from '@mui/material'; + +const CustomerEdit = () => ( + + + + + + + + An error occurred while loading your permissions + + }> + + + + + + + + + + +); +``` +{% endraw %} ### `cardinality` @@ -428,6 +591,78 @@ const CustomerEditWithCardinality = () => { }; ``` +### `enableAccessControl` + +When set to `true`, react-admin will also call the `authProvider.canAccess` method for each input with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.INPUT_SOURCE`. For instance: `customers.first_name` +- `record`: The current record + +**Tip**: `` direct children that don't have a `source` will always be displayed. + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { LongForm } from '@react-admin/ra-form-layout'; + +const CustomerEdit = () => ( + + + + + + + + + + + + + + + + + +); +``` + +### `loading` + +Used when `enableAccessControl` is set to `true` while checking for users permissions. Defaults to `Loading` from `react-admin`: + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { LongForm } from '@react-admin/ra-form-layout'; +import { Typography } from '@mui/material'; + +const CustomerEdit = () => ( + + + + Loading your permissions... + + }> + + + + + Loading your permissions... + + }> + + + + + + + + + + +); +``` + ## AutoSave In forms where users may spend a lot of time, it's a good idea to save the form automatically after a few seconds of inactivity. You turn on this feature by using [the `` component](./AutoSave.md). @@ -469,56 +704,3 @@ Note that you **must** set the `` prop to `{ keepDirtyVal If you're using it in an `` page, you must also use a `pessimistic` or `optimistic` [`mutationMode`](https://marmelab.com/react-admin/Edit.html#mutationmode) - `` doesn't work with the default `mutationMode="undoable"`. Check [the `` component](./AutoSave.md) documentation for more details. - -## Role-Based Access Control (RBAC) - -Fine-grained permissions control can be added by using the [``](./AuthRBAC.md#longform) and [``](./AuthRBAC.md#longform) components provided by the `@react-admin/ra-enterprise` package. - -{% raw %} -```tsx -import { LongForm } from '@react-admin/ra-enterprise'; - -const authProvider = { - checkAuth: () => Promise.resolve(), - login: () => Promise.resolve(), - logout: () => Promise.resolve(), - checkError: () => Promise.resolve(), - getPermissions: () =>Promise.resolve([ - // 'delete' is missing - { action: ['list', 'edit'], resource: 'products' }, - { action: 'write', resource: 'products.reference' }, - { action: 'write', resource: 'products.width' }, - { action: 'write', resource: 'products.height' }, - // 'products.description' is missing - { action: 'write', resource: 'products.thumbnail' }, - // 'products.image' is missing - { action: 'write', resource: 'products.Section.description' }, - { action: 'write', resource: 'products.Section.images' }, - // 'products.Section.stock' is missing - ]), -}; - -const ProductEdit = () => ( - - - - - - - - - - - - - - - - // delete button not displayed - - -); -``` -{% endraw %} - -Check [the RBAC ``](./AuthRBAC.md#longform) documentation for more details. From af9672aedbd9a0f08b4c9c1ecaf42e3792464806 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:32:27 +0100 Subject: [PATCH 03/25] Update WizardForm documentation --- docs/WizardForm.md | 303 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 248 insertions(+), 55 deletions(-) diff --git a/docs/WizardForm.md b/docs/WizardForm.md index fe155440403..9e9885d7170 100644 --- a/docs/WizardForm.md +++ b/docs/WizardForm.md @@ -49,9 +49,12 @@ The `` component accepts the following props: | Prop | Required | Type | Default | Description | | ------------------------ | -------- | ----------------- | ------- | ---------------------------------------------------------- | +| `authorizationError` | Optional | `ReactNode` | `null` | The content to display when authorization checks fail | | `children` | Required | `ReactNode` | - | A list of `` elements. | | `defaultValues` | Optional | `object|function` | - | The default values of the record. | +| `enableAccessControl` | Optional | `boolean` | `false` | Enable checking authorization rights for each panel and input | | `id` | Optional | `string` | - | The id of the underlying `` tag. | +| `loading` | Optional | `ReactNode` | | The content to display when checking authorizations | | `noValidate` | Optional | `boolean` | - | Set to `true` to disable the browser's default validation. | | `onSubmit` | Optional | `function` | `save` | A callback to call when the form is submitted. | | `progress` | Optional | `ReactElement` | - | A custom progress stepper element. | @@ -63,6 +66,49 @@ The `` component accepts the following props: Additional props are passed to `react-hook-form`'s [`useForm` hook](https://react-hook-form.com/docs/useform). +## `authorizationError` + +Used when `enableAccessControl` is set to `true` and an error occurs while checking for users permissions. Defaults to `null`: + + +{% raw %} +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { WizardForm } from '@react-admin/ra-form-layout'; +import { Alert } from '@mui/material'; + +const CustomerEdit = () => ( + + + An error occurred while loading your permissions + + } + > + + + + + + + + + + + + + + + +); +``` +{% endraw %} + ## `children` The children of `` must be `` elements. @@ -110,6 +156,45 @@ export const PostCreate = () => ( **Tip**: React-admin also allows to define default values at the input level. See the [Setting default Values](./forms.md#default-values) section. +## `enableAccessControl` + +When set to `true`, React-admin will call the `authProvider.canAccess` method for each panel with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.section.PANEL_ID_OR_LABEL`. For instance: `customers.section.identity` +- `record`: The current record + +For each panel, react-admin will also call the `authProvider.canAccess` method for each input with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.INPUT_SOURCE`. For instance: `customers.first_name` +- `record`: The current record + +**Tip**: `` direct children that don't have a `source` will always be displayed. + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { WizardForm } from '@react-admin/ra-form-layout'; + +const CustomerEdit = () => ( + + + + + + + + + + + + + + + + + +); +``` + ## `id` Normally, a submit button only works when placed inside a `` tag. However, you can place a submit button outside the form if the submit button `form` matches the form `id`. @@ -131,6 +216,43 @@ export const PostCreate = () => ( ); ``` +## `loading` + +Used when `enableAccessControl` is set to `true` while checking for users permissions. Defaults to `Loading` from `react-admin`: + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { WizardForm } from '@react-admin/ra-form-layout'; +import { Typography } from '@mui/material'; + +const CustomerEdit = () => ( + + + Loading your permissions... + + } + > + + + + + + + + + + + + + + + +); +``` + ## `noValidate` The `` attribute prevents the browser from validating the form. This is useful if you don't want to use the browser's default validation, or if you want to customize the error messages. To set this attribute on the underlying `` tag, set the `noValidate` prop to `true`. @@ -433,6 +555,132 @@ const PostCreate = () => ( ); ``` +The children of `` must be `` elements. + +### Props + + +| Prop | Required | Type | Default | Description | +| --------------------- | -------- | ----------- | ------- | ------------------------------------------------------------------------------------ | +| `authorizationError` | Optional | `ReactNode` | - | The content to display when authorization checks fail | +| `enableAccessControl` | Optional | `ReactNode` | - | Enable authorization checks | +| `label` | Required | `string` | - | The main label used as the step title. Appears in red when the section has errors | +| `loading` | Optional | `ReactNode` | - | The content to display while checking authorizations | +| `children` | Required | `ReactNode` | - | A list of `` elements | +| `sx` | Optional | `object` | - | An object containing the MUI style overrides to apply to the root component | + +### `authorizationError` + +Used when `enableAccessControl` is set to `true` and an error occurs while checking for users permissions. Defaults to `null`: + +{% raw %} +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { WizardForm } from '@react-admin/ra-form-layout'; +import { Alert } from '@mui/material'; + +const CustomerEdit = () => ( + + + + + + + + An error occurred while loading your permissions + + }> + + + + + + + + + + +); +``` +{% endraw %} + + +### `enableAccessControl` + +When set to `true`, react-admin will also call the `authProvider.canAccess` method for each input with the following parameters: +- `action`: `write` +- `resource`: `RESOURCE_NAME.INPUT_SOURCE`. For instance: `customers.first_name` +- `record`: The current record + +**Tip**: `` direct children that don't have a `source` will always be displayed. + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { WizardForm } from '@react-admin/ra-form-layout'; + +const CustomerEdit = () => ( + + + + + + + + + + + + + + + + + +); +``` + +### `loading` + +Used when `enableAccessControl` is set to `true` while checking for users permissions. Defaults to `Loading` from `react-admin`: + +```tsx +import { ArrayInput, Edit, DateInput, SimpleFormIterator, TextInput } from 'react-admin'; +import { WizardForm } from '@react-admin/ra-form-layout'; +import { Typography } from '@mui/material'; + +const CustomerEdit = () => ( + + + + Loading your permissions... + + }> + + + + + Loading your permissions... + + }> + + + + + + + + + + +); +``` + ## Adding a Summary Final Step In order to add a final step with a summary of the form values before submit, you can leverage `react-hook-form` [`useWatch`](https://react-hook-form.com/docs/usewatch) hook: @@ -471,58 +719,3 @@ const PostCreate = () => ( ); ``` - -## Role-Based Access Control (RBAC) - -Fine-grained permissions control can be added by using the [``](./AuthRBAC.md#wizardform) and [``](./AuthRBAC.md#wizardform) components provided by the `@react-admin/ra-enterprise` package. - -{% raw %} -```tsx -import { WizardForm } from '@react-admin/ra-enterprise'; - -const authProvider = { - checkAuth: () => Promise.resolve(), - login: () => Promise.resolve(), - logout: () => Promise.resolve(), - checkError: () => Promise.resolve(), - getPermissions: () =>Promise.resolve([ - // 'delete' is missing - { action: ['list', 'edit'], resource: 'products' }, - { action: 'write', resource: 'products.reference' }, - { action: 'write', resource: 'products.width' }, - { action: 'write', resource: 'products.height' }, - // 'products.description' is missing - { action: 'write', resource: 'products.thumbnail' }, - // 'products.image' is missing - { action: 'write', resource: 'products.step.description' }, - { action: 'write', resource: 'products.step.images' }, - // 'products.step.stock' is missing - ]), -}; - -const ProductCreate = () => ( - - - - - - - {/* Won't be displayed */} - - - - {/* Won't be displayed */} - - - - {/* Won't be displayed */} - - - - - -); -``` -{% endraw %} - -Check [the RBAC ``](./AuthRBAC.md#wizardform) documentation for more details. From cbf50e9c9a72d00ef1f4fccd10193daa0b7bcdc5 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:04:17 +0100 Subject: [PATCH 04/25] Update OSS forms documentation --- docs/SimpleForm.md | 67 ++++++++--------------- docs/TabbedForm.md | 132 ++++++++++++++++++++++++++------------------- 2 files changed, 100 insertions(+), 99 deletions(-) diff --git a/docs/SimpleForm.md b/docs/SimpleForm.md index 5f6b1a26fe4..a03521007d7 100644 --- a/docs/SimpleForm.md +++ b/docs/SimpleForm.md @@ -514,6 +514,28 @@ const formState = useFormState(); // ❌ should deconstruct the formState ## Displaying Inputs Based On Permissions +You can leverage [the `` component](./CanAccess.md) to display inputs if the user has the required access rights. + +{% raw %} +```jsx +import { CanAccess, Create, SimpleForm, TextInput } from 'react-admin'; + +export const UserCreate = () => { + const { permissions } = useGetPermissions(); + return ( + + + + + + + + + ); +} +``` +{% endraw %} + You can leverage [the `usePermissions` hook](./usePermissions.md) to display inputs if the user has the required permissions. {% raw %} @@ -647,51 +669,6 @@ If you're using it in an `` page, you must also use a `pessimistic` or `op Check [the `` component](./AutoSave.md) documentation for more details. -## Role-Based Access Control (RBAC) - -Fine-grained permissions control can be added by using the [``](./AuthRBAC.md#simpleform) component provided by the `@react-admin/ra-rbac` package. - -{% raw %} -```jsx -import { Edit, TextInput } from 'react-admin'; -import { SimpleForm } from '@react-admin/ra-rbac'; - -const authProvider= { - // ... - getPermissions: () => Promise.resolve({ - permissions: [ - // 'delete' is missing - { action: ['list', 'edit'], resource: 'products' }, - { action: 'write', resource: 'products.reference' }, - { action: 'write', resource: 'products.width' }, - { action: 'write', resource: 'products.height' }, - // 'products.description' is missing - { action: 'write', resource: 'products.thumbnail' }, - // 'products.image' is missing - ] - }), -}; - -const ProductEdit = () => ( - - - - - - {/* not displayed */} - - {/* not displayed */} - - - {/* no delete button */} - - -); -``` -{% endraw %} - -Check [the RBAC `` component](./AuthRBAC.md#simpleform) documentation for more details. - ## Versioning By default, `` updates the current record (via `dataProvider.update()`), so the previous version of the record is lost. If you want to keep the previous version, you can use the [``](https://react-admin-ee.marmelab.com/documentation/ra-history#simpleformwithrevision) component instead: diff --git a/docs/TabbedForm.md b/docs/TabbedForm.md index 45a0443c501..6b5bd8a683b 100644 --- a/docs/TabbedForm.md +++ b/docs/TabbedForm.md @@ -796,21 +796,34 @@ Check [the `` component](./AutoSave.md) documentation for more details ## Displaying a Tab Based On Permissions -You can leverage [the `usePermissions` hook](./usePermissions.md) to display a tab only if the user has the required permissions. +You can leverage [the `useCanAccess` hook](./useCanAccess.md) to display tabs if the user has the required access rights. {% raw %} ```jsx -import { usePermissions, Edit, TabbedForm, FormTab } from 'react-admin'; +import { Edit, FormTab, Loading, TabbedForm, TextInput, useCanAccess } from 'react-admin'; +import { Alert } from '@mui/material'; + +export const UserCreate = () => { + const { canAccess, isPending, error } = useCanAccess({ + resource: 'users.tabs.security', + action: 'write', + }); + if (isPending) return ; + if (error) { + return ( + + An error occurred while checking your permissions + + ); + } -const UserEdit = () => { - const { permissions } = usePermissions(); return ( - + ... - {permissions === 'admin' && + {canAccess && ... @@ -818,65 +831,76 @@ const UserEdit = () => { ); -}; +} ``` {% endraw %} -## Role-Based Access Control (RBAC) +If you need to check access rights for multiple tabs, leverage [the `useCanAccessResources` hook](./useCanAccess.md#multiple-resources). -You can show or hide tabs and inputs based on user permissions by using the [``](./AuthRBAC.md#tabbedform) component from the `@react-admin/ra-rbac` package instead of the `react-admin` package. +{% raw %} +```jsx +import { Edit, FormTab, Loading, TabbedForm, TextInput, useCanAccessResources } from 'react-admin'; +import { Alert } from '@mui/material'; + +export const UserCreate = () => { + const { canAccess, isPending, error } = useCanAccessResources({ + resources: ['users.tabs.summary', 'users.tabs.security'], + action: 'write', + }); + if (isPending) return ; + if (error) { + return ( + + An error occurred while checking your permissions + + ); + } + + return ( + + + {canAccess['users.tabs.summary'] && + + ... + } + {canAccess['users.tabs.security'] && + + ... + + } + + + ); +} +``` +{% endraw %} -[``](./AuthRBAC.md#tabbedform) shows only the tabs for which users have write permissions, using the `[resource].tab.[tabName]` string as resource identifier. It also renders the delete button only if the user has a permission for the `delete` action in the current resource. `` shows only the child inputs for which users have the write permissions, using the `[resource].[source]` string as resource identifier. +You can leverage [the `usePermissions` hook](./usePermissions.md) to display a tab only if the user has the required permissions. {% raw %} -```tsx -import { Edit, TextInput } from 'react-admin'; -import { TabbedForm } from '@react-admin/ra-rbac'; - -const authProvider = { - // ... - getPermissions: () => Promise.resolve([ - // crud (the delete action is missing) - { action: ['list', 'edit'], resource: 'products' }, - // tabs ('products.tab.stock' is missing) - { action: 'write', resource: 'products.tab.description' }, - { action: 'write', resource: 'products.tab.images' }, - // fields ('products.description' and 'products.image' are missing) - { action: 'write', resource: 'products.reference' }, - { action: 'write', resource: 'products.width' }, - { action: 'write', resource: 'products.height' }, - { action: 'write', resource: 'products.thumbnail' }, - ]), -}; +```jsx +import { usePermissions, Edit, TabbedForm, FormTab } from 'react-admin'; -const ProductEdit = () => ( - - - - - - - {/* the description input is not displayed */} - - - {/* the stock tab is not displayed */} - - - - - {/* the images input is not displayed */} - - - - {/* the delete button is not displayed */} - - -); +const UserEdit = () => { + const { permissions } = usePermissions(); + return ( + + + + ... + + {permissions === 'admin' && + + ... + + } + + + ); +}; ``` {% endraw %} -Check [the RBAC `` component](./AuthRBAC.md#tabbedform) documentation for more details. - ## Versioning By default, `` updates the current record (via `dataProvider.update()`), so the previous version of the record is lost. If you want to keep track of the previous versions of the record, you can use the [``](https://react-admin-ee.marmelab.com/documentation/ra-history#tabbedformwithrevision) component instead. From 195d26fcb950c1d018c9b04c29ffbc155412a449 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:15:25 +0100 Subject: [PATCH 05/25] Update TabbedShowLayout documentation --- docs/TabbedShowLayout.md | 55 ---------------------------------------- 1 file changed, 55 deletions(-) diff --git a/docs/TabbedShowLayout.md b/docs/TabbedShowLayout.md index 211f732c8fa..81f7f90d31d 100644 --- a/docs/TabbedShowLayout.md +++ b/docs/TabbedShowLayout.md @@ -345,61 +345,6 @@ const StaticPostShow = () => ( When passed a `record`, `` creates a `RecordContext` with the given record. -## Role-Based Access Control (RBAC) - -You can show or hide tabs and inputs based on user permissions by using the [``](./AuthRBAC.md#tabbedshowlayout) component from the `@react-admin/ra-rbac` package instead of the `react-admin` package. - -[``](./AuthRBAC.md#tabbedshowlayout) shows only the tabs for which users have read permissions, using the `[resource].tab.[tabName]` string as resource identifier. `` shows only the child fields for which users have the read permissions, using the `[resource].[source]` string as resource identifier. - -{% raw %} -```tsx -import { Show, TextField } from 'react-admin'; -import { TabbedShowLayout } from '@react-admin/ra-rbac'; - -const authProvider = { - // ... - getPermissions: () => Promise.resolve([ - // crud - { action: ['list', 'show'], resource: 'products' }, - // tabs ('products.tab.stock' is missing) - { action: 'read', resource: 'products.tab.description' }, - { action: 'read', resource: 'products.tab.images' }, - // fields ('products.description' and 'products.image' are missing) - { action: 'read', resource: 'products.reference' }, - { action: 'read', resource: 'products.width' }, - { action: 'read', resource: 'products.height' }, - { action: 'read', resource: 'products.thumbnail' }, - ]), -}; - -const ProductShow = () => ( - - - - - - - {/* the description field is not displayed */} - - - {/* the stock tab is not displayed */} - - - - - {/* the images field is not displayed */} - - - - - -); -``` -{% endraw %} - -Check [the RBAC `` component](./AuthRBAC.md#tabbedshowlayout) documentation for more details. - - ## See Also * [Field components](./Fields.md) From 8560ea5f804462487a9d81962546d88cfd88ae3a Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:23:35 +0100 Subject: [PATCH 06/25] Improve OSS forms documentation --- docs/SimpleForm.md | 7 +++--- docs/TabbedForm.md | 62 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/docs/SimpleForm.md b/docs/SimpleForm.md index a03521007d7..b12267d70f7 100644 --- a/docs/SimpleForm.md +++ b/docs/SimpleForm.md @@ -521,7 +521,6 @@ You can leverage [the `` component](./CanAccess.md) to display inputs import { CanAccess, Create, SimpleForm, TextInput } from 'react-admin'; export const UserCreate = () => { - const { permissions } = useGetPermissions(); return ( @@ -548,8 +547,10 @@ export const UserCreate = () => { - {permissions === 'admin' && - } + {permissions === 'admin' + ? + : null + } ); diff --git a/docs/TabbedForm.md b/docs/TabbedForm.md index 6b5bd8a683b..85d538c5d21 100644 --- a/docs/TabbedForm.md +++ b/docs/TabbedForm.md @@ -839,10 +839,10 @@ If you need to check access rights for multiple tabs, leverage [the `useCanAcces {% raw %} ```jsx -import { Edit, FormTab, Loading, TabbedForm, TextInput, useCanAccessResources } from 'react-admin'; +import { Edit, Loading, TabbedForm, TextInput, useCanAccessResources } from 'react-admin'; import { Alert } from '@mui/material'; -export const UserCreate = () => { +export const UserEdit = () => { const { canAccess, isPending, error } = useCanAccessResources({ resources: ['users.tabs.summary', 'users.tabs.security'], action: 'write', @@ -879,7 +879,7 @@ You can leverage [the `usePermissions` hook](./usePermissions.md) to display a t {% raw %} ```jsx -import { usePermissions, Edit, TabbedForm, FormTab } from 'react-admin'; +import { usePermissions, Edit, TabbedForm } from 'react-admin'; const UserEdit = () => { const { permissions } = usePermissions(); @@ -901,6 +901,62 @@ const UserEdit = () => { ``` {% endraw %} +## Displaying Inputs Based On Permissions + +You can leverage [the `` component](./CanAccess.md) to display inputs if the user has the required access rights. + +{% raw %} +```jsx +import { CanAccess, Edit, TabbedForm, TextInput } from 'react-admin'; + +export const UserEdit = () => { + return ( + + + + + + + + } + + ... + + + + ); +} +``` +{% endraw %} + +You can leverage [the `usePermissions` hook](./usePermissions.md) to display inputs if the user has the required permissions. + +{% raw %} +```jsx +import { usePermissions, Edit, TabbedForm, TextInput } from 'react-admin'; + +export const UserEdit = () => { + const { permissions } = useGetPermissions(); + return ( + + + + + {permissions === 'admin' + ? + : null + } + } + + ... + + + + ); +} +``` +{% endraw %} + ## Versioning By default, `` updates the current record (via `dataProvider.update()`), so the previous version of the record is lost. If you want to keep track of the previous versions of the record, you can use the [``](https://react-admin-ee.marmelab.com/documentation/ra-history#tabbedformwithrevision) component instead. From 247c03defdbeede3184387281ebbef0d81b4606b Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:21:02 +0100 Subject: [PATCH 07/25] Remove mentions of useGetPermissions --- docs/SimpleForm.md | 23 -------------------- docs/TabbedForm.md | 54 ---------------------------------------------- 2 files changed, 77 deletions(-) diff --git a/docs/SimpleForm.md b/docs/SimpleForm.md index b12267d70f7..812b938802d 100644 --- a/docs/SimpleForm.md +++ b/docs/SimpleForm.md @@ -535,29 +535,6 @@ export const UserCreate = () => { ``` {% endraw %} -You can leverage [the `usePermissions` hook](./usePermissions.md) to display inputs if the user has the required permissions. - -{% raw %} -```jsx -import { usePermissions, Create, SimpleForm, TextInput } from 'react-admin'; - -export const UserCreate = () => { - const { permissions } = useGetPermissions(); - return ( - - - - {permissions === 'admin' - ? - : null - } - - - ); -} -``` -{% endraw %} - ## Configurable You can let end users customize the fields displayed in the `` by using the `` component instead. diff --git a/docs/TabbedForm.md b/docs/TabbedForm.md index 85d538c5d21..7923187c52c 100644 --- a/docs/TabbedForm.md +++ b/docs/TabbedForm.md @@ -875,32 +875,6 @@ export const UserEdit = () => { ``` {% endraw %} -You can leverage [the `usePermissions` hook](./usePermissions.md) to display a tab only if the user has the required permissions. - -{% raw %} -```jsx -import { usePermissions, Edit, TabbedForm } from 'react-admin'; - -const UserEdit = () => { - const { permissions } = usePermissions(); - return ( - - - - ... - - {permissions === 'admin' && - - ... - - } - - - ); -}; -``` -{% endraw %} - ## Displaying Inputs Based On Permissions You can leverage [the `` component](./CanAccess.md) to display inputs if the user has the required access rights. @@ -929,34 +903,6 @@ export const UserEdit = () => { ``` {% endraw %} -You can leverage [the `usePermissions` hook](./usePermissions.md) to display inputs if the user has the required permissions. - -{% raw %} -```jsx -import { usePermissions, Edit, TabbedForm, TextInput } from 'react-admin'; - -export const UserEdit = () => { - const { permissions } = useGetPermissions(); - return ( - - - - - {permissions === 'admin' - ? - : null - } - } - - ... - - - - ); -} -``` -{% endraw %} - ## Versioning By default, `` updates the current record (via `dataProvider.update()`), so the previous version of the record is lost. If you want to keep track of the previous versions of the record, you can use the [``](https://react-admin-ee.marmelab.com/documentation/ra-history#tabbedformwithrevision) component instead. From 7183b492b76e15615e9c1cc88d9a9082d4bbfb70 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:55:24 +0100 Subject: [PATCH 08/25] Revert TabbedShowLayout changes --- docs/TabbedShowLayout.md | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/docs/TabbedShowLayout.md b/docs/TabbedShowLayout.md index 81f7f90d31d..8a0b24c9698 100644 --- a/docs/TabbedShowLayout.md +++ b/docs/TabbedShowLayout.md @@ -345,6 +345,60 @@ const StaticPostShow = () => ( When passed a `record`, `` creates a `RecordContext` with the given record. +## Role-Based Access Control (RBAC) + +You can show or hide tabs and inputs based on user permissions by using the [``](./AuthRBAC.md#tabbedshowlayout) component from the `@react-admin/ra-rbac` package instead of the `react-admin` package. + +[``](./AuthRBAC.md#tabbedshowlayout) shows only the tabs for which users have read permissions, using the `[resource].tab.[tabName]` string as resource identifier. `` shows only the child fields for which users have the read permissions, using the `[resource].[source]` string as resource identifier. + +{% raw %} +```tsx +import { Show, TextField } from 'react-admin'; +import { TabbedShowLayout } from '@react-admin/ra-rbac'; + +const authProvider = { + // ... + getPermissions: () => Promise.resolve([ + // crud + { action: ['list', 'show'], resource: 'products' }, + // tabs ('products.tab.stock' is missing) + { action: 'read', resource: 'products.tab.description' }, + { action: 'read', resource: 'products.tab.images' }, + // fields ('products.description' and 'products.image' are missing) + { action: 'read', resource: 'products.reference' }, + { action: 'read', resource: 'products.width' }, + { action: 'read', resource: 'products.height' }, + { action: 'read', resource: 'products.thumbnail' }, + ]), +}; + +const ProductShow = () => ( + + + + + + + {/* the description field is not displayed */} + + + {/* the stock tab is not displayed */} + + + + + {/* the images field is not displayed */} + + + + + +); +``` +{% endraw %} + +Check [the RBAC `` component](./AuthRBAC.md#tabbedshowlayout) documentation for more details. + ## See Also * [Field components](./Fields.md) From 8fc91f68ca340458705641c287e61ee7ff9ddacc Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:55:34 +0100 Subject: [PATCH 09/25] Improve SimpleShowLayout [no ci] --- docs/SimpleShowLayout.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/SimpleShowLayout.md b/docs/SimpleShowLayout.md index 7ff14f68f11..faee080d811 100644 --- a/docs/SimpleShowLayout.md +++ b/docs/SimpleShowLayout.md @@ -261,6 +261,45 @@ const PostShow = () => ( ); ``` +## Role-Based Access Control (RBAC) + +You can show or hide tabs and inputs based on user permissions by using the [``](./AuthRBAC.md#tabbedshowlayout) component from the `@react-admin/ra-rbac` package instead of the `react-admin` package. + +[``](./AuthRBAC.md#tabbedshowlayout) shows only the tabs for which users have read permissions, using the `[resource].tab.[tabName]` string as resource identifier. `` shows only the child fields for which users have the read permissions, using the `[resource].[source]` string as resource identifier. + +{% raw %} +```tsx +import { Show, TextField } from 'react-admin'; +import { SimpleShowLayout } from '@react-admin/ra-rbac'; + +const authProvider = { + // ... + getPermissions: () => Promise.resolve([ + // crud + { action: ['list', 'show'], resource: 'products' }, + // fields ('products.description' is missing) + { action: 'read', resource: 'products.reference' }, + { action: 'read', resource: 'products.width' }, + { action: 'read', resource: 'products.height' }, + ]), +}; + +const ProductShow = () => ( + + + + + + {/* the description field is not displayed */} + + + +); +``` +{% endraw %} + +Check [the RBAC `` component](./AuthRBAC.md#simpleshowlayout) documentation for more details. + ## See Also * [Field components](./Fields.md) From 9fe472ce37b3b1419112fc387666fd7682d10a7e Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:10:38 +0100 Subject: [PATCH 10/25] Document Menu Access Control [no ci] --- docs/Menu.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/Menu.md b/docs/Menu.md index 4b51cd09472..2273ed232d6 100644 --- a/docs/Menu.md +++ b/docs/Menu.md @@ -465,3 +465,33 @@ const MyReactAdmin = () => ( ``` ![MenuLive](./img/MenuLive.png) + +## Displaying Menu Items Based On Permissions + +If you `authProvider` implements [the `canAccess` method](./Permissions.md#authprovidercanaccess), the `` component will call it for each resource with the follwing parameters: +- `resource`: the resource name +- `action`: `list` + +However, if you have a custom menu and want to show items based on the user permissions, you can leverage [the `` component](./CanAccess.md): + +{% raw %} +```tsx +// in src/MyMenu.js +import { CanAccess, Menu } from 'react-admin'; +import LabelIcon from '@mui/icons-material/Label'; + +export const MyMenu = () => ( + + + + + + + } /> + + +); +``` +{% endraw %} + +**Tip**: the `resource` and `action` parameter accept any string value. From c76da1c5baa253e1f529755df5ff284858f84a57 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:29:36 +0100 Subject: [PATCH 11/25] Document CloneButton and ExportButton [no ci] --- docs/Buttons.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/docs/Buttons.md b/docs/Buttons.md index d8777e7ce33..1b8095878fb 100644 --- a/docs/Buttons.md +++ b/docs/Buttons.md @@ -568,6 +568,58 @@ To override the style of all instances of `