Firestore安全规则:如何限制使用get(<document_path>)的查询?

时间:2020-09-25 09:33:05

标签: google-cloud-firestore firebase-security

所以我有一个查询(失败)。内容如下:“作为用户,我可以列出组织中属于我的所有业务。”

fs
    .collection('businesses')
    .where('organizationUid', isEqualTo: 'some-organization-id')
    .get();

以及保护它的要点的安全规则:

match /businesses/{businessId} {
  function isStaffOrHigher() {
    return get(/databases/$(database)/documents/businesses/$(businessId)/users/$(request.auth.uid)).data.role >= 50;
  }

  allow read: if isStaffOrHigher();

  match /orders/{orderId} {
    allow read, write: if isStaffOrHigher();
  }

  match /users/{userId} {
    allow read: if request.auth.uid == userId || isStaffOrHigher();
  }
}

基本上,它在用户文档(由该企业拥有)中查找用户的角色。这种类型的规则(使用get()运算符)适用于orders的子集合(例如,查询{businessId}没问题),但是不适用于试图列出列表的规则。业务。

现在,我知道organizationUid是有效的约束条件,但是在阅读了Rules are not filters之后,我可以理解为什么Firestore如果不读取大量数据就无法验证此声明。

问题是,那么我该如何解决? Firestore如何正确验证子集合的约束?

1 个答案:

答案 0 :(得分:1)

安全规则不会满足您的要求,因为它涉及读取与查询匹配的每个文档的另一个文档。规则无法提前知道这些文档将是什么,因为路径中有变量(businessId)。如果此查询将产生数以百万计的业务集合文档,您将看到从/businesses/$(businessId)/users/$(request.auth)中读取每个匹配的文档将是有问题的(对您而言是昂贵的) .uid)来确定是否应拒绝整个查询。

规则必须以极快的速度运行,以便按照Firestore的扩展方式进行扩展。规则不能成为过滤器的限制是对可伸缩性的要求的一部分。这也是每个规则评估最多只能读取get()的10个文档的原因。

从规则的角度来看,这里没有解决方法,只能执行多个查询,每个查询都在每个集合的规则范围内,然后将结果合并到客户端应用中。