Skip to content

Commit 973fed4

Browse files
authored
Add is-owner policy equivalent to middlewares documentation (#1816)
1 parent b6cf65f commit 973fed4

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

docusaurus/docs/dev-docs/backend-customization/middlewares.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,86 @@ Middlewares are called different ways depending on their scope:
134134
:::tip
135135
To list all the registered middlewares, run `yarn strapi middlewares:list`.
136136
:::
137+
138+
### Restricting content access with an "is-owner policy"
139+
140+
It is often required that the author of an entry is the only user allowed to edit or delete the entry. In previous versions of Strapi, this was known as an "is-owner policy". With Strapi v4, the recommended way to achieve this behavior is to use a middleware.
141+
142+
Proper implementation largely depends on your project's needs and custom code, but the most basic implementation could be achieved with the following procedure:
143+
144+
1. From your project's folder, create a middleware with the Strapi CLI generator, by running the `yarn strapi generate` (or `npm run strapi generate`) command in the terminal.
145+
2. Select `middleware` from the list, using keyboard arrows, and press Enter.
146+
3. Give the middleware a name, for instance `isOwner`.
147+
4. Choose `Add middleware to an existing API` from the list.
148+
5. Select which API you want the middleware to apply.
149+
6. Replace the code in the `/src/api/[your-api-name]/middlewares/isOwner.js` file with the following, replacing `api::restaurant.restaurant` in line 22 with the identifier corresponding to the API you choose at step 5 (e.g., `api::blog-post.blog-post` if your API name is `blog-post`):
150+
151+
```js showLineNumbers title="src/api/blog-post/middlewares/isOwner.js"
152+
"use strict";
153+
154+
/**
155+
* `isOwner` middleware
156+
*/
157+
158+
module.exports = (config, { strapi }) => {
159+
// Add your own logic here.
160+
return async (ctx, next) => {
161+
const user = ctx.state.user;
162+
const entryId = ctx.params.id ? ctx.params.id : undefined;
163+
let entry = {};
164+
165+
/**
166+
* Gets all information about a given entry,
167+
* populating every relations to ensure
168+
* the response includes author-related information
169+
*/
170+
if (entryId) {
171+
entry = await strapi.entityService.findOne(
172+
// highlight-start
173+
// replace the next line with your proper content-type identifier
174+
"api::restaurant.restaurant",
175+
// highlight-end
176+
entryId,
177+
{ populate: "*" }
178+
);
179+
}
180+
181+
/**
182+
* Compares user id and entry author id
183+
* to decide whether the request can be fulfilled
184+
* by going forward in the Strapi backend server
185+
*/
186+
if (user.id !== entry.author.id) {
187+
return ctx.unauthorized("This action is unauthorized.");
188+
} else {
189+
return next();
190+
}
191+
};
192+
};
193+
```
194+
195+
7. Ensure the middleware is configured to apply on some routes. In the `config` object found in the `src/api/[your-api–name]/routes/[your-content-type-name].js` file, define the methods (`create`, `read`, `update`, `delete`) for which you would like the middleware to apply, and declare the `isOwner` middleware for these routes.<br /><br />For instance, if you wish to allow GET (i.e., `read` method) and POST (i.e., `create` method) requests to any user for the `restaurant` content-type in the `restaurant` API, but would like to restrict PUT (i.e., `update` method) and DELETE requests only to the user who created the entry, you could use the following code in the `src/api/restaurant/routes/restaurant.js` file:
196+
197+
```js title="src/api/restaurant/routes/restaurant.js"
198+
199+
/**
200+
* restaurant router
201+
*/
202+
203+
const { createCoreRouter } = require("@strapi/strapi").factories;
204+
205+
module.exports = createCoreRouter("api::restaurant.restaurant", {
206+
config: {
207+
update: {
208+
middlewares: ["api::restaurant.is-owner"],
209+
},
210+
delete: {
211+
middlewares: ["api::restaurant.is-owner"],
212+
},
213+
},
214+
});
215+
```
216+
217+
:::info
218+
You can find more information about route middlewares in the [routes documentation](/dev-docs/backend-customization/routes).
219+
:::

0 commit comments

Comments
 (0)