I've attempted to set up a security rule where a person writing a document to a particular collection may only do so if their uid matches the uid contained in the document, but can't get it to work. In this case I am writing a document to a collection called 'embedUsers' and the document being written contains a uid field that was acquired when the user account was created.
The rules are set up as follows:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /embedUsers/{documents=**} {
allow read: if true;
allow write: if resource.data.uid == request.auth.uid;
}
}
}
The document is written by an Angular client, using the following code:
const userRef: AngularFirestoreDocument<UserModel> = this.afs.doc(`embedUsers/${user.accountAddress}`);
console.log("current logged in user", this.fireUser.uid);
try {
console.log(user.uid);
await userRef.set(user, { merge: true });
} catch (e) {
console.error(`FireAuthService.updateUserData unexpected failure with error ${e.message}`)
throw new Error("updateUserData failed");
}
console.log("wrote embed user successfully")
Although I have checked that the uid of the signed in user matches the uid field in the data object being written, this call to userRef.set
fails with FireAuthService.updateUserData unexpected failure with error Missing or insufficient permissions.
It seems like something must be wrong with my rules but I'm not sure what (if I change the rule to simply say allow write: if true;
the document gets written as expected.
CodePudding user response:
As explained in the doc, "When writing data ... the request.resource
variable contains the future state of the document". So you should adapt your rule to:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /embedUsers/{documents=**} {
allow read: if true;
allow write: if request.resource.data.uid == request.auth.uid;
}
}
}