Firebase 安全 - 如何允许推送到节点并更新该节点上的子树?

Firebase Security - How to allow to push to a node AND update subtree on that node?

我觉得这是一个很常见的问题,但由于我一直在学习 Firebase 安全性,我似乎仍然无法破解这个小问题,我有一个树节点,我希望能够推送新的数据,同时能够更新现有节点。根据 Firebase 文档,如果您将这些规则放在顶级树中,您应该能够 create/delete,但不能更新:

".write": "!data.exists() || !newData.exists()"

因此,当我使用带有身份验证和所有功能的 Firebase 数据库模拟器时,我会在路径 /social/bands 上模拟一个 "write",但是我得到一个 Simulated write denied。我应该注意到,在这个路径中,数据确实存在。

此示例的完整规则如下:

"social": {
   "bands": {
     ".read": "auth != null",
     ".write": "!data.exists() || !newData.exists() && auth != null",
     "$bandId": {
        ".write": "auth != null && data.child('admins').child(auth.uid).val() === true"
     }
   }
}

有没有办法能够 create/delete 我的 /social/bands 树上的节点,同时能够像 /social/bands/$bandId 这样存在的节点,无论数据是否存在于小路?我觉得这是经常发生的事情。

我应该注意到,我正在尝试在 Ionic 3 应用程序的上下文中实现这些规则,利用 AngularFire,如果这应该有任何不同的话(我不相信它会,因为模拟器给我权限错误)。

更新:这是模拟器失败的截图:

这是我要在模拟器中写入的数据

{
  "admins" : {
    "ruNdZP2Gx6bqsovL8gMlLJP9g0a2" : true
  },
  "creator_id" : "ruNdZP2Gx6bqsovL8gMlLJP9g0a2",
  "followers" : 2,
  "genres" : [ "Classical" ],
  "looking_for_musicians" : true,
  "members" : {
    "ruNdZP2Gx6bqsovL8gMlLJP9g0a2" : true
  },
  "name" : "Radiant and the beach",
  "social_profiles" : {
    "soundcloud" : ""
  }
}

我要写入的路径是/social/bands

模拟器中的认证状态如下:

这是树中的现有数据,其中一个节点已展开:

而错误消息只是我之前提到的 Simulator write denied 问题。

有没有想过我做错了什么?

您正在尝试写入 /social/bands。在该级别上,您有一个规则 !data.exists()/social/bands下已经有数据,比如名为My Awesome Band的乐队。由于数据已经存在,!data.exists() 的计算结果为 false,写入被拒绝。

如果您希望用户能够添加新的频段,您应该将该规则下移到 JSON 中特定频段的级别:

"social": {
   "bands": {
     ".read": "auth != null",
     "$bandId": {
        ".write": "auth != null && (
          !data.exists() || !newData.exists() ||
          data.child('admins').child(auth.uid).val() === true
        )"
     }
   }
}

换句话说:任何经过身份验证的用户都可以添加或删除乐队,只有管理员可以修改乐队。