Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
dfc2d39
Update AccordionForm documentation
djhi Dec 11, 2024
33ae7f5
Update LongForm documentation
djhi Dec 11, 2024
af9672a
Update WizardForm documentation
djhi Dec 11, 2024
cbf50e9
Update OSS forms documentation
djhi Dec 11, 2024
195d26f
Update TabbedShowLayout documentation
djhi Dec 11, 2024
8560ea5
Improve OSS forms documentation
djhi Dec 11, 2024
247c03d
Remove mentions of useGetPermissions
djhi Dec 11, 2024
7183b49
Revert TabbedShowLayout changes
djhi Dec 11, 2024
8fc91f6
Improve SimpleShowLayout [no ci]
djhi Dec 11, 2024
9fe472c
Document Menu Access Control [no ci]
djhi Dec 11, 2024
c76da1c
Document CloneButton and ExportButton [no ci]
djhi Dec 11, 2024
bbd922c
Update Datagrid documentation [no ci]
djhi Dec 11, 2024
a551e35
Update RBAC documentation [no ci]
djhi Dec 11, 2024
809641a
Apply suggestions from code review
djhi Dec 12, 2024
4308f7c
Improve introduction
fzaninotto Dec 12, 2024
40b374d
Document Datagrid access control in Datagrid doc
fzaninotto Dec 12, 2024
a98cd5a
Move the List RBAC features to the List doc
fzaninotto Dec 12, 2024
c2b7550
Move SimpleShowLayout RBAC doc to SimpleShowLayout chapter
fzaninotto Dec 12, 2024
5a33cfd
Move Simpleform RBAC doc to SimpleForm chapter
fzaninotto Dec 12, 2024
ff42f32
Move Menu RBAC doc to the Menu chapter
fzaninotto Dec 12, 2024
30ff4d3
Move TabbedShowLayout RBAC doc to TabbedshowLayout chapter
fzaninotto Dec 12, 2024
3011173
Move TabbedForm RBAC doc to TabbedForm chapter
fzaninotto Dec 12, 2024
7f60ef3
Move RBAC buttons doc to the Buttons chapter
fzaninotto Dec 12, 2024
0c71fe8
Add mention of built-in access control
fzaninotto Dec 12, 2024
1a96836
MAke access control section position consistent
fzaninotto Dec 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
371 changes: 329 additions & 42 deletions docs/AccordionForm.md

Large diffs are not rendered by default.

1,069 changes: 245 additions & 824 deletions docs/AuthRBAC.md

Large diffs are not rendered by default.

126 changes: 126 additions & 0 deletions docs/Buttons.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,80 @@ To override the style of all instances of `<Button>` using the [application-wide

## `<CloneButton>`

The `<CloneButton>` can be added anywhere there is a `RecordContext` to redirect users to the record's resource create page. The create page form will be prefilled with the record values (except the `id`).

### Usage

`<CloneButton>` reads the current resource from `ResourceContext`, so in general it doesn't need any props:

```jsx
import { CloneButton, TopToolbar, List } from 'react-admin';

const PostList = () => (
<List>
<TextField source="title" />
<CloneButton />
</List>
);
```

`<CloneButton>` is based on react-admin's base `<Button>`, so it's responsive, accessible, and the label is translatable.

### Props

| Prop | Required | Type | Default | Description |
| ------------- | -------- | --------------- | ------------------ | -------------------------------------------- |
| `resource` | Optional | `string` | - | Target resource, e.g. 'posts' |
| `label` | Optional | `string` | 'ra.action.create' | label or translation message to use |
| `icon` | Optional | `ReactElement` | - | iconElement, e.g. `<CommentIcon />` |
| `scrollToTop` | Optional | `boolean` | `true` | Scroll to top after link |

It also supports [all the other `<Button>` props](#button).

### Access Control

If you want to control whether this button should be displayed based on users permissions, use the `<CloneButton>` exported by the `@react-admin/ra-rbac` Enterprise package.

```diff
-import { CloneButton } from 'react-admin';
+import { CloneButton } from '@react-admin/ra-rbac';
```

This component adds the following [RBAC](./AuthRBAC.md) controls:

- It will only render if the user has the `'clone'` permission on the current resource.

```js
{ action: "clone", resource: [current resource] }
```

Here is an example of how to use the `<CloneButton>` with RBAC:

```tsx
import { Edit, TopToolbar } from 'react-admin';
import { CloneButton } from '@react-admin/ra-rbac';

const PostEditActions = () => (
<TopToolbar>
<CloneButton />
</TopToolbar>
);

export const PostEdit = () => (
<Edit actions={<PostEditActions />}>
{/* ... */}
</Edit>
);
```

This component accepts additional props:

| Prop | Required | Type | Default | Description |
| -------------------- | -------- | ----------------- | ---------- | ---------------------------------------------------------------------- |
| `accessDenied` | Optional | ReactNode | null | The content to display when users don't have the `'clone'` permission |
| `action` | Optional | String | `"clone"` | The action to call `authProvider.canAccess` with |
| `authorizationError` | Optional | ReactNode | null | The content to display when an error occurs while checking permission |

## `<CreateButton>`

Opens the Create view of the current resource:
Expand Down Expand Up @@ -942,6 +1016,58 @@ export const PostList = () => (

**Tip**: If you are looking for an `<ImportButton>`, check out this third-party package: [benwinding/react-admin-import-csv](https://github.com/benwinding/react-admin-import-csv).

### Access Control

If you want to control whether this button should be displayed based on users permissions, use the `<ExportButton>` exported by the `@react-admin/ra-rbac` Enterprise package.

```diff
-import { ExportButton } from 'react-admin';
+import { ExportButton } from '@react-admin/ra-rbac';
```

This component adds the following [RBAC](./AuthRBAC.md) controls:

- It will only render if the user has the `'export'` permission on the current resource.

```js
{ action: "export", resource: [current resource] }
```

- It will only export the fields the user has the `'read'` permission on.

```js
{ action: "read", resource: `${resource}.${source}` }
```

Here is an example usage:

```jsx
import { CreateButton, TopToolbar } from 'react-admin';
import { ExportButton } from '@react-admin/ra-rbac';

const PostListActions = () => (
<TopToolbar>
<PostFilter context="button" />
<CreateButton />
<ExportButton />
</TopToolbar>
);

export const PostList = () => (
<List actions={<PostListActions />}>
...
</List>
);
```

This component accepts additional props:

| Prop | Required | Type | Default | Description |
| -------------------- | -------- | ----------------- | ---------- | ---------------------------------------------------------------------- |
| `accessDenied` | Optional | ReactNode | null | The content to display when users don't have the `'export'` permission |
| `action` | Optional | String | `"export"` | The action to call `authProvider.canAccess` with |
| `authorizationError` | Optional | ReactNode | null | The content to display when an error occurs while checking permission |

## `<FilterButton>`

This button is an internal component used by react-admin in [the Filter button/form combo](./FilteringTutorial.md#the-filter-buttonform-combo).
Expand Down
12 changes: 11 additions & 1 deletion docs/Create.md
Original file line number Diff line number Diff line change
Expand Up @@ -701,10 +701,20 @@ export const BookCreate = () => {
};
```

## Security
## Anonymous Access

The `<Create>` component requires authentication and will redirect anonymous users to the login page. If you want to allow anonymous access, use the [`disableAuthentication`](#disableauthentication) prop.

```jsx
const PostCreate = () => (
<Create disableAuthentication>
...
</Create>
);
```

## Access Control

If your `authProvider` implements [Access Control](./Permissions.md#access-control), `<Create>` will only render if the user has the "create" access to the related resource.

For instance, for the `<PostCreate>`page below:
Expand Down
169 changes: 127 additions & 42 deletions docs/Datagrid.md
Original file line number Diff line number Diff line change
Expand Up @@ -1074,48 +1074,6 @@ Additionally, `<DatagridAG>` is compatible with the [Enterprise version of ag-gr

Check [the `<DatagridAG>` documentation](./DatagridAG.md) for more details.

## Fields And Permissions

You might want to display some fields only to users with specific permissions. Use the `usePermissions` hook to get the user permissions and hide Fields accordingly:

{% raw %}
```tsx
import { List, Datagrid, TextField, TextInput, ShowButton, usePermissions } from 'react-admin';

const getUserFilters = (permissions) => ([
<TextInput label="user.list.search" source="q" alwaysOn />,
<TextInput source="name" />,
permissions === 'admin' ? <TextInput source="role" /> : null,
].filter(filter => filter !== null)
);

export const UserList = ({ permissions, ...props }) => {
const { permissions } = usePermissions();
return (
<List
{...props}
filters={getUserFilters(permissions)}
sort={{ field: 'name', order: 'ASC' }}
>
<Datagrid>
<TextField source="id" />
<TextField source="name" />
{permissions === 'admin' && <TextField source="role" />}
{permissions === 'admin' && <EditButton />}
<ShowButton />
</Datagrid>
</List>
)
};
```
{% endraw %}

Note how the `permissions` prop is passed down to the custom `filters` component to allow Filter customization, too.

It's up to your `authProvider` to return whatever you need to check roles and permissions inside your component. Check [the authProvider documentation](./Authentication.md) for more information.

**Tip**: The [ra-rbac module](./AuthRBAC.md#datagrid) provides a wrapper for the `<Datagrid>` with built-in permission check for columns.

## Standalone Usage

You can use the `<Datagrid>` component to display data that you've fetched yourself. You'll need to pass all the props required for its features:
Expand Down Expand Up @@ -1386,3 +1344,130 @@ export const PostList = () => (
</List>
);
```

## Access Control

If you need to hide some columns based on a set of permissions, use the `<Datagrid>` component from the `@react-admin/ra-rbac` package.

```diff
-import { Datagrid } from 'react-admin';
+import { Datagrid } from '@react-admin/ra-rbac';
```

This component adds the following [RBAC](./AuthRBAC.md) controls:

- Users must have the `'read'` permission on a resource column to see it in the export:

```jsx
{ action: "read", resource: `${resource}.${source}` }.
// or
{ action: "read", resource: `${resource}.*` }.
```

- Users must have the `'delete'` permission on the resource to see the `<BulkExportButton>`.

- The default `rowClick` depends on the user permissions:
- `"edit"` if the user can access the current resource with the `edit` action
- `"show"` if the user can access the current resource with the `show` action
- empty otherwise

Here is an example of `<Datagrid>` with RBAC:

```tsx
import { canAccessWithPermissions, List, Datagrid } from '@react-admin/ra-rbac';
import {
ImageField,
TextField,
ReferenceField,
NumberField,
} from 'react-admin';

const authProvider = {
// ...
canAccess: async ({ action, record, resource }) =>
canAccessWithPermissions({
permissions: [
{ action: 'list', resource: 'products' },
{ action: 'read', resource: 'products.thumbnail' },
{ action: 'read', resource: 'products.reference' },
{ action: 'read', resource: 'products.category_id' },
{ action: 'read', resource: 'products.width' },
{ action: 'read', resource: 'products.height' },
{ action: 'read', resource: 'products.price' },
{ action: 'read', resource: 'products.description' },
// { action: 'read', resource: 'products.stock' },
// { action: 'read', resource: 'products.sales' },
// { action: 'delete', resource: 'products' },
{ action: 'show', resource: 'products' },
],
action,
record,
resource
}),
};

const ProductList = () => (
<List>
{/* The datagrid has no bulk actions as the user doesn't have the 'delete' permission */}
<Datagrid>
<ImageField source="thumbnail" />
<TextField source="reference" />
<ReferenceField source="category_id" reference="categories">
<TextField source="name" />
</ReferenceField>
<NumberField source="width" />
<NumberField source="height" />
<NumberField source="price" />
<TextField source="description" />
{/** These two columns are not visible to the user **/}
<NumberField source="stock" />
<NumberField source="sales" />
</Datagrid>
</List>
);
```

**Tip**: Adding the 'read' permission on the resource itself doesn't grant the 'read' permission on the columns. If you want a user to see all possible columns, add the 'read' permission on columns using a wildcard:

```jsx
{ action: "read", resource: "products.*" }.
```

Fow simple cases, you can also use [the `useCanAccess` hook](./useCanAccess.md) to check whether users have access to a field:

{% raw %}
```tsx
import { List, Datagrid, TextField, TextInput, ShowButton, useCanAccess } from 'react-admin';

const getUserFilters = (canAccessRole) => ([
<TextInput label="user.list.search" source="q" alwaysOn />,
<TextInput source="name" />,
canAccessRole ? <TextInput source="role" /> : null,
].filter(filter => filter !== null)
);

export const UserList = ({ permissions, ...props }) => {
const { canAccess, error, isPending } = useCanAccess({
resource: 'users.role',
action: 'read'
});
return (
<List
{...props}
filters={getUserFilters(canAccess)}
sort={{ field: 'name', order: 'ASC' }}
>
<Datagrid>
<TextField source="id" />
<TextField source="name" />
{canAccess ? <TextField source="role" /> : null}
<EditButton />
<ShowButton />
</Datagrid>
</List>
)
};
```
{% endraw %}

Note how the `canAccess` value is passed down to the custom `filters` component to allow Filter customization, too.
14 changes: 12 additions & 2 deletions docs/Edit.md
Original file line number Diff line number Diff line change
Expand Up @@ -981,10 +981,20 @@ export const BookEdit = () => {
};
```

## Security
## Anonymous Access

The `<Edit>` component requires authentication and will redirect anonymous users to the login page. If you want to allow anonymous access, use the [`disableAuthentication`](#disableauthentication) prop.

```jsx
const PostEdit = () => (
<Edit disableAuthentication>
...
</Edit>
);
```

## Access Control

If your `authProvider` implements [Access Control](./Permissions.md#access-control), `<Edit>` will only render if the user has the "edit" access to the related resource.

For instance, for the `<PostEdit>`page below:
Expand Down Expand Up @@ -1012,4 +1022,4 @@ const PostEdit = () => (

Users without access will be redirected to the [Access Denied page](./Admin.md#accessdenied).

**Note**: Access control is disabled when you use [the `disableAuthentication` prop](#disableauthentication).
**Note**: Access control is disabled when you use [the `disableAuthentication` prop](#disableauthentication).
Loading