1

We are building a platform using Firebase Realtime Database and I'm having a bit of a struggle to find the best way to structure our data for private and public access.

Today we have

database: {
  items: {
    $userUid: {
      $itemUid: {
        poster_link: "..."
        format: "..."
        title: "..."
      }
    }
  }
}

All our items are stored under each user in order to make it fast and secure to load.

Our rules are set up like this

{
  "rules": {
    "items": {
      "$userId": {
        "$itemId": {
          ".read": "auth !== null,
          ".write": "auth !== null"
        }
      }
    }
  }
}

So only an authorised user can read and write the data. I could create something like this to allow items to be public if the value is true:

".read": "auth !== null || data.child('public').val() == true"

But this will still be under $userUid

So I was wondering if you have any suggestion on how to structure this example to allow items to be under a user and also seen publicly, not necessary under this user, a bit like Dropbox does when you share something.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • The simplest solution is to separate the public and the private data. See my answer here on the why and how: https://stackoverflow.com/questions/38648669/firebase-how-to-structure-public-private-user-data – Frank van Puffelen Jul 01 '17 at 15:37

2 Answers2

1

You can structure like this

database: {
  items: {
      $itemUid: {
        poster_link: "..."
        format: "..."
        title: "..."
        user: "userid"
      }
  }
}

now set the rules as

{
  "rules": {
    "items": {
        "$itemId": {
          ".read": "auth !== null || data.child('public').val() == true,
          ".write": "auth !== null"
        }
    }
  }
}
Prags
  • 811
  • 5
  • 17
1

You chosen data structure does not take advantage of the flat data principles of Firebase. This will make it very difficult for you to query items of multiple users. For example, how do you get all the public items without drilling into each user?

Similarly, a boolean called public is also not good because you can't extend it to other ACL scenarios. Much better is an ACL object that can be extended in the future.

For example:

items: {
  itemsUid: { 
    [...],
    userId: ...,
    ACL: { public: true }
  }
}

Now you can write the rule:

auth !== null && (root.child(items/ACL/public).exsists() || data.userId === auth.UID)

If in three months you add a concept of friends that can see you posts or followers that can see you items you can simply add friends: true, followers: true to the ACL object and adjust the rule.

Mika
  • 5,807
  • 6
  • 38
  • 83