'Firebase Firestore Rules for Large Teams with low read count
I'm trying to create a SaaS platform where customers can create organizations and invite other users to their organizations.
At the moment I have these 4/5 collections:
- Users
- Organizations
-
- (Team Members)
-
- Domains
-
- Uptime
The problem I'm facing when querying client-side is that I get insufficient permissions because my queries "potentially include documents that violate my security rules".
For Organizations then there is a simple solution, create a "members" field in each document that contain user uid's and then do allow read: if request.auth.uid in resource.data.members. Although I don't like this solution because (1) it doesn't say anything about read/create/update/delete permissions, and (2) I can't keep track of all (future) team members on each document inside the domain and uptime (sub)collections so I have no idea how I could then query those (sub)collections.
I tried to attach some custom tokens (my thought was that I could perform the same permission check on the subcollections if I did like this) and then say, e.g.
match /organizations/{organization} {
allow read: if organization in request.auth.token.organizations;
}
But that doesn't work, I also tried to create custom tokens where token key included organization id and value included read/create/update/delete permissions, but it was also unsuccessful due to same insufficient permissions error.
I would really appreciate if someone could help guide me towards the right solution, ideally one that doesn't result in extra "reads" to check permission, because I plan to load many documents at the same time and watch for live changes so that the organization's team members can easily modify the same domain/uptime documents without worrying that they're overwriting each others work.
Edit: Code examples of my attempts (I didn't run multiple "allow read" on the same collection, just to show the things I remember trying):
const { request } = require("http");
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// this works when I do queries like: query(collection(db, 'organizations'), where('members', 'array-contains', uid))
match /organizations/{document=**} {
allow read: if request.auth.uid in resource.data.members; // works
// however, if I try to query subcollections then I cannot do the same, e.g.
match /domains/{documents=**} {
// this of course doesn't work unless I store "members" inside the "domains" subcollection which is not an option
allow read: if request.auth.uid in resource.data.members; // insufficient permissions
}
}
// based on the above problem with querying subcollections, then I tried the following
// (I use same where members query as above)
match /organizations/{organization} {
allow read: if request.auth.uid in organization.members; // insufficient permissions
allow read: if organization in request.auth.token.organizations; // insufficient permissions
// if it worked, then my plan was to do something similar to this:
match /domains/{document=**} {
allow read: if organization in request.auth.token.organizations; // insufficient permissions
// or perhaps something like this (although I have no idea how to inject document ID into the request.auth.token key):
allow read: if 'read-role' in request.auth.token.{organization}.roles; // insufficient permissions
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
