如何在读取父列表时约束子属性

时间:2017-10-03 08:10:09

标签: firebase firebase-realtime-database

我有以下数据库架构:

{
    "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"
                        }
                    }
                }
            }
        }
    }
}

有效,因为当我阅读事件列表时,它不会尊重.readparticipants字段中的$participantKey约束。它只是一直检索完整的参与者名单。

@ 修改

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

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

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

但是,当我.read删除 events标记时,检索数据会在.read中显示participants标记。

@的 EDIT2

来自documentation

  

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

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

2 个答案:

答案 0 :(得分:1)

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

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

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

Firebase会忽略".read": false

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

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

因此,您有两个顶级列表:eventseventparticipants。列表对其下的对象使用相同的键:事件ID。但由于这些是两个顶级列表,一个可以公开阅读而另一个更受限制。

答案 1 :(得分:0)

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

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

由于Firebase是一个NoSQL数据库,并且因为它的结构是密钥和valeu对,因此解决方案是使用Map而不是数组。更改在数据库中添加数据的方式,您的问题就会得到解决。