Firebase simple blog (confused with security rules)

- 1 answer

Ad

I'm trying to create a simple todo or blog system based on React + ReactFire.

And after a hour of reading firebase tutorial confused about configuring firebase security rules.

Code for saving element :

this.props.itemsStore.push({
    text : this.state.text,
    done : false,
    user : this.props.user.uid
})

Everything ok, but how i can get all records what owns only but authorized user?

This rules doesn't works :

  "rules": {
    "items" : {
         ".write" : "auth !== null",
         "$item" : {
            ".read": "data.child('user').val() == auth.uid"
         }
    }
  }

Seems to there no way to get all records only for one user, with security rules, instead of this, i should use something like filter. But again, i don't know how to filter elements in ReactFire, and in manuals no information.

As example how does it work in Parse http://i.stack.imgur.com/l9iXM.png

Ad

Answer

Ad

The Firebase security model has two common pitfalls:

  1. permissions cascade: once you've granted a read or write permission on a specific level, you cannot take this permission away at a lower level

  2. rules are not filters: (this is essentially a consequence of the previous pitfall) you cannot use security rules to return a different subset of children for specific users. Either a user has access to a node, or they don't have access to it.

You seem to be falling for that second pitfall. While the user can access each specific message that they are the user for, they cannot query the higher-level items node since they don't have read access to it.

If you want to secure a list of messages/todos for a specific user, you will need to store that data for that specific user.

items_per_user
    $uid
        $itemid: true

This is quite common in NoSQL database and is often called denormalizing. See this article called "denormalization is normal" on the Firebase web site. It's a bit outdated as far as the Firebase API goes, but the architectural principles on denormalizing still apply.

To then show the items for a user, you'd do:

ref.child('items_per_user')
   .child(ref.getAuth().uid)
   .on('child_added', function(snapshot) {
       ref.child('items')
          .child(itemId.key())
          .once('value', function(itemSnapshot) {
               console.log(itemSnapshot.val());
          });
   })

Many developer new to Firebase think that the inner loop will be too slow to load their data. But Firebase is very efficient when it comes to handling multiple requests, since it only opens a connection once per client and pipelines all the requests in the inner loop.

Ad
source: stackoverflow.com
Ad