Reputation: 13789
I'm trying to create a rule that only lets a user create/edit a document in which request.auth.uid
matches the name of the document they're trying to create. From https://cloud.google.com/firestore/docs/security/secure-data:
Using variables from wildcards
When you match a rule using a database path with a wildcard, a variable is created with a name matching the string you included inside the curly brackets. You can then reference these variables in your security rules.
One common use of these types of wildcards is to store documents by userID, and then only allow users to access documents for which their userID matches the ID of the document.
service cloud.firestore { match /databases/{database}/documents { match /users/{userIDFromWildcard}/ { // Users can only edit documents in the database if the documentID is // equal to their userID allow read, write: if request.auth.uid == userIDFromWildcard; } } }
I tried using this code in my rules, but it errors. When removing the last /
, i.e. match /users/{userIDFromWildcard}
instead of match /users/{userIDFromWildcard}/
, it publishes, but permissions aren't granted if the document doesn't exist.
Edit: I also tried something like this, but I don't know how to do it correctly because of the lack of documentation:
allow read, write: if request.auth.uid == request.resource.__name__;
This is the code I'm running that gets insufficient permissions
:
this.items = afs.doc("/users/" + this.uid); // afs is AngularFirestore, this.uid is the uid of the authenticated user
...
// the user is authenticated at this point
this.items.snapshotChanges().subscribe(snapshot => {
if (!snapshot.payload.exists) { // if user isn't in db
function recursive() {
// ...
this.updateDB(); // called once because of conditional
}
recursive();
} else {
// ...
}
}
updateDB
:
public updateDatabase(): void {
const changes: Item = { name: this.name, username: this.username,
photoURL: this.photoURL };
this.items.set(changes).then((item) => { // causes error
console.log("Saving successful");
}, (err) => {
console.log(err);
}).catch((err) => {
console.log(err);
});
}
Upvotes: 0
Views: 1739
Reputation: 181
You probably need this setup for documents:
service cloud.firestore {
match /database/{databases}/documents {
match /users/{userId}/{document=**} {
allow read, write: if request.auth.uid == userId;
}
}
}
Also, if you need to write to a sub-collections see this answer
And more info on wildcard matching in firestore here
Upvotes: 1