所以我有一个查询(失败)。内容如下:“作为用户,我可以列出组织中属于我的所有业务。”
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如何正确验证子集合的约束?
答案 0 :(得分:1)
安全规则不会满足您的要求,因为它涉及读取与查询匹配的每个文档的另一个文档。规则无法提前知道这些文档将是什么,因为路径中有变量(businessId
)。如果此查询将产生数以百万计的业务集合文档,您将看到从/businesses/$(businessId)/users/$(request.auth)中读取每个匹配的文档将是有问题的(对您而言是昂贵的) .uid)来确定是否应拒绝整个查询。
规则必须以极快的速度运行,以便按照Firestore的扩展方式进行扩展。规则不能成为过滤器的限制是对可伸缩性的要求的一部分。这也是每个规则评估最多只能读取get()
的10个文档的原因。
从规则的角度来看,这里没有解决方法,只能执行多个查询,每个查询都在每个集合的规则范围内,然后将结果合并到客户端应用中。