Reputation: 1166
I have this data structure:
and need a rule that only allows updates when the city
attribute is not changed:
match /requests/{requestId} {
allow update: if (request.resource.data.diff(resource.data).unchangedKeys().
hasAll(["customerlocation.city"]))
That doesn't work, because the diff
result only shows the customerlocation
field, but not the city
attribute.
Is it even possible to achieve what I want? I know there are limitations wrt what you can do with nested objects in security rules, but I have might just missed something.
Upvotes: 4
Views: 657
Reputation: 109
I think what you're after is something like this:
match /requests/{requestId} {
allow update: if (request.resource.data.customerLocation.diff(resource.data.customerLocation).unchangedKeys().
hasAll([resource.data.customerlocation.city]))
I am unsure about the [resource.data.customerlocation.city] part...but I did just write a similar rule to prevent updates to a map field that is not the user's own id that works.
allow update: if isSignedIn() && (request.resource.data.memberMap.diff(resource.data.memberMap).affectedKeys().hasOnly([getUid()]));
Upvotes: 0
Reputation: 2224
I believe that the solution Aion proposed is the only one that will work if you don't want to change your data structure and have to do this inside of the Firestore rules.
I don't know what your overall data structure looks like, but you could move customerLocation
out to its own collection. Then you would store a DocumentReference to customerLocation
inside of the request
.
You could also create a cloud function with document('requests/{requestId}').onUpdate()
and check if the city changed. If it has, then change it back in there. This would require you to keep track of the fact that you changed back the property though. Otherwise, the function would keep triggering and flipping the values.
Upvotes: 2
Reputation: 1256
I would simply recommend that you check to see if the City is still in it's default value, in this example I put that as "Default City" (that default would likely be nil)
match /requests/{requestID} {
allow update: if request.resource.customerLocation.city == "Default City"
}
Since your entire Firestore database is not referenced it may look slightly different in your project, but I think logically this will work.
Upvotes: 0
Reputation: 681
Why dont you directly compare the field value ?
allow update: if request.resource.data.customerLocation.city
!= resource.data.customerLocation.city;
Upvotes: 1