I am trying to read a collection of documents only if the document has the user id of the current user logged in with firebase. Here are my database rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /todos/{todoId} {
allow read: if isLoggedIn() && request.auth.uid == resource.data.userId;
allow create: if isLoggedIn() && request.auth.uid == request.resource.data.userId;
allow update, delete: if isLoggedIn() && request.auth.uid == resource.data.userId;
}
function isLoggedIn() {
return request.auth != null;
}
}
}
Creating documents is not a problem, but reading them. Here is my function that retrieves the data:
getData () {
this.$fire.firestore.collection('todos').get()
.then((doc) => {
if (doc.exists) {
console.log('Document data:', doc.data())
} else {
// doc.data() will be undefined in this case
console.log('No such document!')
}
}).catch((error) => {
console.log('Error getting document:', error)
})
}
It seems that the resource.data.id rule is not pointing to the todo userId and therefore I get the FirebaseError: Missing or insufficient permissions. Here is my current database structure:
Any ideas on why the rule is not working as intended?
CodePudding user response:
Firebase security rules don't filter data. Instead they merely ensure that any operation you perform meets the rules you've set.
So this rule you have says that the user can only read documents that have their own UID:
allow read: if isLoggedIn() && request.auth.uid == resource.data.userId;
But then your code goes ahead and tries to read all documents:
this.$fire.firestore.collection('todos').get()
Since your rules don't allow reading all documents, the operation is rejected.
To allow the operation, ensure that your read operation matches your rules and only request documents where the UID matches:
let uid = ...
this.$fire.firestore.collection('todos').where("userId", "==", uid).get()
CodePudding user response:
I already solved the issue, the method for getting the data from firestore was incomplete, the solution was in the firebase documentation.
The correct way to do the data retrieving is using the where constraint:
getData () {
this.$fire.firestore.collection('todos').where('userId', '==', this.user.uid).get()
.then((docs) => {
if (docs) {
// console.log('Document data:', docs.data())
docs.forEach((doc) => {
console.log(doc.data())
})
} else {
// doc.data() will be undefined in this case
console.log('No such document!')
}
}).catch((error) => {
console.log('Error getting document:', error)
})
}