Reputation: 8241
Assume the following.
posts : {
"$postid":{
"meta":{
"state":true,
"text" :"I should be read",
},
"likes":{
"uid1":true,
"uid2":true,
},
},
"$postid":{
"meta":{
"state":false,
"text" :"I should be read",
},
"likes":{
"uid1":true,
"uid2":true,
"uid3":true,
},
}
}
I want to query the parent node('posts') as follows.
Security Rules
Here's the Javascript Version Of how I'm querying data. ////$.fdr === firebase.database.ref();
$.fdr("posts").orderByChild("time").limitToLast(20).once('value',function(r) {
var r = r.val();
if(r !== null){
///use r;
}
},function(e){
console.log(e);
});
Why this: I want the user to delete a post, and be able to revoke the delete later on. To delete I change the value of "post.meta.state" to "false". While "post.meta.state" is false, security rules shouldn't allow that post to be read.
Problem : If i set rules inside the post node rather than the parent node("posts"),
"postid": {
".read":"data.child('state').val() == true"
}
then I can restrict ".read", but only if i'll query posts as follows :
firebase.database.ref("posts/postid");
Otherwise if I try to query from the parent node like:
firebase.database.ref("posts/"),
so that I can filter out posts I don't want returned, then I'll have to elevate the rules from "posts" children to "posts"(parent), which will cause the rules in the children to be ignored, and there I can't seem to find a way to deny returning posts with "state" == false;
The above is based on my understanding so far, please do correct where I'm lost.
Upvotes: 1
Views: 1042
Reputation: 1506
Unfortunately, it is not possible to block reading/writing on any child node when a user as permission to read/write the parent node. You can read more about how security rules cascade in the Firebase Docs.
That said, there are a couple possible solutions for you to consider:
Instead of marking a post as deleted, you can move it out to a separate parent node. Then you can adjust the security rules for deleted_posts to hide it.
{
"posts": {
"$postid1": {
"meta": {
"state": true,
"text": "I should be readable"
},
"likes": {
"uid1": true,
"uid2": true,
"uid3": true
}
}
}
"deleted_posts": {
"$postid2": {
"meta": {
"state": false,
"text": "I should not be readable"
},
"likes": {
}
}
}
}
Keep a separate list of postids that are visible, and set the "posts" node to not readable, but the children to readable if not hidden. You will have to do a second query to get the data for each post:
{
"posts": {
"$postid1": {
"meta": {
"state": true,
"text": "I should be readable"
},
"likes": {
"uid1": true,
"uid2": true,
"uid3": true
}
},
"$postid2": {
"meta": {
"state": false,
"text": "I should not be readable"
},
"likes": {}
},
"$postid3": {
"meta": {
"state": true,
"text": "I should be readable"
},
"likes": {}
}
},
"visible_posts": {
"$postid1": true,
"$postid3": true
}
}
Upvotes: 4