如何在自定义 Strapi 控制器中填充"user"关系,而不公开所有用户的"find"?



我认为我误解了Strapi的一些基本原理:如果我想填充查询以获得其所有关系字段,我需要激活"查找";部分API。但这会让所有人都看到这种模式。。。。

例如,我有一个名为";文章";,其具有关联的";用户";关系在我的自定义article.js控制器中,我试图允许任何人看到一篇文章,以及相应的用户名称(但仅限于他们的名称(。要做到这一点,我有这样的东西:

async find(ctx) {
const entries = await strapi.entityService.findMany('api::article.article', {
populate: {
user: {fields: ['username']}
}
});
const sanitizedEntries = await this.sanitizeOutput(entries, ctx);
return this.transformResponse(sanitizedEntries);
}

但是,为了使其发挥作用,我需要启用";查找";对于整个用户模型,这是不安全的。我是否在如何实现这一点上遗漏了一些显而易见的东西?在关系数据库中,允许在不向所有人公开整个模型的情况下进行填充似乎是一个非常基本的需求。

感谢

一种可能的解决方案是实现这里描述的中间件。

简短描述:

  1. 将strapi-server.js添加到用户权限插件中。(更多信息此处为主题(
  2. 添加一个中间件。(例如使用yarn strapi generate(
  3. 在中间件中实现对象净化例如:
// sanitizer function
const sanitizeItem = (item, user) => {
// check if user is not undefined
if (user) {
// check if user id is same as the item.id (user from request)
if (user.id === item.id) {
// if it's same return full object
return item;
}
}
// TODO: rename hiddenField to the field you want to hide
let { hiddenField, ...rest } = item;
return rest;
}

当试图隐藏用户的电子邮件时,您的中间件可能看起来像这样:

'use strict';
/**
* `user-sanitization` middleware
*/
module.exports = (config, { strapi }) => {
return async (ctx, next) => {
// before controller
await next();
// after controller
// we need to check if the reponse is correct, 
// otherwise we will have error message in the data
if (ctx.response.status === 200) {
// get the authenticated user, if no user - undefined
const { user } = ctx.state;
// get data from response
let data = ctx.response.body;
// check if data is array
if (Array.isArray(data)) {
// run sanitize function for each element
data = data.map(item => sanitizeItem(item, user))
} else {
// else run for single item
data = sanitizeItem(data, user);
}
// apply result to response
ctx.response.body = data;
}
};
};
// sanitizer function
const sanitizeItem = (item, user) => {
// check if user is not undefined
if (user) {
// check if user id is same as the item.id (user from request)
if (user.id === item.id) {
// if it's same return full object
return item;
}
}
// else extract email from object
let { email, ...rest } = item;
return rest;
}

相关内容

最新更新