Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloud Firestore rules on subcollection

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 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.

like image 473
Gertjan Smits Avatar asked Dec 14 '17 09:12

Gertjan Smits


People also ask

What is a Subcollection in firestore?

A subcollection is a collection associated with a specific document. Note: You can query across subcollections with the same collection ID by using Collection Group Queries. You can create a subcollection called messages for every room document in your rooms collection: collections_bookmark rooms. class roomA.

How do I set rules for firestore database?

Cloud Firestore provides a rules simulator that you can use to test your ruleset. You can access the simulator from the Rules tab in the Cloud Firestore section of the Firebase console. The rules simulator lets you simulate authenticated and unauthenticated reads, writes, and deletes.

What file should be used for firestore rules firestore rules?

firestore. rules // is a file used to define the security rules for your Firestore database. firestore.


1 Answers

Honestly, I think you're okay with your structure and get call as-is. Here's why:

  1. If you're fetching a bunch of documents in a subcollection, Cloud Firestore is usually smart enough to cache values as needed. For example, if you were to ask to fetch all 200 items in "conversions/chat_abc/messages", Cloud Firestore would only perform that get operation once and re-use it for the entire batch operation. So you'll end up with 201 reads, and not 400.

  2. As a general philosophy, I'm not a fan of optimizing for pricing in your security rules. Yes, you can end up with one or two extra reads per operation, but it's probably not going to cause you trouble the same way, say, a poorly written Cloud Function might. Those are the areas where you're better off optimizing.

like image 123
Todd Kerpelman Avatar answered Sep 21 '22 13:09

Todd Kerpelman