Currently I've been looking at FireBase, and have been using the AngularJS plugin, and have found the following problem I cannot get out of.
I currently have implemented the simple login system. Logged in with my mail and password after registering, I create a post like this:
post = {
name: "Hi",
message: "Guys",
user_id: Auth.user.id // for my current user this is 1
}
posts.$add(post)
From this point on everything is fine. Now what I wanted to do is that in the posts/ endpoint on firebase, I want only to display the posts of the user currently logged in.
Other users may be able to read posts of others by having a public boolean variable (but that's for later)
I've been looking at the security API of Firebase (see: https://www.firebase.com/docs/security/security-rules.html) Currently I have this:
{
"rules": {
"posts": {
"$post": {
".read": "data.child('user_id').val() == auth.id",
".write": "(data.child('user_id').val() == auth.id) || (newData.child('user_id').val() == auth.id)"
}
}
}
}
It works to a certain extend, I can write posts only if I'm logged in, but I cannot read any posts!
posts = new Firebase(base + '/posts')
posts = $firebase(posts)
The error is: FIREBASE WARNING: on() or once() for /posts failed: Error: permission_denied: Client doesn't have permission to access the desired data.
If anyone has a solution then that would be awesome!
Security rules cannot be used as data filters. You can't just read the entire posts path and expect to only retrieve the records you're allowed to see. Instead, you need to architect your data in a manner that you can read the whole path, or store an index of which records are viewable and fetch them separately.
For example, store the records by group ids or by user ids:
/posts/$group/data...
/posts/$user/data...
And then you can ensure your users have permissions by assigning them to appropriate groups, and simply fetching the messages for those groups:
var ref = new Firebase(base + '/posts/' + GROUP_ID);
var posts = $firebaseArray(ref);
Or you can create an index of messages each user/group/etc may view:
/posts/$post_id/data...
/posts_i_can_view/$user_id/$post_id/true
And fetch them individually from the master list. A tool like Firebase-util will make this much simpler:
var fb = new Firebase(base);
var ref = Firebase.util.NormalizedCollection(
fb.child('posts_i_can_view/'+USER_ID),
fb.child('posts')
)
.select('posts.message', 'posts.user_id')
.ref();
var posts = $firebaseArray(ref);
Further reading on Firebase data structures:
https://www.firebase.com/docs/web/guide/structuring-data.html https://www.firebase.com/docs/web/guide/understanding-data.html https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html