Firebase.update()对于原子更新多个节点非常有用。但是,它似乎有限,因为安全规则仍由update()
操作中的根节点定义。
例如,我们假设我的数据结构为:
users : {
uid : {account: accountId, ...},
...
},
accounts : {
accountId : {uid: uid, ....},
...
},
customers : {
customerId : {uid: uid, accountId: accountId...},
...
}
我的Firebase安全性组织为:
{
"rules": {
"users" : {
"$uid" : {
".read": "data.child('account').val() === root.child('users').child(auth.uid).child('account').val()",
".write": "data.child('account').val() === root.child('users').child(auth.uid).child('account').val()"
}
},
"accounts" : {
"$accountId” : {
".read": "data.child('users').child(auth.uid).exists() || newData.child('users').child(auth.uid).exists()",
".write": "data.child('users').child(auth.uid).exists() || newData.child('users').child(auth.uid).exists()"
}
},
“customers” : {
"$customerId” : {
".read": "root.child('users').child(auth.uid).child('account').val() == root.child('customers').child($customerId).child('account').val()",
".write": "root.child('users').child(auth.uid).child('account').val() == root.child('customers').child($customerId).child('account').val()"
}
}
}
要跨这些节点对给定的businessId进行原子更新,我可以进行update()
调用:
firebaseRef.update({
accounts : {
accountId : { foo: bar },
},
customers : {
customerId : { foo: bar },
}
}
由于update()
应仅修改指定的位置,因此可以应用逐节点安全规则(例如,使用uid
)。但是,似乎根安全性(例如/
)占优势,我收到了警告:
FIREBASE WARNING: update at / failed: permission_denied
所以现在我使用promise链来使用set()
按顺序更新不同的节点,这意味着我将失去原子操作。
是否有更好的方法可以跨多个节点进行原子操作而无需打开root的安全性?
答案 0 :(得分:0)
在您的安全规则中,root
指的是根目录中的当前/旧数据。如果要在根目录中访问新数据,则必须从newData
:
".read": "newData.parent().parent().child('businessDta')...
我们的Bolt语言有一个特殊的快捷方式,当您使用root
时,它实际上会为您生成必要的newData.parent().parent()...
来电。
答案 1 :(得分:0)
我遇到过这个问题,我通过修复更新中每个路径的安全规则来解决这个问题。事实证明SDK适用于update()
和安全规则。
对于您的情况,您可能需要仔细检查/accounts/accountId
和/customers/customerId
的安全规则是否适用于您的update()
电话。您可以通过将更新分成原始set()
调用来调试此操作,以测试每个更新路径是否正在使用规则。
但是,我认为您可能在“/ accounts / $ accountId”规则中输入错字。您可能需要root.child("users")
代替data.child("users")