So I've come across this thread.
Structuring data for chat app in Firebase
I would just like to give a sample for my firebase db structure ( similar in firebase docs).
{
"chatMetadata": {
"chatroom_id_1": {
"title": "Some Chatroom Title",
"lastMessage": "Some Message",
"timestamp": 1459361875666
"users": {
"uid_1": true,
"uid_3": true
}
},
"chatroom_id_2": { ... }
},
"users": {
"uid_1": {
"chatRooms": {
"chatroom_id_1": true,
"chatroom_id_2": true
},
},
"uid_3": { ... }
},
"chatrooms": {
"chatroom_id_1": {
"m1": {
"name": "uid_1",
"message": "The relay seems to be malfunctioning.",
"timestamp": 1459361875337
},
"m2": { ... }
},
"chatroom_id_2": { ... }
}
}
For me to implement like a recent chat messages. I'll probably need the "/chatMetadata/" data since it has the lastMessage
To query it in client we need the answer in the link above to get it in one reference alone.
//chatMetaDataRef = root of "chatMetadata"
chatMetaDataRef.queryOrderedByChild("users/uid_3").queryEqualToValue(true)
.observeSingleEventOfType(.Value, withBlock: { snapshot in
// Do something here
})
Problem with this is all users should have read access to "/chatMetadata" node for that to work.
Here is my security rule for it
{
"rules": {
".read": "auth.uid === 'someServiceWorker'",
".write": "auth.uid === 'someServiceWorker'",
"chatMetadata": {
"$chatroomId":{
".read": "data.child('users/'+auth.uid).exists()"
},
".read": "auth != null"
},
"chatrooms": {
"$chatroomId": {
".read": "root.child('chatMetadata/'+ $chatroomId + '/users/'+auth.uid).exists()",
}
},
"users": {
"$userId": {
".read": "auth.uid === $userId"
}
}
}
}
Now my question is how should we implement the security rule for this one such that users shall not have access to all chatMetadata(because if i remove "auth!=null", my query above will not work. Or if it is not possible how should we restructure the data such that we can query it with one reference alone?
P.S.
Reason for the question is I didn't like the idea that I will loop over "users/$uid/chatrooms" and query each reference I receive from it. Like the 2nd answer in the link above.
for chat in listOfChatsUserIsIn
ref.child("chatMetadata").child("\(chat)").child("lastMessage").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
lastMessage = snapshot
// do something here
}