firestore安全规则获取动态密钥的值



文档结构:

{
[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参考文档,不能硬编码,但字段名称(字段1、字段2…(在每个地图中都是相同的

有没有一种方法可以检查任何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对象本身只有正确格式的所需数据。我强烈建议彻底测试所有可能的场景。

安全规则不够灵活,无法满足您的要求。这需要循环和赋值,这两种语言都不可用。我建议使用后端从客户端收集数据,然后检查它是否有效。

最新更新