Cloud Firestore 安全规则中的 MapDiff 是什么?

cre*_*not 3 firebase firebase-security google-cloud-firestore

我听说MapDiffCloud Firestore 安全规则中有一项新功能。

我想用它来更有效地解决这里描述问题,即避免必须写出以下内容:

allow update: if request.resource.data.size() == 6
              && request.resource.data.likes == resource.data.likes
              && request.resource.data.name == resource.data.name
              && request.resource.data.date == resource.data.date
              && request.resource.data.body == resource.data.body
              && request.resource.data.title == resource.data.title
              && request.resource.data.cakes is int;
Run Code Online (Sandbox Code Playgroud)

过去,writeFields存在,但现在不支持

我怎样才能有效地(关于代码简洁性)检查是否只有一个字段被更改和使用MapDiff

cre*_*not 10

TL; 博士

allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(['cakes'])
              && request.resource.data.cakes is int;
Run Code Online (Sandbox Code Playgroud)

MapDiff 解释

rules.MapDiff是最近添加到 Cloud Firestore 安全规则的一项强大功能,是比较两个Map对象的有效方法。
由于request.resource.dataresource.data是地图,MapDiff因此非常适合。

Map.diff()

为了使用任何MapDiff功能,您首先必须调用diff您的地图。这很容易,看起来像这样:

request.resource.data.diff(resource.data) // Now you have a MapDiff object!
Run Code Online (Sandbox Code Playgroud)

affectedKeys

MapDiff.affectedKeys功能是最有用的,因为它结合addedKeysremovedKeyschangedKeys。这意味着这affectedKeys将解决原始问题中的问题。
这意味着所有:

allow update: if request.resource.data.size() == 6
              && request.resource.data.likes == resource.data.likes
              && request.resource.data.name == resource.data.name
              && request.resource.data.date == resource.data.date
              && request.resource.data.body == resource.data.body
              && request.resource.data.title == resource.data.title
              && request.resource.data.cakes is int;
Run Code Online (Sandbox Code Playgroud)

变成只是:

allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(['cakes'])
              && request.resource.data.cakes is int;
Run Code Online (Sandbox Code Playgroud)

因此affectedKeys返回rules.Set两个映射之间受影响的所有键中的一个,即添加、删除或更改。

addedKeys

这与工作方式相同affectedKeys,现在只返回一个添加了键的集合。

{'cakes': 1}.diff({}).addedKeys() == ['cakes'].toSet() // true
Run Code Online (Sandbox Code Playgroud)

removedKeys

MapDiff.removedKeysMapDiff.addedKeys并返回一组仅在两个映射之间删除的键:

{}.diff({'cakes': 1}).removedKeys() == ['cakes'].toSet() // true
Run Code Online (Sandbox Code Playgroud)

changedKeys

MapDiff.changedKeys返回Set在两个映射之间更改的所有键的一个:

{'cakes': 0}.diff({'cakes': 1, 'pies': 4}).changedKeys() == ['cakes'].toSet() //true
Run Code Online (Sandbox Code Playgroud)

每当两个集合中的值相等时,就会发生变化。

unchangedKeys

MapDiff.unchangedKeysMapDiff.changedKeys并返回两个映射之间更改的所有键的集合,即具有相同值的所有键:

{'cakes': 0}.diff({'cakes': 0}).unchangedKeys() == ['cakes'].toSet() // true
Run Code Online (Sandbox Code Playgroud)

  • 感谢您清晰的解释!我想知道当比较的映射深度嵌套时这些方法的行为是什么?例如,如果我执行 `{ 'level1': { 'level2': 0 } }.diff({ 'level1': { 'level2': 1 } }).affectedKeys()` ,`affectedKeys` 会返回任何内容吗?// 期望返回 `['level1']` (7认同)