When i run the query below i get permission-denied
and in the "Monitor rules"-tab i get an error.
const timeNow = useMemo(() => Timestamp.now(), []);
const query = query(
postRef,
where("tags", "array-contains-any", ["Event"]),
where("publishDate", "<=", timeNow),
orderBy("publishDate", "desc"),
limit(4)
);
This is part of my security rules where I have located the error to come from:
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postID}{
allow read: if resource.data.publishDate <= request.time;
}
}
}
I have tested to change the rule to resource.data.publishDate != null
which is true e.g. allows the request. When I try resource.data.publishDate is timestamp
I get a deny.
So I wonder I have something wrong in the query or if I have missed something in the security rules?
2
Answers
It’s not possible use
request.time
as a range check in security rules. Futhermore, theTimestamp.now()
token only works when updating a field in a document – it also can’t be used effectively in a range filter.The rule as written will only work when getting a single document. In that case, the rule will check if the single document field to see if the date is less than or equal to the current time.
I don’t believe there are any direct workarounds. You could instead write backend code to enforce that the filter must always limit the date in the query filter, and have your app call the backend to get the data.
Your security rules syntax looks correct. Here is how I verified using simulation on my end.
I think for you, the document’s publishDate field is not actually timestamp but rather it is storing some other type value as as string. I confirmed that security rules gives error message when we try to compare request.time with value other than timestamp.
Thus, I would recommend you do update the rule as :
if resource.data.publishDate is timestamp && resource.data.publishDate <= request.time;