Hi to all. I would like to tell my own version of IsOwner (global) Policy.
To get it work, the collection or content type must have a field named “author” that is a relation N-1 to users-permission
/config/policies/is-owner.js:
// the content type must have field named "author" that is a relation N-1 to users-permission
module.exports = async (ctx, next) => {
// must be authenticated user
if (!ctx.state.user) {
return ctx.unauthorized(`Forbidden`)
}
const url = ctx.request.url
// I get the collection or content type from url. Sure there is a better way
const parts = url.split('/')
const last = parts[parts.length - 1]
const collection = parts[parts.length - (last.match(/^\d+$/) ? 2 : 1)]
if (!strapi.services[collection])
return ctx.unauthorized(`Collection ${collection} not found`)
const [content] = await strapi.services[collection].find({
id: ctx.params.id,
'author.id': ctx.state.user.id
})
if (!content) {
return ctx.unauthorized(`Only the author can do this`)
}
return await next()
}
Then, we can use the global policy in routes.json for update or delete a content. For example:
/api/articles/config/routes.json:
...
{
"method": "PUT",
"path": "/articles/:id",
"handler": "articles.update",
"config": {
"policies": ["global::is-owner"]
},
{
"method": "DELETE",
"path": "/articles/:id",
"handler": "articles.delete",
"config": {
"policies": ["global::is-owner"]
}
...
We also can use a custom controller that binds automatically author with the content when is created.
/api/articles/controllers/articles.js:
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
module.exports = {
// https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#controllers
async create(ctx) {
let entity;
if (ctx.is('multipart')) {
const { data, files } = parseMultipartData(ctx);
data.author = ctx.state.user.id;
entity = await strapi.services.articles.create(data, { files });
} else {
ctx.request.body.author = ctx.state.user.id;
entity = await strapi.services.articles.create(ctx.request.body);
}
return sanitizeEntity(entity, { model: strapi.models.articles});
}
}
If you have more than a content type with author ownerness policy, you must replicate last two steps in each content type (routes.json and custom ‘create’ controller).
If anyone knows another way to get same or better result to get global IsOwner policy to work, please tell.