【问题标题】:How to constraint a child property when reading a parent list读取父列表时如何约束子属性
【发布时间】:2018-03-14 09:03:49
【问题描述】:

我有以下数据库架构:

{
    "events": {
        "$eventId": {
            "eventTitle": "Go shopping",
            "participants": {
                "0": {
                    "id": "0",
                    "name": "John Smith"
                },
                "1": {
                    "id": "1",
                    "name": "Jason Black"
                }
            }
        }
    }
}

这是一个事件数组,其中每个事件都有一个参与者列表。如何制定数据库规则,其中:

  • 每个人都可以获取事件或事件列表,
  • 获取活动时,参与者的完整列表只能由管理员查看,
  • 在获取事件时,如果用户是该事件的参与者,参与者列表将只检索他,而不是其他人,
  • 获取事件时,如果用户不是参与者,参与者列表将为空

这是我在规则方案中的尝试:

{
    "rules": {
        "events": {
            ".read": true,
            "$eventKey": {
                "eventTitle": {
                    ".validate": "newData.isString() && newData.val().length < 100"
                },
                "participants": {
                    ".read": "root.child('users/'+auth.uid+'/role').val() === 'ADMIN'",
                    ".validate": "newData.hasChildren()",
                    "$participantKey": {
                        ".read": "($participantKey === auth.uid || root.child('users/'+auth.uid+'/role').val() === 'ADMIN')",
                        "id": {
                            ".validate": "newData.val() === $participantKey"
                        },
                        "name": {
                            ".validate": "newData.isString() && newData.val().length < 100"
                        }
                    }
                }
            }
        }
    }
}

不起作用,因为当我阅读事件列表时,它不遵守 participants$participantKey 字段中的 .read 约束。它只是一直检索完整的参与者列表。

@编辑

换句话说。我有这个简化的规则:

{
    "events": {
        ".read": true,
        "$eventKey": {
            "participants": {
                ".read": false
            }
        }
    }
}

当我查询:events/{eventKey}/participants 时,即使 participants 读取标志设置为 false,我仍然会得到一个包含参与者的对象。

但是,当我从events 删除 .read 标志时,然后检索数据尊重participants 中的.read 标志。

@edit2

来自documentation

授予读取位置权限的 .read 规则也将允许读取该位置的任何后代,即使后代有自己的 .read 规则失败。

我现在的问题是,如何省略这条规则?

【问题讨论】:

    标签: firebase firebase-realtime-database


    【解决方案1】:

    Firebase permissions cascade 向下。一旦您在 JSON 树中的某个级别授予用户权限,您就无法在树中的较低级别撤消该权限。

    这意味着这些规则将不起作用:

    {
      "events": {
        ".read": true,
        "$eventKey": {
            "participants": {
                ".read": false
            }
        }
      }
    }
    

    ".read": false 被 Firebase 忽略。

    相反,您必须以符合您的安全要求的方式构建数据。这是通过完全分离具有不同安全要求的数据类型来实现的。

    {
      "events": {
        ".read": true,
        "$eventKey": {
            "participants": {
                ".read": false
            }
        }
      }
      "eventparticipants": {
        ".read": false
        "$eventKey": {
            /* This is where you store the participants */
        }
      }
    }
    

    所以你有两个顶级列表:eventseventparticipants。这些列表对它们下面的对象使用相同的键:事件 id。但由于这是两个顶级列表,一个可以公开阅读,而另一个则受到更多限制。

    【讨论】:

      【解决方案2】:

      Firebase 文档建议在向数据库添加数据时不要使用数组。您的代码中的主要问题是您使用了一个数组,这在 Firebase 中是一种反模式。

      Firebase 建议不要使用数组的众多原因之一是它使安全规则无法编写,这就是您的情况。

      因为 Firebase 是一个 NoSQL 数据库,并且它的结构是成对的键和值,所以解决方案是使用 Map不是一个数组。改变你在数据库中添加数据的方式,你的问题就会得到解决。

      【讨论】:

      • 当我在对象上使用set,而不是列表中的push 时,它仍然会列出所有内容
      • 好的,但您仍然无法编写安全规则,这正是您要查找的内容,对吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多