I am trying to get all posts made between two users to each other in one firestore query, but I get permission denied. I have a "posts" collection with post documents that have the following fields:
{
to : uid_of_user_receiving_post,
from : uid_of_user_sending_post,
queryIdentifier: uidsToQueryIdentifier(uid_of_user_receiving_post, uid_of_user_sending_post),
...
}
where:
uidsToQueryIdentifier = (uid1, uid2) => {
if (uid1 < uid2) {
return uid1 + "_" + uid2;
}
return uid2 + "_" + uid1;
}
Whenever I make a post document, I use uidsToQueryIdentifier() function as the value to the field queryIdentifier.
I am running this query on the client side with the following security rules and getting permission denied. The user object is authenticated and has a uid.
match /posts/{postId} {
allow read: if request.auth.uid == resource.data.to ||
request.auth.uid == resource.data.from;
allow write: if true;
}
const queryIdentifier = uidsToQueryIdentifier(user.uid, friend.uid);
let query = firestore().collection("posts")
.where("queryIdentifier", "==", queryIdentifier)
.orderBy("createdAt")
2
Answers
Firestore security rules are not filters (you should read and understand that documentation). What security rules do is place requirements on the queries that would be allowed by them. Your rule has requirements for the values of both
to
andfrom
fields in the query, so your query must filter on the values of those fields using the UID of the user. Either one of these should work with the rule you have now:Or, if you want to use
queryIdentifier
in your query, you would instead need to change your rule to place a requirement on that field instead.While Doug’s answer explains why your current approach won’t work, and his approach with two queries does work, my preferred solution to this problem is to add an array field to each document with the UID values of the participants in the post:
With that in place, you can use a single query to get all posts the current user participates in:
If you ensure the
participants
values are always in the same order (similar to what you already do forqueryIdentifier
, you can even use an==
on the field to replace you current condition:This can work, but I usually prefer to have the string value like you have already as it’s easier to troubleshoot.