I'm attempting to setup security rules that allow access to a collection, based on the value of a document field in a subcollection.
This works as expected when retrieving an individual document by id, which is a get
operation. However, when querying main_collection
(a list
operation), this fails with a "permission denied" error. Since there is only a single document in the collection, this is not a case where I don't have permission to some of the documents being queried, such as on this question.
My database structure looks like the following. It contains the collection being listed (main_collection
), which has a single document (some_doc
), which has a single subcollection (sub_collection
), which has a single document (another_doc
).
/main_collection/some_doc/sub_collection/another_doc
another_doc
has one string field someFieldValue
.
For this example, my query is of the entire collection, which is the single document. In my actual application it only queries the documents it expects to have access to, but the end result here is the same because I cannot filter against a document's subcollection from the client library.
firestore.collection('main_collection').get()
These are my security rules.
service cloud.firestore {
match /databases/{database}/documents {
match /main_collection/{mainColDoc} {
// This operation works
allow get: if subCollectionDocumentHasField('someFieldValue');
// This operation fails with permission denied
allow list: if subCollectionDocumentHasField('someFieldValue');
// This checks for the existence of a field on the subcollection's document
function subCollectionDocumentHasField(fieldName) {
return get(/databases/$(database)/documents/main_collection/$(mainColDoc)/sub_collection/another_doc).data.keys().hasAny([fieldName]);
//return get(/databases/$(database)/documents/main_collection/some_doc/sub_collection/another_doc).data.keys().hasAny([fieldName]);
}
}
}
}
The subCollectionDocumentHasField
function checks for the existence of the someFieldValue
field on the document another_doc
. In this function, if I replace the $(mainColDoc)
variable with the hard-coded document id some_doc
, the list
operation is successful. Since the $(database)
path variable can be used in this context, I would expect that others could be as well.
Is this a bug or expected behavior?