GraphQL:如何跨查询限制服务器端的字段?

Jon*_*rsi 6 graphql

假设我有一个包含以下字段的用户类型:

type User {
  name: String
  username: String
  someOtherField1: String
  someOtherField2: String
  someOtherField3: String
  someOtherField4: String
  creditCardNumber: String
}
Run Code Online (Sandbox Code Playgroud)

如果我要自己查询,可以返回所有字段,因为信息是我的.所以回到creditCardNumber客户端并不重要.但是,如果我要查询其他人,我应该只能访问返回用户的公共信息.回来creditCardNumber会很糟糕.即使我不在客户端上编写查询代码,也会阻止恶意用户深入挖掘代码,更新客户端查询以包含creditCardNumber和执行它?

在GraphQL中跨查询实现此级别字段限制的最佳方法是什么?到目前为止,我唯一想到的是创建一个单独的UserSearch类型,即

type UserSearch {
  name: String
  username: String
  someOtherField1: String
  someOtherField2: String
  someOtherField3: String
  someOtherField4: String
}
Run Code Online (Sandbox Code Playgroud)

这不包括私人领域,但是这并不觉得干,因为你要创造许多在结构上彼此相似90%的类型.

有没有更简洁的方法来实现这一点,不会创建不必要的类型或重复字段?

yac*_*aka 14

默认情况下,GraphQL类型可能是类型,这意味着您可以将null返回到任何字段.

这意味着,在resolve您的creditCardNumber字段功能内,您可以检查当前用户是否是正在获取的用户,如果是,则返回该数字.否则,返回null.

要访问"上下文"数据(如当前用户),GraphQL允许您context在执行graphql函数时传递对象:

graphql(schema, query, rootValue, context) // <-- the last parameter
Run Code Online (Sandbox Code Playgroud)

你会在每个字段resolve函数签名中找到这个对象:

...
resolve: (object, args, context) => {
  // Third argument is your object
},
....
Run Code Online (Sandbox Code Playgroud)

那么你可以做的是在上下文中传递当前记录的用户:

graphql(schema, query, rootValue, { user: getCurrentLoggedUser() })
Run Code Online (Sandbox Code Playgroud)

在你的User类型中,creditCardNumber字段内部解析函数:

creditCardNumber: {
  ...
  resolve: (user, args, context) => {
    if (user.id === context.user.id)
      return user.creditCardNumber;

    return null;
  },
  ...
}
Run Code Online (Sandbox Code Playgroud)

如果您正在使用graphql-express,则上下文默认为请求,您可以自定义它.

  • 我无法相信这必须在每个需要过滤的领域得到解决. (5认同)