GraphQL - 如何区分公共领域和私有领域?

时间:2018-03-07 08:55:38

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

上下文
我有一个GraphQL API和一个NodeJS&使用包含用户的MongoDB数据库的Angular应用程序。对于每个用户,都有一个公共页面,其中包含function openResources(e, resourceName) { $('.resources__all-tabs-container').each(function() { $(this).hide(); }) $('.resources__tabs').each(function() { $(this).removeClass('.resources__tabs'); }) $('#'+resourceName).show(); $(e.target).addClass('resources__all-tabs'); } id等公共信息。当用户登录时,会有一个包含username等扩展信息的私人资料页面。

仅针对上下文,我使用jsonwebtokenaccesscontrol对用户进行身份验证和授权。该信息存储在每个GraphQL解析函数的上下文中,因此无需识别登录用户所需的任何信息。

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

email

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

问题
如何实现公共和私人用户之间的区别?

注意事项

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

公开查询

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

私人查询

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

2。使用GraphQL接口
我遇到了this Medium article,它解释了如何使用GraphQL接口根据query getMe { getMe { id, username, email } } 函数返回不同的类型。所以我会这样做:

resolveType

我没有找到适当的解决方案,而且我对目前的任何一个考虑都不确定。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

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

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

在这里添加两个作者字段并不是很有效。同样在您的示例中,您可能不知道配置文件页面是您自己的,直到您从后端获得响应(想想推特配置文件)。

相反,我认为有两种方法需要考虑:

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

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收到空值。要减少空值检查的数量,您可以轻松地将字段捆绑到各自的类型中(例如Address)。

<强>要点:

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