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

时间:2017-06-19 23:44:00

标签: graphql

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

type User {
  name: String
  username: String
  someOtherField1: String
  someOtherField2: String
  someOtherField3: String
  someOtherField4: String
  creditCardNumber: String
}

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

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

type UserSearch {
  name: String
  username: String
  someOtherField1: String
  someOtherField2: String
  someOtherField3: String
  someOtherField4: String
}

排除了私有字段,但是这并不感觉干,因为你要创建许多结构形式相似90%的类型。

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

1 个答案:

答案 0 :(得分:13)

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

这意味着,在resolve字段的creditCardNumber函数内,您可以检查当前用户是否是被提取的用户,如果是,则返回该数字。否则,返回null。

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

graphql(schema, query, rootValue, context) // <-- the last parameter

您将在每个字段resolve函数签名中找到此对象:

...
resolve: (object, args, context) => {
  // Third argument is your object
},
....

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

graphql(schema, query, rootValue, { user: getCurrentLoggedUser() })

在您的User类型中,creditCardNumber字段解析功能:

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

    return null;
  },
  ...
}

如果您使用的是graphql-express,则默认情况下上下文是and you can customize it