【问题标题】:Firestore: Access documents in collection user has permission toFirestore:访问集合中的文档用户有权
【发布时间】:2019-05-24 16:00:02
【问题描述】:

我有一个名为公告的集合,用于存储数据。但是,每个文档都有一个名为“permissions”的字段,其中包含一个权限级别字符串。我编写了函数来根据用户的权限级别和资源的权限级别确定用户是否具有访问权限。

当我为应该工作的单个文档设置 onSnapshot 回调时,我得到了响应。一旦我将它切换到获取集合的快照,它就会得到一个无效的权限错误。根据我的发现,如果用户有可能无法访问集合中的任何文档,firestore 就会失败。我应该使用什么型号?如何获取用户也应该有权访问的文档?

规则

match /chapters/{chapter} {
        function isMember() {
          return exists(/databases/$(database)/documents/chapters/$(chapter)/members/$(request.auth.uid))
      }

      function getUser() {
        return get(/databases/$(database)/documents/chapters/$(chapter)/members/$(request.auth.uid))
      }

      function hasPermission(userPermission, documentPermission) {
        return documentPermission == "all" || userPermission == "admin" || userPermission == documentPermission
      }

        allow read: if isMember()

      match /announcements/{announcement} {
        allow read: if isMember() && hasPermission(getUser().data.permissions, resource.data.permissions)
      }
}

作品vvv

firestore.collection("chapters").doc("chapter-1").collection("announcements").doc("doc1").onSnapshot(doc => {
                const announcements = doc.data()

                console.log(announcements)
        })

不工作vvv

 firestore.collection("chapters").doc("chapter-1").collection("announcements").onSnapshot(docs => {
            docs.forEach(doc => {
                const announcements = doc.data()

                console.log(announcements)
            })
        })

【问题讨论】:

    标签: javascript firebase google-cloud-firestore firebase-security


    【解决方案1】:

    这是因为在查询的情况下,规则不是过滤器

    正如doc中解释的那样,

    在编写查询以检索文档时,请记住安全性 规则不是过滤器——查询是全有或全无。

    您需要“编写查询以适应安全规则的约束”

    另一方面,

    此行为适用于检索一个或多个文档的查询 从一个集合而不是单个文档检索。当你 使用文档 ID 检索单个文档,Cloud Firestore 读取 文档并使用您的安全规则评估请求,以及 实际的文档属性。

    这就是当您使用

    仅查询一个文档时它起作用的原因

    firestore.collection("chapters").doc("chapter-1").collection("announcements").doc("doc1").onSnapshot()


    因此,要查询集合,您需要在查询中添加过滤器,如下所示:

    firestore.collection("chapters").doc("chapter-1").collection("announcements").where("permissions", "==", "xxxxx");
    

    【讨论】:

    • 谢谢,我需要这个细分。是否可以使用此 where 子句检查文档(parent_doc)是否在其子集合中具有另一个文档(child_doc)?
    • 不,不使用where() 方法,请参阅firebase.google.com/docs/reference/js/… ("'创建并返回一个带有附加过滤器的新查询,该过滤器文档必须包含指定的字段并且值应满足关系约束假如。”)。您可以在文档中添加一个额外的字段,该字段包含与子文档相同的信息。
    • 请注意,观看有关 Firestore 安全规则的官方视频很有趣:youtube.com/watch?v=eW5MdE3ZcAw。在 14min20 你会看到与答案相对应的解释。
    • 有没有办法形成一个“where”子句来检查地图是否包含键?我知道这可以为数组完成,但我想(如果可能的话)存储键值对的映射,键是用户的 id,值是具有一些详细信息的对象。我将 array-contains 视为一个选项,但我不知道如何执行类似“members.keys() array-包含 "
    • @AustinE 你有没有找到问题的答案?我也想做类似的事情。
    猜你喜欢
    • 1970-01-01
    • 2022-01-05
    • 2019-08-16
    • 2018-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-22
    相关资源
    最近更新 更多