get() 和 getAfter() 之间的 Firebase 安全规则差异

Pan*_*rld 3 firebase firebase-security google-cloud-firestore

在文档中,它说:

使用 get() 和 exists() 函数,您的安全规则可以针对数据库中的其他文档评估传入请求。

这对我来说没问题,这个例子对我来说很有意义:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before allowing any writes to the 'cities' collection
      allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但是然后它说

对于写入,您可以使用 getAfter() 函数在事务或批量写入完成之后但在事务或批量提交之前访问文档的状态。

我可能还没有完全理解这个概念。我的问题是:

  1. 为什么事务或批量写入必须专门使用getAfter(),我们可以只使用get()吗?
  2. 如果您必须使用 getAfter() 进行事务或批量写入,是否意味着您仍然需要 get() 进行正常写入?它们是如何同时存在的?

谢谢。

Dou*_*son 7

首先,请记住,在数据库中的任何内容被该写入更改之前,写入的安全规则就会生效。这就是安全规则如何能够安全有效地拒绝访问,而不必回滚任何已经发生的写入。

您引用的文档表明 getAfter 可用于在记录整个事务的状态之后(在内存中的某种“暂存”环境中)检查数据库的内容,但在事务实际更改数据库之前,对数据库可见每个人。这与 不同get,因为get在最终提交事务之前只查看数据库的实际内容。简而言之,getAfter使用整个事务或批处理的整个分阶段写入,同时get使用数据库的实际现有内容。

getAfter如果get适用于您的情况,您绝对没有义务使用。

getAfter当您需要检查交易或批次中可能已更改的其他文档,并且仍有机会因规则失败而拒绝整个交易或批次时,此功能很有用。因此,例如,如果在单个事务中写入的两个文档必须具有一些共同的字段值才能保持一致,则需要使用getAfter来验证两者之间的相等性。 get在这里不会有帮助,因为它对交易中尚未写入的其他文档一无所知。

另一方面,如果您的规则需要检查事务中的文档是否未更改现有文档中的字段(即不是当前正在检查的文档),get则需要在写入之前获取该值通过交易。