Search code examples
ember.jsfirebase-securityemberfire

Basic security rules with Firebase


I'm having issues implementing basic security rules with Firebase (I read documentation on Firebase and StackExchange but cannot make security rules work):

The model (Emberjs representation of the model):

App.User = DS.Model.extend({
  uid: DS.attr('string'),
  displayName: DS.attr('string'),
  books: DS.hasMany('statistic', { inverse: 'user', async: true}),
  actions: DS.hasMany('action', { inverse: 'user', async: true}),
});


App.Action = DS.Model.extend({
  date: DS.attr('date'),
  actionType: DS.attr('string'),
  comment: DS.attr('string'),
  user: DS.belongsTo('user', {inverse: 'actions', async: true} )
});


App.Book = DS.Model.extend({
  name: DS.attr('string'),
  description: DS.attr('string'),
  user: DS.belongsTo('user', { inverse: 'books', async: true} )
});

The 3 nodes (models) are stored directly in the root of the Firebase app. The Book and Action models have a user field (property).

What are the rules to writes so that:

  1. Only the user identified in the user field of the Book and Action models (nodes) can have read and write access to their own data? (The value of the user field in Book and Action must be equal to the value of auth.uid in Firebase for the user to be granted the read and write privileges.)
  2. That the users can only access the information of the User model (node) that pertain to them?

Thanks


Solution

  • It is important to understand the structure of data in the Firebase.

    Basically, there are two ways to write security rules. You either set up security rules right under books/ or you write security rules for each model attribute separately. Or a combination of both but make sure you understand the top-down principle first.

    I prefer to write rules for each attribute separately, it is more easily maintainable and testable.

    But in your case, because other users don't need to acces some part of books or users it is easy to write the rules for the whole model:

    "rules" :{
      "books": {
        "$book_id": {
          ".read": "data.child('user').val() === auth.uid && auth !== null",
          ".write": "!data.exists() && newData.child('user').val() === auth.uid || data.child('user').val() === newData.child('uid').val() && auth !== null"
         },
       "users": {
         "$user_id": {
          ".read": "data.child('uid') === auth.uid",
           ".write": "!data.exists() && newData.child('uid').val() === auth.uid || data.child('uid').val() === newData.child('uid').val()"
         }
       }
      }
    }

    I did not test these rules, they can contain flaws, please use the simulator tool to make them bulletproof :]

    Check my medium post for more info: https://medium.com/@martinmalinda/emberfire-is-awesome-but-querying-data-and-writing-security-rules-can-be-a-pain-f5370f4decb