Skip to content

Commit

Permalink
Merge branch 'next' of github.com:refinedev/refine into next
Browse files Browse the repository at this point in the history
  • Loading branch information
Ömer Faruk APLAK committed Mar 17, 2023
2 parents adb5bda + 41a4525 commit 6577f17
Show file tree
Hide file tree
Showing 21 changed files with 1,221 additions and 326 deletions.
5 changes: 5 additions & 0 deletions .changeset/rotten-mayflies-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@refinedev/core": minor
---

feat: make CanAccess component props optional. Now CanAccess component infers resource and action automagically.
10 changes: 7 additions & 3 deletions documentation/docs/advanced-tutorials/access-control.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ const App: React.FC = () => {
action,
);

return Promise.resolve({ can });
return { can };
},
}}
// highlight-end
Expand Down Expand Up @@ -249,7 +249,11 @@ const App: React.FC = () => {
can: async ({ resource, action }) => {
const enforcer = await newEnforcer(model, adapter);
// highlight-next-line
const can = await enforcer.enforce(role, resource, action);
const can = await enforcer.enforce(
role,
resource,
action,
);

return Promise.resolve({
can,
Expand Down Expand Up @@ -564,7 +568,7 @@ export const PostList: React.FC = () => {
```

:::tip
[`<CanAccess />`](/api-reference/core/components/accessControl/canAccess.md) can be used too to check access control in custom places in your app.
[`<CanAccess />`](/docs/api-reference/core/components/accessControl/can-access) can be used too to check access control in custom places in your app.
:::

<br/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,43 @@ Passes the given properties to the `can` method from your [access control provid

## Basic Usage

By default, `CanAccess` component will infer the current `resource` and the `action` based on your route automatically. `id` will also be inferred if the current route includes one.

So if you are at `/posts` route, `CanAccess` will check authorization for `posts` resource and `list` action.

For `/posts/show/:id` route, action will be `show`.

```tsx
import { CanAccess } from "@refinedev/core";

const MyComponent = () => (
<CanAccess
resource="posts"
action="edit"
params={{ id: 1 }}
fallback={<CustomFallback />}
>
<CanAccess fallback={<CustomFallback />}>
<YourComponent />
</CanAccess>
);
```

### Usage with props

You may have a case like in the `/posts/show/:id` page, where inferred resource is `posts` and action is `show`, but you want to authorize a different resource eg. `category`.

In this case, you can explicitly pass props to `CanAccess` component for authorizing a different resource.

```tsx
import { CanAccess } from "@refinedev/core";

export const MyComponent = () => {
return (
<Buttons>
<CreateButton>Create</CreateButton>
<CanAccess resource="posts" action="delete">
<DeleteButton>Delete</DeleteButton>
</CanAccess>
</Buttons>
);
};
```

## Properties

It's also accepts all the properties of [`useCan`](/docs/api-reference/core/hooks/accessControl/useCan/#properties).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,48 @@ A basic example looks like:

```tsx
const App: React.FC = () => {
<Refine
// other providers and props
accessControlProvider={{
can: async ({ resource, action, params }) => {
if (resource === "posts" && action === "edit") {
return Promise.resolve({
can: false,
reason: "Unauthorized",
});
}

// or you can access directly *resource object
// const resourceName = params?.resource?.name;
// const anyUsefulMeta = params?.resource?.meta?.yourUsefulMeta;
// if (resourceName === "posts" && anyUsefulMeta === true && action === "edit") {
// return Promise.resolve({
// can: false,
// reason: "Unauthorized",
// });
// }

return Promise.resolve({ can: true });
},
}}
>
{/* your app */}
</Refine>
return (
<Refine
// other providers and props
accessControlProvider={{
can: async ({ resource, action, params }) => {
if (resource === "posts" && action === "edit") {
return Promise.resolve({
can: false,
reason: "Unauthorized",
});
}

return { can: true };
},
}}
>
{/* your app */}
</Refine>
);
};
```

:::tip
You can also access resource object directly.

```tsx
export const accessControlProvider = {
can: async ({ resource, action, params }) => {
const resourceName = params?.resource?.name;
const anyUsefulMeta = params?.resource?.meta?.yourUsefulMeta;

if (
resourceName === "posts" &&
anyUsefulMeta === true &&
action === "edit"
) {
return {
can: false,
reason: "Unauthorized",
};
}
},
};
```

Expand Down
18 changes: 15 additions & 3 deletions documentation/docs/migration-guide/router-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,25 @@ const CustomSider = () => {
}
```

If you have customized the use of `useMenu` hook, you might need to check the usage of it to make sure it's working as expected. Even though the `useMenu` hook is not changed in its return values, the way it generates the menu item keys is changed.
If you have customized the use of `useMenu` hook, you might need to check the usage of it to make sure it's working as expected. Even though the `useMenu` hook is not changed in its return values, the way it generates the menu item keys is changed.

### Behavioral Changes in Routing

Since **refine** doesn't create routes internally anymore, you will need to create your routes manually. In the previous versions, this also made **refine** responsible for authentication checks and redirections. With the new router provider, **refine** no longer handles these checks and redirections. You will need to handle them yourself such as redirecting to the `/login` page or 404 pages. This also means that the access control point in routes are now needed to be handled by the user. You can handle it using the `CanAccess` component or the `useCan` hook in your pages or as wrappers around your pages.
Since **refine** doesn't create routes internally anymore, you are free to create your routes according to your framework without any limitation.

You can find more information and examples in the documentation for each router.
This means, tasks like `authentication` and `access control` are also de-coupled from **refine**.

However, for convenience we still provide a set of helpers for you to handle these tasks easily.

#### Authentication and Access Control

This also means that the authentication and access control flows should be handled according to your framework.

However **refine** still provides some helpers for user's convenience.

For **authentication**, you can use [`Authenticated`](/docs/api-reference/core/components/auth/authenticated) component as wrapper or use `useIsAuthenticated` hook inside your components.

For **access control**, you can use [`CanAccess`](/docs/api-reference/core/components/accessControl/can-access) component as wrapper or use `useCan` hook in your components.

## Using the New Router Providers

Expand Down
Loading

0 comments on commit 6577f17

Please sign in to comment.