firestore security rules get value of dynamic key?

shm*_*les 3 firebase-security google-cloud-firestore

document structure:

{
    [id 1] {
        field1: "value",
        field2: "value",
        field3: "value"
    }
    [id 2] {
        field1: "value",
        field2: "value",
        field3: "value"
    }
    [id 3] {
        field1: "value",
        field2: "value",
        field3: "value"
    }
}
Run Code Online (Sandbox Code Playgroud)

the map ids reference documents and cannot be hardcoded, but field names (field1, field2...), are the same in each map

is there a way to check that only 1 field in any 1 map is changed, and allow write if those conditions are met?

Big*_*day 5

为了将所有验证逻辑保留在 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' }
});
Run Code Online (Sandbox Code Playgroud)

然后,在 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();
Run Code Online (Sandbox Code Playgroud)

如您所见,我使用metaID变量来动态访问对象的键。

这种方法的优点是 (1) 所有验证逻辑都在 Firebase 中,(2) 它比执行云函数要快得多(因为您只是直接与 Firestore 通信)。

但是,这种方法的缺点是您将让这个meta对象漂浮在每个人身上都可以看到。最重要的是,我将添加更多验证以确保meta对象本身仅具有正确格式的必需数据。我强烈建议彻底测试所有可能的场景。