文档结构:
{
[id 1] {
field1: "value",
field2: "value",
field3: "value"
}
[id 2] {
field1: "value",
field2: "value",
field3: "value"
}
[id 3] {
field1: "value",
field2: "value",
field3: "value"
}
}
地图ID参考文档,不能进行硬编码,但是每个地图中的字段名称(field1,field2 ...)都是相同的
有没有一种方法可以检查任何1个映射中只有1个字段被更改,并在满足这些条件的情况下允许写操作?
答案 0 :(得分:1)
安全规则不够灵活,无法满足您的要求。这需要循环和赋值,而这两种语言都不可用。我建议改为使用后端从客户端收集数据,然后检查其是否有效。
答案 1 :(得分:1)
为了将所有验证逻辑保留在Firestore中,您可以使用的一个技巧是为写入请求增加冗余。例如,您可以从客户端发送以下数据:
firestore.collection('A').doc('B').update({
'your_id_here': {
field1: 'my new value',
// keep old data, since we are updating a nested object
field2: 'original value',
field3: 'original value'
},
// this is the redundancy component
meta: { id: 'your_id_here' }
});
然后,在您的Firestore规则中,可以如下定义写入规则:
function valid() {
// grab ID from "redundant" part of the request
let metaID = request.resource.data.meta.id;
// grab changed keys in the root of the document
let rootAftectedKeys = request.resource.data.diff(resource.data).affectedKeys();
// validate root keys; need to include "meta", since it is now also part of the object
let rootChangesGood = rootAffectedKeys.hasOnly([metaID, 'meta']);
// grab the nested object in question
let nestedObjectChanges = request.resource.data[metaID].diff(resource.data[metaID]).affectedKeys();
// check there was only one affected key
let nestedObjectChangesGood = nestedObjectChanges.size() == 1;
return rootChangesGood && nestedObjectChangesGood;
}
allow write: if valid();
如您所见,我正在使用metaID
变量来动态访问对象的键。
此方法的优点是(1)所有验证逻辑都在Firebase中,并且(2)比执行云功能要快得多(因为您仅直接与Firestore通信)。
这种方法的缺点是,您将拥有这个meta
对象,每个人都可以看到。最重要的是,我将添加更多验证,以确保meta
对象本身仅具有正确格式的必需数据。我强烈建议彻底测试所有可能的情况。