How to add exclude data in Firebase rules on multiple levels? - firebase

I have my rules set. Normally, all data can only be read by the person who is auth to do so. However, I want to make exceptions. These are my rules:
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid",
"ForEveryone": {
".read": true,
".write": true
}
"NoWrite" : {
".read": true,
".write": false
}
}
}
So I let's say I have 3 string. String 1 is called private and can the auth person can read and write. String 2 is ForEveryone, so everyone can change and write data. String 3 is NoWrite, for everyone but you can not write to it.
I get an error, saying:Expecting a ; or " at the line NoWrite. So what am I doing wrong? Is it a wrong placed }? Thank you.

The approach you're taking to your rule structure won't work. Firebase security rules cascade, meaning that a permission given to any node will apply to any of its children and on down the tree. You cannot grant read or write access on a node and then revoke it further down. (But you can grant permissions not granted above.) See the docs on rule cascading.
In your case, you want to have some user data that be can written to by anyone and some that cannot. It's not clear from your example whether you want NoWrite to be written only by the authenticated user, or by nobody. Depending on how you will be reading this data, you will need to either separate these data into different collections, or make $uid inaccessible and define your rules only for ForEveryone and NoWrite.
The first approach might look like this:
"rules": {
"users-public": {
"$uid": {
".read": "true",
".write": "true",
},
"users-nowrite": {
"$uid": {
".read": "true",
".write": "$uid === auth.uid"
}
}
Or the second, like this:
"rules": {
"users": {
"$uid": {
"ForEveryone": {
".read": "true",
".write": "true"
},
"NoWrite" : {
".read": "true",
".write": "$uid === auth.uid"
}
}
}
As to your syntax error, you need a comma , after the closing brace before "NoWrite".

Here are your rules, properly spaced so you can see the relationship between the parent nodes and child nodes. It seems this is not what you want. So this isn't really an answer but will lead to a better question that we can answer. Will update once we know what the OP is after.
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid",
"ForEveryone": {
".read": true,
".write": true
},
"NoWrite" : {
".read": true,
".write": false
}
} //end uid
} //end users
} //end rules
} //outside closure

Related

Can I access data from firebase's real time database on security rules

I have a token stored in my /users/UID object, and I want to check if the token provided in the request matches it. How can I do this?
At the moment, I have this:
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid",
"files": {
".write": "newData.child(\"token\").val() === \"ZnYKcbTIaN466iQ\"", //
".read": "$uid === auth.uid"
},
}
},
}
}
The code above returns true, but the token changes periodically. Can I, somehow, access this information in my database?
I got it! To check was quite simple, you just need to use the data object
".write": "newData.child(\"token\").val() === data.child(\"token\").val()"

Firebase Realtime Database Rule

My database rules is as below which only lets authorized users to read/write their own data. However, I want everyone to read all database without any authorization. How can I do it?
{
"rules": {
"posts": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
It is not 100% clear what you mean by "I want everyone to read all database without any authorization".
If you mean that anyone should be able to read the posts (even users without an account, i.e. unauthenticated users) you would adapt your rules as follows:
{
"rules": {
"posts": {
"$uid": {
".read": true,
".write": "$uid === auth.uid"
}
}
}
}
If you mean that only authenticated users should be able to read the posts of all the other users (in others words, authenticated users shall get the authorization to read all posts), you would adapt your rules as follows:
{
"rules": {
"posts": {
"$uid": {
".read": auth != null,
".write": "$uid === auth.uid"
}
}
}
}
See the doc for more details.

Firebase user permission

I have two mega parent nodes, but I am currently unable to write to the second one.
-users
uid
some other info
uid
-secondParent
child
uid
child
uid
I would like the user to be able to write to his own child of secondParent. Read and write permissions are working correctly for the users parent node, but I can't get it working for the secondParent.
The rule I have currently is:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null",
".write": "$uid === auth.uid",
}
},
"parentdNode": {
"$childID":{
".read" : "auth != null",
"$uid":{
".write": "$uid === auth.uid",
}
}
}
}
}
Simulation failure below:
You have to write rules for each parents to enable permission
{
"rules": {
"users": {
"$uid": {
".read": "auth != null",
".write": "$uid === auth.uid",
}
},
"parentdNode": {
"$childID":{
"$uid":{
".read" : "auth != null",
".write": "$uid === auth.uid",
}
}
}
}
}
According to the screenshot, you are trying to write {"uid":"X","property":"Y"} to /parentNode/someNode. The rules give permission to write {"property":"Y"} to /parentNode/someNode/65ef..aa62.
JSON trees come with key/value pairs. There is no key uid in the scheme you presented, there is a $uid which is replaced by the a value from the path you are accessing.
It may still be a bit confusing, but I hope this points to clarifying ideas.

Why are these two identical sets of Firebase rules are working very differently?

This set of rules is working fine and giving output as expected
{
"rules": {
"intents" : {
".read" : "auth.uid === data.child('to').val()",
".write" : true
},
"messages" : {
".read": "auth.uid !== null",
"$message": {
".write": true
}
}
}
}
But, this set of rules is not allowing any user to read any data, though write operation is working fine in this set too.
{
"rules": {
"intents" : {
".read" : "auth.uid === data.child('to').val()",
".write" : true
},
"messages" : {
"$message": {
".read": "auth.uid !== null",
".write": true
}
}
}
}
To me, both these sets look almost identical. Is there any "Firebase security rules" rule which I'm missing?
NOTE Both these rules were tested without making any change to the database or any code. Only the rules shown were altered.
The two sets of rules have one important difference: The first one allows to read "messages" in one operation, while the other allows only to read any single message at once. You are probably trying to read all messages in one operation, only the first rules will let you do that.
{
"rules": {
...
"messages" : {
".read": "auth.uid !== null", // Here: Can read all at once
"$message": {
".read": "auth.uid !== null", // Here: Can only read one at a time
".write": true
}
}
}
}

Is there a way to store a custom expression in Firebase Rules to be reused?

I would like to be able to reuse an expression in my Firebase Rules multiple times.
If I have the following rules:
{
"rules": {
".read": true,
".write": false,
"secretArea1": {
".read": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'"
},
"secretArea2": {
".read": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'"
}
}
}
Is there a way to store root.child('users').child(auth.uid).child('role').val() === 'admin' somewhere so it doesn't have to be repeated 4 times?
Something like:
{
"rules": {
".read": true,
".write": false,
"secretArea1": {
".read": "isAdmin",
".write": "isAdmin"
},
"secretArea2": {
".read": "isAdmin",
".write": "isAdmin"
}
}
}
Maybe I'm approaching this the wrong way. Any suggestions would be great!
I just discovered Blaze Compiler which was linked at Security & Rules Libraries. Not exactly what I was looking for and adds an extra compile step but seems to provide the functionality I was looking for. It would be nice if it was included as an option in the Firebase Dashboard.

Resources