Reputation: 565
I have a firestore with a collection called "children" and a subcollection called events. The children documents have an array called "caretakers" which contains the authids for users that should have access to this document. My question is, what is the right way to secure the subcollection. I am currently doing the following:
match /children/{childId} {
allow read, write, delete, list:
if request.auth.uid in resource.data.caretakers;
allow create:
if true;
}
match /children/{childId}/events/{eventId} {
allow read,write,delete,get:
if request.auth.uid in get(/databases/$(database)/documents/children/$(childId)).data.caretakers
}
Something about that get(...) doesn't feel right to me. Is that necessary? Do I really need to specify rules separately for each subcollection? or if the parent document has permissions.. those permissions should cascade down to subcollections?
Upvotes: 1
Views: 1558
Reputation: 565
I'm answering my own question to note what I ended up going with as a solution.
In my case, the number of Users that have access to each {childId} is very low. Therefore, I ended up storing custom claims in the Users Auth object. Basically stored an array of {childId} in the Users auth object instead of storing a bunch of userIds into the Child object.
This allows me to do a direct check to see if the {childId} exists in the users auth object and saves me extra reads of data.
Upvotes: 0
Reputation: 598688
With your current structure unfortunately you will indeed need to read the parent document to check against its caretakers
role for each subdocument. What's even worse is that this makes queries impossible, as you can't read from the parent document when querying events
.
The common workaround for this is to duplicate the caretakers
into each events
document, so that you can query for it there, and the rules can then secure that only that query is allowed.
Upvotes: 2
Reputation: 50830
Yes you need to explicitly define rules for sub-collections. You can nest the sub-collection's rule in that collection itself to structure it.
Security rules apply only at the matched path, so the access controls defined on the [children] collection do not apply to the [events] subcollection
service cloud.firestore {
match /databases/{database}/documents {
match /children/{childId} {
allow read, write, delete, list: if request.auth.uid in resource.data.caretakers;
allow create: if true;
// These rule will apply for docs in children collection only
// Explicitly define rules for the 'events' subcollection
match /events/{eventId} {
allow read,write,delete,get: if request.auth.uid in get(/databases/$(database)/documents/children/$(childId)).data.caretakers
// This rule will apply for docs in events sub-collections only
}
}
}
}
You can read more about this at: How security rules work?
Upvotes: 2