I'm working on an iOS app which has (whoah surprise!) chat functionality. The whole app is heavily using the Firebase Tools, for the database I’m using the new Cloud Firestore solution.
Currently I'm in the process of tightening the security using the database rules, but I'm struggling a bit with my own data model :) This could mean that my data model is poorly chosen, but I'm really happy with it, except for implementing the rules part.
The conversation part of the model looks like this. At the root of my database I have a conversations
collection:
/conversations/$conversationId
- owner // id of the user that created the conversation
- ts // timestamp when the conversation was created
- members: {
$user_id_1: true // usually the same as 'owner'
$user_id_2: true // the other person in this conversation
...
}
- memberInfo: {
// some extra info about user typing, names, last message etc.
...
}
And then I have a subcollection on each conversation called messages. A message document is a very simple and just holding information about each sent message.
/conversations/$conversationId/messages/$messageId
- body
- sender
- ts
And a screenshot of the model:
The rules on the conversation documents are fairly straightforward and easy to implement:
match /conversations/{conversationId} {
allow read, write: if resource.data.members[(request.auth.uid)] == true;
match /messages/{messageId} {
allow read, write: if get(/databases/$(database)/documents/conversations/$(conversationId)).data.members[(request.auth.uid)] == true;
}
}
Problem
My problem is with the messages subcollection in that conversation. The above works, but I don’t like using the get()
call in there.
Each get()
call performs a read action, and therefore affects my bill at the end of the month, see documentation.
Which might become a problem if the app I’m building will become a succes, the document reads ofcourse are really minimal, but to do it every time a user opens a conversation seems a bit inefficient. I really like the subcollection solution in my model, but not sure how to efficiently implement the rules here.
I'm open for any datamodel change, my goal is to evaluate the rules without these get()
calls. Any idea is very welcome.