【问题标题】:What is MapDiff in Cloud Firestore Security Rules? [closed]Cloud Firestore 安全规则中的 MapDiff 是什么? [关闭]
【发布时间】:2020-03-09 19:34:29
【问题描述】:

我听说 Cloud Firestore 安全规则中有一个新的 MapDiff 功能。

我想用它来更有效地解决problem described here,即避免写出以下内容:

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;

过去,writeFields 存在,但它们是unsupported now

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

【问题讨论】:

  • 您没有回答您链接到的其他问题的任何原因?这在技术上是一个骗局,已经被问过好几次了。
  • @DougStevenson 我为此使用 StackOverflow,就我而言,这也是鼓励的:stackoverflow.blog/2011/07/01/…
  • 问题不在于您在回答自己的问题。我也这样做。问题是这个问题相当广泛,而一篇博客文章可能是这类广泛主题的更好工具。如果你问我,你甚至可以通过中等帖子赚钱,这比 SO 点要好。
  • @PeterHaddad 今天,在我完成的最后三个帖子中,我每月赚取超过 60 美元。总体而言,对于教程等冗长的内容来说,它是一个更好的工具。 Stack Overflow 适用于对特定问题的相对简短的回答。这篇文章中的问题不是很具体:“我一般如何使用 MapDiff”.
  • FWIW,我强烈不同意@DougStevenson。我总是将媒体视为随机质量内容,没有时间检查每个作者的简历。如果谷歌搜索得到一个 SO 答案,它大多数时候会回答我的问题,或者会包含有用的信息来缩小我的搜索范围,或者给我关于我应该寻找什么的新指针。我也觉得OP的回答比这个话题的官方文档(firebase.google.com/docs/firestore/security/rules-fields)更简洁易读易懂

标签: firebase google-cloud-firestore firebase-security


【解决方案1】:

TL;DR

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

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!

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;

变成just:

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

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

addedKeys

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

{'cakes': 1}.diff({}).addedKeys() == ['cakes'].toSet() // true

removedKeys

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

{}.diff({'cakes': 1}).removedKeys() == ['cakes'].toSet() // true

changedKeys

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

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

只要两个集合中的值相等,就会发生变化。

unchangedKeys

MapDiff.unchangedKeysMapDiff.changedKeys 的反义词,它返回一组在两个映射之间更改的所有键,即所有具有 相等 值的键:

{'cakes': 0}.diff({'cakes': 0}).unchangedKeys() == ['cakes'].toSet() // true

【讨论】:

  • 感谢清晰的解释!我想知道当比较的地图深度嵌套时,这些方法的行为是什么?例如如果我这样做 { 'level1': { 'level2': 0 } }.diff({ 'level1': { 'level2': 1 } }).affectedKeys()affectedKeys 会返回任何东西吗? // 期望返回 ['level1']
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-05
  • 2018-07-23
  • 2021-04-21
  • 2020-11-27
  • 2021-11-22
相关资源
最近更新 更多