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

一种可能性是扩展控制器中 findfindOne 使用的查询,并限制登录用户。在这种情况下,您可能还希望调整 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 插件。