I am trying to prevent a user from creating spam fields inside a document, fields that are different form that state of the original doc (after it has been created) my current rules looks like the following :
//Create
allow create : if request.auth != null
&& request.auth.uid == userId
&& request.resource.data.keys().hasOnly(
['clients', 'verifiedEmail', 'accountStatus' ,'createdAt', 'endsAt'])
allow read: if request.auth != null && request.auth.uid == userId
allow update : if request.auth.uid == userId
&& request.auth.uid == userId
&& request.resource.data.keys().hasAny(
['clients', 'verifiedEmail', 'accountStatus' ,'createdAt', 'endsAt']])
The idea here is in one instance I will want to update clients
await updateDoc(doc(db, 'Data', userCredential.user.uid), {
clients: //data,
});
in other instance I want to updated verified Email. while prevent a user from creating a filed like
await updateDoc(doc(db, 'Data', userCredential.user.uid), {
shouldnotbecreated: //some spam,
});
In the Rules update chunk
if I use hasOnly() it is so strict that it need the whole payload to be the same. as in
['clients', 'verifiedEmail', 'accountStatus' ,'createdAt', 'endsAt'].
If I use hasAll() or hasAny() a spam filed gets created.
It worked for my by using a combination of request.resource.data.diff(resource.data).affectedKeys().hasOnly()
//Create
allow create : if request.auth != null
&& request.auth.uid == userId
&& request.resource.data.keys().hasOnly(
['clients', 'verifiedEmail', 'accountStatus' ,'createdAt', 'endsAt'])
allow read: if request.auth != null && request.auth.uid == userId
allow update : if request.auth.uid == userId
&& request.auth.uid == userId
&& request.resource.data.diff(resource.data).affectedKeys().hasOnly(
['clients', 'verifiedEmail', 'accountStatus' ,'createdAt', 'endsAt']])