【问题标题】:GraphQL - How to distinguish Public from Private fields?GraphQL - 如何区分公共字段和私有字段?
【发布时间】:2018-08-15 07:20:42
【问题描述】:

上下文
我有一个 GraphQL API 和一个 NodeJS 和 Angular 应用程序,以及一个包含用户的 MongoDB 数据库。对于每个用户,都有一个公共页面,其中包含 idusername 等公共信息。当用户登录时,会出现一个包含扩展信息的私人个人资料页面,例如 email

就上下文而言,我使用jsonwebtokenaccesscontrol 来验证和授权用户。该信息存储在每个 GraphQL 解析函数的 Context 中,因此可以使用识别登录用户所需的任何内容。

我有一个 GraphQL 查询,可以像这样检索公共用户:

query getUserById($id: ID!) {
  getUserById(id: $id) {
    id,
    username
  }
}

我正在尝试考虑检索公共用户或私人用户的正确实现。由于 GraphQL 是强类型的,我在想出一个合适的解决方案时遇到了一些麻烦。

问题
如何区分公共用户和私人用户?

注意事项

1.单独查询
因此,其中一种选择是对公共和私有字段进行单独查询:

公开查询

query getUserById($id: ID!) {
  getUserById(id: $id) {
    id,
    username
  }
}

私人查询

query getMe {
  getMe {
    id,
    username,
    email
  }
}

2。使用 GraphQL 接口
我遇到了this Medium article,它解释了如何使用 GraphQL 接口基于resolveType 函数返回不同的类型。所以我会这样做:

query getUser($id: ID!) {
   getUser(id: $id) {
     ... on UserPrivate {
       id,
       username
     }
     ... on UserPublic {
       id,
       username,
       email
     }
   }
}

我还没有找到合适的解决方案,我不确定我目前的任何考虑。

非常感谢任何帮助!

【问题讨论】:

    标签: node.js graphql access-control graphql-js role-based-access-control


    【解决方案1】:

    我认为您在这里缺少的是,在 GraphQL 中您通常希望创建这种深度连接的图结构。虽然getUserByIdgetMe 作为入口点工作得很好(我认为即使使用接口类型它们仍然是一个好主意),您很可能会在您的架构中出现用户类型。想象一下流行的博客文章示例:

    type Post {
      id: ID!
      title: String!
      content: String!
      author: User!
    }
    

    在这里添加两个作者字段并不是很好。同样,在您的示例中,您可能不知道个人资料页面是您自己的,直到您从后端获得响应(想想 twitter 个人资料)。

    相反,我认为有两种方法可以考虑:

    第一个是界面的想法。您将拥有一个接口,其中包含私有和公共类型的所有公共字段和具体实现。这里的好处是:如果您只使用公共字段,您甚至不必使用类型匹配:

    query getUser($id: ID!) {
       getUser(id: $id) {
         id
         username
    
         # if you need a private field you can branch off here
         ... on UserPrivate {
           email
         }
       }
    }
    

    当它变得更细粒度(人们分享他们想向公众公开的内容,想象一下 Facebook)或者您有很多类型(UserMe、UserFriend、UserStranger)时,您可能需要考虑可空字段。如果您无权访问该字段,您将从 API 收到 null。为了减少 null 检查的数量,您可以轻松地将字段捆绑到它们自己的类型中(例如 Address)。

    总结:

    从 API 角度来看,返回可为空的字段会更容易一些,因为它为您提供了很大的灵活性。在不破坏更改的情况下发展第二个选项比第一个选项容易得多。如果您使用静态类型(Typescript、Flow、Scala.js、Reason 等),则在前端使用接口更具表现力,而且肯定更有趣。关键字:模式匹配。

    【讨论】:

    • 谢谢你,这很有帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-04
    • 2018-03-17
    • 2017-12-09
    • 2010-11-19
    • 2010-09-29
    相关资源
    最近更新 更多