Reputation: 308
i have the following sample app here: Github repo
It uses vuefire in ChatList.vue
// vuefire firestore component manages the real-time stream to that reactive data property.
firestore() {
return {
chats: db.collection('chats').where('members', 'array-contains', this.uid)
}
},
I now wrote security rules to secure the data, but can't seem to get the combination of vuefire and security rules to work:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
// THIS IS THE PART I'D LIKE TO REMOVE
match /chats/{chatId=**} {
allow read: if request.auth.uid != null;
}
// THIS WORKS AS INTENDED, AND I'D LIKE TO INCLUDE "READ"
match /chats/{chatId}/{documents=**} {
allow write: if chatRoomPermission(chatId)
}
function chatRoomPermission(chatId) {
return request.auth.uid in get(/databases/$(database)/documents/chats/$(chatId)).data.members;
}
}
}
So the goal is: make the individual chats only readable and writable to users that are in the members array in firestore. (Currently i achieved this partially, since all chats are readable to anyone, but only writable to users in the members array.)
Do i have to rewrite the vuefire component so i can have the following security rule? (It gives an error message: listing of chats not possible due to missing permissions)
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
match /chats/{chatId}/{documents=**} {
allow read, write: if chatRoomPermission(chatId)
}
function chatRoomPermission(chatId) {
return request.auth.uid in get(/databases/$(database)/documents/chats/$(chatId)).data.members;
}
}
}
For completeness, the working solution is (credits to Renaud Tarnec):
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
match /chats/{chatId=**} {
allow read: if request.auth.uid in resource.data.members;
}
match /chats/{chatId}/{documents=**} {
allow read, write: if chatRoomPermission(chatId)
}
function chatRoomPermission(chatId) {
return request.auth.uid in get(/databases/$(database)/documents/chats/$(chatId)).data.members;
}
}
}
Upvotes: 0
Views: 204
Reputation: 83093
Since you want to check, in your Security Rules, if a given value (the user uid
in this case) is contained in a field of type Array in your document, you can use the in
operator of the List
type.
So, the following should do the trick:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
// THIS IS THE PART I'D LIKE TO REMOVE
match /chats/{chatId=**} {
allow read: if request.auth.uid in resource.data.members;
}
// ....
}
}
Upvotes: 1