我想让用户有权更新文档。但仅限用户更新此文档的一个特定字段。此用户不应更改所有其他字段。
这可以在firestore中使用吗?
我试过这样的事情:
function isUpdateToOpenField(attr) {
return attr == get(/databases/$(database)/documents/stores/$(store)).data.open;
}
allow update: if isUpdateToOpenField(request.resource.data);
但我不知道如何比较更新是否与正确的字段相对应。
答案 0 :(得分:24)
引入了“规则”语言中的地图差异来解决此问题:
function isUpdateToOpenField() {
return request.resource.data.diff(resource.data).affectedKeys().hasOnly(['open']);
}
allow update: if isUpdateToOpenField(request.resource.data);
答案 1 :(得分:16)
更新:Firestore不再支持writeFields
,最终将删除其功能。请参阅此post。
查看writeFields
变量以获取安全规则:
allow update: if ((request.writeFields.size() == 1) && ('open' in request.writeFields));
答案 2 :(得分:3)
由于writeFields已被弃用并且不应使用,因此您必须检查request.resource.data
。但是,它始终包含书面文档的所有字段(最终状态)。这意味着您必须将书面文档的所有字段与resource.data
中原始文档的字段进行比较,以确保只有那些更改的内容才是允许您更改的内容。
当前,这需要对可能写入的每个字段进行显式检查,实现起来并不容易。 Firebase团队正在研究通过允许您区分“之前”和“之后”文档的数据映射来使这种规则更易于表达的方法。
答案 3 :(得分:1)
您可以使用:
allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(["fieldToBeUpdated"]);
OR
allow update: if request.resource.data.diff(resource.data).affectedKeys() == ["fieldToBeUpdated"].toSet;
您可以根据自己的用例将affectedKeys()
替换为addedKeys()
,removedKeys()
或changedKeys()
。
affectedKeys()
等同于将这三者结合使用。
有关更多详细信息,请在https://firebase.google.com/docs/reference/rules/rules.MapDiff
中阅读文档答案 4 :(得分:0)
由于request.resource.data
将在写入后显示将来的对象-唯一的方法是使用以下命令检查每个字段:
function notUpdating(field) {
return !(field in request.resource.data)
|| resource.data[field] == request.resource.data[field]
}
allow update: if notUpdating('title') && notUpdating('description')
确保您确认用户未更新除您希望他有权访问的字段以外的所有其他字段
答案 5 :(得分:0)
“斯科特·克罗斯(Scott Crossen)”的相同答案,几乎没有变化,但更加通用化
function isUpdateToOpenField(attr) {
return request.resource.data.diff(resource.data).affectedKeys().hasOnly([attr]);
}
allow update: if isUpdateToOpenField('open');