简体   繁体   中英

How to restrict Firestore document update to only increment by one in rules?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM