So I have a query (that fails). It reads like this: "As I user I can list all the businesses, which I'm a part of, for an organization".
fs
.collection('businesses')
.where('organizationUid', isEqualTo: 'some-organization-id')
.get();
And a security rule to protect it (the gist of it):
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();
}
}
Basically it looks up the user's role in his user document (that is owned by that business). This type of rule (that uses the get()
operator) works for sub-collections (there's no problem querying orders
, for example) of {businessId}
, but not for queries that attempts to list the businesses.
Now I KNOW that the organizationUid
is a valid constraint, but having read Rules are not filters, I can understand why Firestore can't validate this claim without reading a ton of data.
The question is just, then how do I solve this? And how does Firestore validate the constraint for sub-collections correctly?