【问题标题】:Reference field in nested map in Firestore security rulesFirestore 安全规则中嵌套映射中的引用字段
【发布时间】:2021-02-02 14:24:05
【问题描述】:

我有这个数据结构:

并且需要一个仅在city 属性未更改时才允许更新的规则:

match /requests/{requestId} {
  allow update: if (request.resource.data.diff(resource.data).unchangedKeys().
     hasAll(["customerlocation.city"]))

这不起作用,因为diff 结果只显示customerlocation 字段,而不显示city 属性。

是否有可能实现我想要的?我知道您可以对安全规则中的嵌套对象执行的操作存在限制,但我可能只是遗漏了一些东西。

【问题讨论】:

  • 您应该能够获得customerLocation 的密钥,但我不确定我是否了解您的文档是什么样的。您可以在问题中添加文档的屏幕截图吗?

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


【解决方案1】:

如果您不想更改数据结构并且必须在 Firestore 规则中执行此操作,我相信 Aion 提出的解决方案是唯一可行的解​​决方案。

我不知道您的整体数据结构是什么样的,但您可以将customerLocation 移到它自己的集合中。然后,您将在 request 内存储一个 DocumentReference 到 customerLocation

您还可以使用document('requests/{requestId}').onUpdate() 创建一个云功能并检查城市是否发生了变化。如果有,则将其更改回那里。这将要求您跟踪您更改回属性的事实。否则,该函数将继续触发和翻转值。

【讨论】:

    【解决方案2】:

    为什么不直接比较字段值呢?

    allow update: if request.resource.data.customerLocation.city
     != resource.data.customerLocation.city;
    

    【讨论】:

    • 因为可维护性。最初的问题是一个更复杂的规则的简化,它考虑了更多的属性。从技术上讲,您的建议应该可行,但维护它将是一场噩梦。
    【解决方案3】:

    我只是建议您检查一下 City 是否仍在其默认值中,在此示例中,我将其设为“默认城市”(该默认值可能为 nil)

    match /requests/{requestID} {
      allow update: if request.resource.customerLocation.city == "Default City"
    }
    

    由于您的整个 Firestore 数据库没有被引用,它在您的项目中可能看起来略有不同,但我认为从逻辑上讲这会起作用。

    【讨论】:

    • 如果不设置默认值,我认为您无法做到这一点。难道你不能在文档中添加一个标志来查看某个字段是否已被编辑,如果它已被“更改”?这比在城市中设置默认值更容易,因为用户可能会看到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多