我认为update()
功能中的错误可能是Firebase中特定使用规则的错误。
我对profile
节点有以下规则:
"profile": {
"$appUserId": {
".read": "auth.uid !== null",
".write": "!newData.child('photo').exists()"
}
}
(为了清楚起见,我在.write
规则中省略了身份验证)
用户profile
包含photo
,但只能通过后端进行更新。客户无法设置此信息。
我使用update()
功能设置个人资料数据。当我创建一个配置文件(新节点)时,一切正常。但是,每个update()
使用PERMISSION_DENIED调用结果创建配置文件。如果我在一个呼叫中更新一个字段或多个字段并不重要。当然,传入对象中没有photo
个键。此外,set()
函数在相同条件下完美运行(但删除任何其他字段 - 包括photo
)。
当我删除.write
规则(并且只是保持身份验证)时,它正在运行。所以我开始疑惑。对我来说,它似乎在update()
调用期间内部读取现有数据,将其与传入数据合并,用新值覆盖旧值,然后尝试将其全部保存。在它实际保存数据之前,有一个规则检查,所以 - 此时 - 它将导致错误。我想它应该在数据合并之前进行规则检查(假设它像我上面描述的那样工作)。
修改
重现问题:
1)设置代码:
var appId = 'APP ID', appUserIdKey = 'test'; //appUserIdKey can be whatever you want
//data to be saved
var profileData = {
name: "Pawel"
age: 31,
photo: 'image.jpg'
};
2)由于在我的环境中只有后端使用服务密钥将数据保存到profile/[appUserIdKey]/photo
,因此您必须暂时删除.write
规则。
现在规则应该是:
"profile": {
"$appUserId": {
".read": "auth.uid !== null",
".write": "auth.uid !== null"
}
}
3)运行代码以创建配置文件
var ref = new Firebase('https://'+appId+'.firebaseio.com/profile/' + appUserIdKey);
ref.update(profileData);
4)现在,恢复规则。
"profile": {
"$appUserId": {
".read": "auth.uid !== null",
".write": "(auth.uid !== null) && (!newData.child('photo').exists())"
}
}
5)尝试再次更新个人资料:
var ref = new Firebase('https://'+appId+'.firebaseio.com/profile/' + appUserIdKey);
ref.update({'age':18});
您将收到错误
6)将规则更改为以下内容:
"profile": {
"$appUserId": {
".read": "auth.uid !== null",
".write": "(auth.uid !== null) && (!newData.child('photo').exists()) || newData.child('photo').val() == data.child('photo').val())"
}
}
现在有效。
答案 0 :(得分:3)
答案 1 :(得分:0)
解决方法是扩展规则,以便在旧值等于新值时返回true:
"profile": {
"$appUserId": {
".read": "auth.uid !== null",
".write": "(!newData.child('photo').exists() || newData.child('photo').val() == data.child('photo').val())"
}
}
但是,我认为它不应该像这样工作,应该改变。