strapi - 限制用户只获取与他相关的数据
strapi - restrict user to fetch only data related to him
通常,登录用户会获得一个内容类型的所有条目。
我创建了一个 "snippets" 内容类型 (_id,name,content,users<<->>snippets)
<<->>
表示 "has and belongs to many" 关系。
我创建了一些测试用户并提出了一个请求:
curl -H 'Authorization: Bearer eyJ...' http://localhost:1337/snippets/
主要问题:经过身份验证的用户应该只能看到分配给他的条目。相反,登录用户会获得所有片段,这很糟糕。
如何修改 fetchAll(ctx.query);
查询以将其考虑在内,以便它在 /
-route->find
- 执行类似 fetchAll(ctx.state.user.id);
的操作方法 ?
基本的查找方法在这里:
find: async (ctx) => {
if (ctx.query._q) {
return strapi.services.snippet.search(ctx.query);
} else {
return strapi.services.snippet.fetchAll(ctx.query);
}
},
子问题:当我进行 Bearer-Token 身份验证时,strapi 甚至知道哪个用户登录了吗?
您可以在 snippets 配置下设置 /snippets/me 路由。
该路由可以调用 Snippets.me 控制器方法,该方法将检查用户然后根据用户查询片段。
所以在 api/snippet/config/routes.json
中会有这样的东西:
{
"method": "GET",
"path": "/snippets/me",
"handler": "Snippets.me",
"config": {
"policies": []
}
},
然后在控制器 (api/snippet/controllers/Snippet.js
) 中,您可以执行以下操作:
me: async (ctx) => {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [{ messages: [{ id: 'No authorization header was found' }] }]);
}
const data = await strapi.services.snippet.fetch({user:user.id});
if(!data){
return ctx.notFound();
}
ctx.send(data);
},
然后您将为经过身份验证的用户授予 me 路由权限,而不是整个 snippets 路由权限。
以上是正确的,除了较新版本的 strapi。使用 find
而不是 fetch
:)
const data = await strapi.services.snippet.find({ user: user.id });
Strapi v3.0.0-beta.20
一种可能性是扩展控制器中 find
和 findOne
使用的查询,并限制登录用户。在这种情况下,您可能还希望调整 count
端点以保持一致。
这将导致:
withOwnerQuery: (ctx, ownerPath) => {
const user = ctx.state.user;
if (!user) {
ctx.badRequest(null, [
{ messages: [{ id: "No authorization header was found" }] },
]);
return null;
}
return { ...ctx.query, [ownerPath]: user.id };
};
find: async (ctx) => {
ctx.query = withOwnerQuery(ctx, "owner.id");
if (ctx.query._q) {
return strapi.services.snippet.search(ctx.query);
} else {
return strapi.services.snippet.fetchAll(ctx.query);
}
},
// analogous for for findOne
根据您对控制器和服务的使用情况,您可以通过调整 service methods.
来实现相同的目的
这种解决方案适用于 GraphQL 插件。
通常,登录用户会获得一个内容类型的所有条目。
我创建了一个 "snippets" 内容类型 (_id,name,content,users<<->>snippets)
<<->>
表示 "has and belongs to many" 关系。
我创建了一些测试用户并提出了一个请求:
curl -H 'Authorization: Bearer eyJ...' http://localhost:1337/snippets/
主要问题:经过身份验证的用户应该只能看到分配给他的条目。相反,登录用户会获得所有片段,这很糟糕。
如何修改 fetchAll(ctx.query);
查询以将其考虑在内,以便它在 /
-route->find
- 执行类似 fetchAll(ctx.state.user.id);
的操作方法 ?
基本的查找方法在这里:
find: async (ctx) => {
if (ctx.query._q) {
return strapi.services.snippet.search(ctx.query);
} else {
return strapi.services.snippet.fetchAll(ctx.query);
}
},
子问题:当我进行 Bearer-Token 身份验证时,strapi 甚至知道哪个用户登录了吗?
您可以在 snippets 配置下设置 /snippets/me 路由。
该路由可以调用 Snippets.me 控制器方法,该方法将检查用户然后根据用户查询片段。
所以在 api/snippet/config/routes.json
中会有这样的东西:
{
"method": "GET",
"path": "/snippets/me",
"handler": "Snippets.me",
"config": {
"policies": []
}
},
然后在控制器 (api/snippet/controllers/Snippet.js
) 中,您可以执行以下操作:
me: async (ctx) => {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [{ messages: [{ id: 'No authorization header was found' }] }]);
}
const data = await strapi.services.snippet.fetch({user:user.id});
if(!data){
return ctx.notFound();
}
ctx.send(data);
},
然后您将为经过身份验证的用户授予 me 路由权限,而不是整个 snippets 路由权限。
以上是正确的,除了较新版本的 strapi。使用 find
而不是 fetch
:)
const data = await strapi.services.snippet.find({ user: user.id });
Strapi v3.0.0-beta.20
一种可能性是扩展控制器中 find
和 findOne
使用的查询,并限制登录用户。在这种情况下,您可能还希望调整 count
端点以保持一致。
这将导致:
withOwnerQuery: (ctx, ownerPath) => {
const user = ctx.state.user;
if (!user) {
ctx.badRequest(null, [
{ messages: [{ id: "No authorization header was found" }] },
]);
return null;
}
return { ...ctx.query, [ownerPath]: user.id };
};
find: async (ctx) => {
ctx.query = withOwnerQuery(ctx, "owner.id");
if (ctx.query._q) {
return strapi.services.snippet.search(ctx.query);
} else {
return strapi.services.snippet.fetchAll(ctx.query);
}
},
// analogous for for findOne
根据您对控制器和服务的使用情况,您可以通过调整 service methods.
来实现相同的目的这种解决方案适用于 GraphQL 插件。