Skip to content

Commit

Permalink
Move RBAC buttons doc to the Buttons chapter
Browse files Browse the repository at this point in the history
  • Loading branch information
fzaninotto committed Dec 12, 2024
1 parent 3011173 commit 7f60ef3
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 74 deletions.
115 changes: 53 additions & 62 deletions docs/AuthRBAC.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ React-admin already does page-level access control with actions like "list", "sh
| `create` | Allow to access the Create page | [`<Create>`](./Create.md), [`<CreateButton>`](./Buttons.md#createbutton), [`<List>`](./List.md#access-control) |
| `edit` | Allow to access the Edit page | [`<Edit>`](./Edit.md), [`<EditButton>`](./Buttons.md#editbutton), [`<Datagrid>`](./Datagrid.md#access-control), [`<Show>`](./Show.md) |
| `delete` | Allow to delete data | [`<DeleteButton>`](./Buttons.md#deletebutton), [`<BulkDeleteButton>`](./Buttons.md#bulkdeletebutton), [`<Datagrid>`](./Datagrid.md#access-control), [`<SimpleForm>`](./SimpleForm.md#access-control), [`<TabbedForm>`](#tabform) |
| `export` | Allow to export data | [`<ExportButton>`](#exportbutton), [`<List>`](./List.md#access-control) |
| `clone` | Allow to clone a record | [`<CloneButton>`](#clonebutton), [`<Edit>`](./Edit.md) |
| `export` | Allow to export data | [`<ExportButton>`](./Buttons.md#exportbutton), [`<List>`](./List.md#access-control) |
| `clone` | Allow to clone a record | [`<CloneButton>`](./Buttons.md#clonebutton), [`<Edit>`](./Edit.md) |
| `read` | Allow to view a field (or a tab) | [`<Datagrid>`](./Datagrid.md#access-control), [`<SimpleShowLayout>`](./SimpleShowLayout.md#access-control), [`<TabbedShowLayout>`](./TabbedShowLayout.md#access-control) |
| `write` | Allow to edit a field (or a tab) | [`<SimpleForm>`](./SimpleForm.md#access-control), [`<TabbedForm>`](./TabbedForm.md#access-control), [`<WizardForm>`](./WizardForm.md#enableaccesscontrol), [`<LongForm>`](./LongForm.md#enableaccesscontrol), [`<AccordionForm>`](./AccordionForm.md#enableaccesscontrol) |

Expand Down Expand Up @@ -365,80 +365,71 @@ Ra-rbac provides alternative components to react-admin base components. These al
- List
- [`<List>`](./List.md#access-control)
- [`<Datagrid>`](./Datagrid.md#access-control)
- [`<ExportButton>`](./Buttons.md#exportbutton)
- Detail
- [`<SimpleShowLayout>`](./SimpleShowLayout.md#access-control)
- [`<TabbedShowLayout>`](./TabbedShowLayout.md#access-control)
- [`<CloneButton>`](./Buttons.md#clonebutton)
- Form
- [`<SimpleForm>`](./SimpleForm.md#access-control)
- [`<TabbedForm>`](./TabbedForm.md#access-control)

## `<ExportButton>`

Replacement for react-admin's [`<ExportButton>`](./Buttons.md#exportbutton) that checks users have the `'export'` permission before rendering. Use it if you want to provide your own `actions` to the `<List>`:
Here is an example of `<Datagrid>` with RBAC:

```tsx
import { CreateButton, List, 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>
);
```

It accepts the following props in addition to the default [`<ExportButton>` props](./Buttons.md#props-8):

| 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 |

**Tip**: Don't forget to give read permissions on all the fields you want to allow in exports
```jsx
{ action: "read", resource: `${resource}.${source}` }.
// or
{ action: "read", resource: `${resource}.*` }.
```

## `<CloneButton>`

Replacement for react-admin's [`<CloneButton>`](./Buttons.md#clonebutton) that checks users have the `'clone'` permission before rendering. Use it if you want to provide your own `actions` to the `<Edit>`:
import { canAccessWithPermissions, List, Datagrid } from '@react-admin/ra-rbac';
import {
ImageField,
TextField,
ReferenceField,
NumberField,
} from 'react-admin';

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

const PostEditActions = () => (
<TopToolbar>
<CloneButton />
</TopToolbar>
);
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
}),
};

export const PostEdit = () => (
<Edit actions={<PostEditActions />}>
{/* ... */}
</Edit>
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>
);
```

It accepts the following props in addition to the default `<CloneButton>` 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 |

## Performance

`authProvider.canAccess()` can return a promise, which in theory allows to rely on the authentication server for permissions. The downside is that this slows down the app a great deal, as each page may contain dozens of calls to these methods.
Expand Down
69 changes: 57 additions & 12 deletions docs/Buttons.md
Original file line number Diff line number Diff line change
Expand Up @@ -600,26 +600,48 @@ 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, you can leverage the `<CloneButton>` exported by the `@react-admin/ra-rbac` Enterprise package.
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.

This `<CloneButton>` will call `authProvider.canAccess()` using the following parameters:
```diff
-import { CloneButton } from 'react-admin';
+import { CloneButton } from '@react-admin/ra-rbac';
```

```txt
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] }
```

```jsx
import { TopToolbar, List } from 'react-admin';
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 PostList = () => (
<List>
<TextField source="title" />
const PostEditActions = () => (
<TopToolbar>
<CloneButton />
</List>
</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 @@ -996,14 +1018,29 @@ export const PostList = () => (

### Access Control

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

This `<ExportButton>` will call `authProvider.canAccess()` using the following parameters:
```diff
-import { ExportButton } from 'react-admin';
+import { ExportButton } from '@react-admin/ra-rbac';
```

```txt
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';
Expand All @@ -1023,6 +1060,14 @@ export const PostList = () => (
);
```

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

0 comments on commit 7f60ef3

Please sign in to comment.