Skip to content

Commit

Permalink
MAke access control section position consistent
Browse files Browse the repository at this point in the history
  • Loading branch information
fzaninotto committed Dec 12, 2024
1 parent 0c71fe8 commit 1a96836
Show file tree
Hide file tree
Showing 7 changed files with 331 additions and 293 deletions.
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
254 changes: 127 additions & 127 deletions docs/Datagrid.md
Original file line number Diff line number Diff line change
Expand Up @@ -1074,133 +1074,6 @@ Additionally, `<DatagridAG>` is compatible with the [Enterprise version of ag-gr

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

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

## 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 @@ -1471,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).
45 changes: 26 additions & 19 deletions docs/Resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,25 +321,6 @@ const MyComponent = () => (
);
```

## Security

The usual components for the `<Resource>` routes ( `<List>`, `<Create>`, `<Edit>`, `<Show>`) require authentication and will redirect anonymous users to the login page. If you want to allow anonymous access, use the [`disableAuthentication`](./List.md#disableauthentication) prop on the component.

In addition, if your `authProvider` implements [Access Control](./Permissions.md#access-control), these components will only render if the user has the right permission (e.g., `{ action: 'list', resource: 'posts' }` for the `list` page of the `posts` resource).

For instance, given the following resource:

```tsx
<Resource name="posts" list={PostList} create={PostCreate} edit={PostEdit} show={PostShow} />
```

React-admin will call the `authProvider.canAccess` method when users try to access the pages with the following parameters:

- For the list page: `{ action: "list", resource: "posts" }`
- For the create page: `{ action: "create", resource: "posts" }`
- For the edit page: `{ action: "edit", resource: "posts" }`
- For the show page: `{ action: "show", resource: "posts" }`

## Nested Resources

React-admin doesn't support nested resources, but you can use [the `children` prop](#children) to render a custom component for a given sub-route. For instance, to display a list of songs for a given artist:
Expand Down Expand Up @@ -464,3 +445,29 @@ When users navigate to the `/posts` route, react-admin will display a loading in
![Loading indicator](./img/lazy-resource.png)
## Anonymous Access
The usual components for the `<Resource>` routes ( `<List>`, `<Create>`, `<Edit>`, `<Show>`) require authentication and will redirect anonymous users to the login page. If you want to allow anonymous access, use the [`disableAuthentication`](./List.md#disableauthentication) prop on the component.
## Access Control
In addition, if your `authProvider` implements [Access Control](./Permissions.md#access-control), these components will only render if the user has the right permission (e.g., `{ action: 'list', resource: 'posts' }` for the `list` page of the `posts` resource).
For instance, given the following resource:
```tsx
<Resource
name="posts"
list={PostList}
create={PostCreate}
edit={PostEdit}
show={PostShow}
/>
```
React-admin will call the `authProvider.canAccess` method when users try to access the pages with the following parameters:
- For the list page: `{ action: "list", resource: "posts" }`
- For the create page: `{ action: "create", resource: "posts" }`
- For the edit page: `{ action: "edit", resource: "posts" }`
- For the show page: `{ action: "show", resource: "posts" }`
12 changes: 11 additions & 1 deletion docs/Show.md
Original file line number Diff line number Diff line change
Expand Up @@ -701,10 +701,20 @@ export const BookShow = () => {
};
```

## Security
## Anonymous Access

The `<Show>` 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 PostShow = () => (
<Show disableAuthentication>
...
</Show>
);
```

## Access Control

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

For instance, for the `<PostShow>`page below:
Expand Down
Loading

0 comments on commit 1a96836

Please sign in to comment.