Reputation: 1046
I have a question regarding firestore rules.
I have a collection that holds documents... and these documents also have sub- collections.... and these documents also have subcollections.
e.g.
"Collection" -> "Document" -> "Sub-collection-1" -> "Document1" -> "Sub-collection-2" -> "Document2"
(i have changed the names to make it simpler to understand)
I have a 2 timestamps stored in the "Document" that are used to control when the user is able to read the document... e.g. it must be after the 'startTimestamp' but before the 'endTimestamp'.
My rules for this are as follows.
allow read: if request.auth.uid != null
&& int(resource.data.startReadTimestamp) < request.time.toMillis()
&& int(resource.data.endReadTimestamp) > request.time.toMillis()
My question is that if the user tries to read a sub-collection document, e.g. "Document1" or "Document2" and the time they request is invalid based on the timestamps in "Document" will this automatically reject because of the parent collection rule?
If not, I have seen that you can use the functions combined with get to access other documents but it seems wasteful as this will be charging me reads.
e.g. doing this
function getTopLevelDocData() {
return get(/databases/$(database)/documents/Collection/$(documentWildcard)).data
}
The only other method I can think of is writing the timestamps to each document in the sub collection... but this could be hard to keep track of.
Any help is appreciated :)
--- UPDATE
I just tried it and it does allow reads to "Document1" If i dont call the function that checks the "Document" timestamps in the "Document1" rules... Just to clarify will reading "Document1" or "Document2" be only 1 extra read as it will have to check the "Document" timestamps?
--- SECOND UPDATE
Imagine "Document" in the above example actually has the doc name "2020-08-29".
If I try to read "Document1" or "Document2" is there a firestore rule that will not incur any document reads but will still block reads where the request timestamp (after transformation) does not match the parent "Document" name, e.g. "2020-08-29"
for Example, would something like this work?
match /collection/{document}{
match /Sub-collection-1/{document1}{
function transfomRequestTimestampToDate(){
return request.time.year() + "-" + request.time.month() + request.time.day();
}
allow read if request.auth.uid != null && transfomRequestTimestampToDate() == {document}
}
}
Upvotes: 0
Views: 1670
Reputation: 83191
I just tried it and it does allow reads If i dont call the function...
You don't show to which collection(s) you apply the read
security rules shown in your question, but note that resource.data
points to the resource
you are trying to read, therefore if you don't have the corresponding fields in the subcollections docs, it will not work as such for these docs.
Will reading "Document1" or "Document2" be only 1 extra read as it will have to check the "Document" timestamps?
Yes, it will cont for one document read each time the security rule is evaluated.
Yes, by using the wildcard syntax, you can use the document ID of the parent to write the rules for the children, like, for example, as follows:
service cloud.firestore {
match /databases/{database}/documents {
match /Collection/{parentDocId} {
allow read: if parentDocId == '2020-08-29';
match /Subcollection1/{SubcollectionDoc} {
allow read: if parentDocId == '2020-08-29';
}
}
}
}
and if you want to make this dynamic, you could do as follows:
service cloud.firestore {
match /databases/{database}/documents {
match /a/{a} {
allow read: if a == string(request.time.year()) + "-" + string(request.time.month()) + "-" + string(request.time.day());
match /b/{b} {
allow read: if a == string(request.time.year()) + "-" + string(request.time.month()) + "-" + string(request.time.day());
}
}
}
}
However, note that string(request.time.day())
and string(request.time.month())
will return a string of one character for months before October, e.g. 8 for August or days before 10. It's up to you to deal with that, either by using YYYY-M-D or by fine tuning the security rule.
Upvotes: 2