5

I want to create item lists using Firebase that can be created by a user and then he can specify other users to share the list with (so they can also modify its contents). I plan to do this by using the following structure:

enter image description here

So the user section specifies the lists that a user has. Then the node 'lists', all lists created have a unique id and for each list its members are specified:

enter image description here

In this example, Rick is the admin of the list and Tom just a member. Now I want the rules to, for example, only allow reading and writing under the 'items' node, if the user id is present under the 'members' node.

Now I have two questions: 1. Is this approach the correct on or should my entire data structure be different for this purpose? 2. If the structure is fine, how should I write the rules such that the above described behavior is obtained and how do I generate a unique id for each list?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
BramH
  • 221
  • 5
  • 24

1 Answers1

4

At first glance this seems like a reasonable starting point. I'd just replace the "values that are the same as the key" with a simple true, to save a few bytes of storage/bandwidth. Aside from that it's hard to give more "hard" advice without knowing all use-cases.

You might also want to consider a recent change: security rules can now validate queries, which means that you could potentially do without the /users/$uid/lists index. I recommend that you try this and see if it works for your use-case.

To allow read access to a list only to members of that list, these rules could be a starting point:

{
  "rules": {
    "lists": {
      "$listid": {
        "items": {
          ".read": "
            data.parent().child('members').child('admin').val() === auth.uid ||
            data.parent().child('members').child(auth.uid).exists()
          "
        }
      }
    }
  }
}

The first line of that .read rule grants read access to the admin. The second line then grants read access to all other users.

Finally: as always I recommend reading NoSQL data modeling and watching Firebase for SQL developers.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks for the advice, I will try that. With the rules I mean that for the 'lists/uniqueListID/items/...' node, I want a read or write to allowed if; 'uniqueListID/members/...' contains 'auth.uid'. Do you know how to do this? – BramH Feb 02 '18 at 14:58
  • works perfect, thank you so much! one edit; '.parent()' is called twice in your code, but I think it should be called once. – BramH Feb 02 '18 at 15:43
  • Ah right, good catch. I moved the `.read` rule one level up before posting, but forgot to remove that one. Updated. – Frank van Puffelen Feb 02 '18 at 15:53
  • I think I will keep the node 'users/$uid/lists', since it makes querying for the lists of a user a lot simpler and faster I think. Do you agree? (if you dont I will try it using validation) – BramH Feb 02 '18 at 16:06
  • That approach has worked for developers for years, so it's hard to recommend against it. :-) I'm just interested in hearing from devs using this new API. – Frank van Puffelen Feb 02 '18 at 16:41
  • Thank you very much for the answer. @FrankvanPuffelen. Can I ask that will it be able to share and sync the data (or the subset of that data) between multiple users when using realtime database ? Or should I change to cloud firestore. – Ken Pham May 08 '20 at 08:50