Let's assume we have a Firestore collection called todos
, where each todo will look something like this:
{
name: "Buy milk",
completed: false,
user: "eYtGDHdfgSERewfqwEFfweE" // some user's uid
}
Now, I want to prevent modification of the user
field during updates (in other words - make this field read-only).
Believe me, I've done my research. My update
rule looks like this:
allow update: if request.auth.uid == resource.data.user
//&& !request.writeFields.hasAny(["user"]);
//&& !(request.writeFields.hasAny(["user"]));
//&& !request.resource.data.keys().hasAny(["user"]);
//&& !('user' in request.resource.data);
//&& ('user' in request.resource.data) == false;
//&& !('user' in request.writeFields);
None of the above (commented out) work. They all result in an error: Error: Missing or insufficient permissions.
.
But...
It gets even more interesting! Because if we compare some of the above rules for positive outcome (aka true
) they will work!
For example, this one works perfectly (assuming we include user
field in our request):
allow update: if request.resource.data.keys().hasAny(["user"]) == true;
BUT this one doesn't work (assuming we do NOT include the user
field in the request):
allow update: if request.resource.data.keys().hasAny(["user"]) == false;
Can anyone explain me what is going on here? Is it possible this is actually a bug in Firestore?
At "Writing conditions for Cloud Firestore Security Rules" section "Data validation" example #2
service cloud.firestore {
match /databases/{database}/documents {
// Make sure all cities have a positive population and
// the name is not changed
match /cities/{city} {
allow update: if request.resource.data.population > 0
&& request.resource.data.name == resource.data.name;
}
}
}
So request.resource.data.user == resource.data.user
should work for you? CMIIW
Ref: https://firebase.google.com/docs/firestore/security/rules-conditions#data_validation