How to denormalise / structure data in Firebase in the context of complex security rules requirement?

StackOverflow https://stackoverflow.com/questions/19017175

Pregunta

My original title was "How to structure and secure user (account) data in Firebase for secure user access." as this is the domain of this question, but then I thought that a more general question could be formed instead. Having said that I am familiar with the
https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html
but as great as this article is, it does not quite apply to my problem, so here I go.


Firstly, I am going to be using Simple Login of email / password authentication type (though might use Persona instead if verification of user's email would have to involve server-side coding).
I have a userData object with user data (read user accounts) stored in them. It is required that each user can read data stored in their own account only. The actual data that all users will be accessing will be stored in a separate node called upcomingData.
Which data from the upcomingData can be accessed by a user will be determined by the type of the purchase a user made:
Those with the "subscription" type will be able to access all data until their subscription expires. I presume the "now" variable can be used to achieve this with security expressions.
Those with the "purchase" type can access only data purchased (listed in the array).
The admin@mydomain.com need to be able to read all data for all users, but write (and read) only to the upcomingData node.

So here is the test data structure I am trying to save to Firebase:

new Firebase(url).update({
  userData: {
    "admin@mydomain.com" : {
      subscription : {expire : '9999999999999'},
      purchase : []
    },
    "testUser@somwhere.com" : {
      subscription : {expire : '1379904665974'},
      purchase : ['upcomingData/-J47idp64ANBRmFS5rVY', 'upcomingData/-J47idpHg-pwzW1c-rfw', 'upcomingData/-J47idpLfIhlUQWTPc9y']
    },
    "testUser2@somwhereelse.co.uk" : {
      subscription : {expire : '1379904734517'},
      purchase : ['upcomingData/-J47idp64ANBRmFS5rVY', 'upcomingData/-J47idpHg-pwzW1c-rfw', 'upcomingData/-J47idpLfIhlUQWTPc9y']
    }
  }
});

This doesn't work because of the '.' characters.
Should I go for a DOT mangle like this:

"admin@mydomainDOTcom" : {...}

or rather should I 'push()' 'empty' user accounts upon creation to the userData node and save user's usernames as an {"id" : "admin@mydomain.com"} property in them?
How do I set security rules in Firebase so that the contents of userData can be read-only at all times with the exception to write at the time of successful purchase (say with PayPal)?
Can this be done securely without having to resort to server code?
I know that I can set up security rules so that only a server can write the data to Firebase, but this would involve a server-side code which would then write appropriate data in response to a valid PayPal payment notification (IPN) - a server-side code which I'd rather avoid not only because I'm not very proficient at server-side coding (though should be able to succeed node.js), but also because LAMP stacked shared servers are still much cheaper than a VPS needed for node (aaand I can't do php :( ).
The client code will be developed using the awesome Angular.js / angularFire combo.
Appreciate your time,
Jared

¿Fue útil?

Solución

Two different questions in here, handled separately:

  1. For "." characters, you can replace them with ",". Simple Login will do this for you automatically, for example, if you're using the Persona provider, the escaped email address will be accessible as userObject.id (and the real email address in userObject.email).

  2. To create read-only records, except for the first time, you can use a rule like:

".write": "!data.exists()"

This will prevent a record from being modified after being written to once.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top