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
)"
}
}
}
换句话说:任何经过身份验证的用户都可以添加或删除乐队,只有管理员可以修改乐队。
我觉得这是一个很常见的问题,但由于我一直在学习 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
)"
}
}
}
换句话说:任何经过身份验证的用户都可以添加或删除乐队,只有管理员可以修改乐队。