So I have a document for an event. Here's the current structure:
{
"name": "Some Event Name",
"users" : {
"a": {
"name": "Some Name"
},
"b": {
"name": "Some Name"
}
}
}
What I'm looking to is a query for documents the user belongs to. I can do this by calling
db.events().order(by: "users.\(userId)")
However I cannot get rules to work when listing the events. I only want the user to be able to list results they belong to.
Heres my current rules:
match /events/{eventId} {
allow list: if isAuthed() && request.auth.uid in resource.data.users;
}
Is there a way to make this work? I know if I had an array of user IDs, the rules work. But can't get it to work with a object map. I prefer the map as it allows me to store the users names in the document.
With Firestore security rules, your query must match your rule. So, if your rule demands that some condition be met, your query must absolutely ensure that condition holds for all matching documents, else the query is immediately denied.
With Firestore queries, there is no way to make a query that filters on the simple existence of key in a map (using some sort of where clause), which means the rule you have now will always deny any query on the events collection.
I know if I had an array of user IDs, the rules work.
Realistically, this is your only way out without drastically changing your data. You can pretty easily keep both a list of UIDs and also map using those same UIDs in two separate fields. Use the list field for both filtering and security rules (so that they match perfectly), and the map field for any additional data you need to keep in addition to the UIDs. It will be up to you to keep those two fields up to date if something changes.