I know Firestore rules allows rule checking for specific fields and data types of the request data, but I also want to control the specific difference of a field being updated.
For example, I have a counter on a document. I only want the counter to increase by one on each request, no more, no less.
I tried this in the rules playground on the firebase console and it works:
match /myCollection/{myDoc} {
allow update: if(request.resource.data.diff(resource.data).affectedKeys().hasOnly(["counter"])
&& request.resource.data.counter is int &&
request.resource.data.counter == resource.data.counter + 1);
}
but then in code I call:
docRef.update({
counter: firebase.firestore.FieldValue.increment(1)
}
which is blocked with a permission denial.
My guess is the rules are registering this as a function and not an int on the doc value, which causes it to fail. (which makes sense)
How can I properly validate this client side increment operation in the rules without reading the document first?
The rules you have work when the document has a previous value for counter
. However, if counter
is omitted on the original document, your rules will fail. This is because accessing a missing property on a map in security rules throws an error which will fail your rules.
You either need to enforce a counter
field on the initial document (make sure to fix existing documents) or allow counter
to be optional on the initial document.
Require counter
on creation & update:
match /myCollection/{myDoc} {
allow create: if "counter" in request.resource.data
&& request.resource.data.counter is int;
allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(["counter"])
&& request.resource.data.counter is int
&& request.resource.data.counter == resource.data.counter + 1;
}
Require counter
on update, may be omitted from initial document write:
match /myCollection/{myDoc} {
allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(["counter"])
&& request.resource.data.counter is int
&& request.resource.data.counter == resource.data.get("counter", 0) + 1;
}
Any final solutions on this? It would be nice to know a suggested use case. Thank you,
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.