Within firestore security rules, is there a way to get direct access to the value of a resource.data
for a list query? More specifically, for array-contains
. I’d like to use the value of the list
query and do some transformations with it inside the rules before evaluating the result.
Example:
Let’s assume that admin1
is the currently loggedin user.
I have a list of resources with the following property:
someResource{
sharedWithIds: ["client1", "client2", ..., "admin1", "admin2", ..., "admin1_client1", ...] //basically a manual index
}
And a query:
getDocs(query(collection, where("sharedWithIds", "array-contains", "admin1_client1"))
Security rules must only grant access if the current user is listed in sharedWithIds
So I was hoping I could do the following in the rules:
match /resources/{resourceId}{
allow list: if request.auth.uid in resource.data.sharedWithIds.split(“_”)
}
Here I assume that resource.data.sharedWithIds
equals to "admin1_client1"
, which is the value of the query. But it didn’t work – it just gives me false
all the time.
In fact, the rule’s debug
gives the following output for resource.data.sharedWithIds
:
constraint_value {
simple_constraints {
comparator: LIST_CONTAINS
value {
string_value: "admin1_client1"
}
}
}
I wasn’t able to find any documentation on this structure, but apparently I can perform hasAny
, but I can’t figure out how to get the underlying value of "admin1_client1"
.
Any suggestions? Or is it a dead end?
2
Answers
After digging through different questions and related comments on SO, it seems like it's not possible to get the value of the
array-contains
query in the rules. At least not now.In the rules for some queries we receive the query's value directly, like for
==
. For other queries we only get some internal wrapper object that only exposes a specific method.That method only allows to test against the specific action related to the query - in case of
array-contains
we only havehasAny()
While that allows to do the specific job defined in the doc, it seems like it enforces unnecessary limitations on what can be done in the rules. As opposite if we could get the value of the query itself, this would allow for more flexible rules.
For example in case of
array-contains
, rules could expose the value that user provided in the query or an array like[value]
- this would allow to test the query in the same way it works right now, plus it would allow for additional manipulations.The current approach of how the rules work unfortunately limits more complex scenarios.
As a remark, while Frank's answer mentions that there is no way to manipulate the data, that wasn't really my question, so I'm posting my answer to complete it
There is no way in Firestore security rules to manipulate the data.
The best solution I can think of is to include the separate parts you want to check on the in
sharedWithIds
too, or add another array field with the split values for this purpose.