Firebase RealTime Database Rules using regular expression for custom ID - firebase

I have a requirement that users can only write to their account node in the RT database. Normally this would work:
"accounts": {
"$uid": {
".write": "$uid === auth.uid",
".read": "$uid === auth.uid"
},
However, the requirement is that the uid from Authentication is stored inside "accounts" prefixed with "US_".
So, I've tried this:
"accounts": {
"$uid": {
".write": $uid.matches(/^US_/) + "auth.uid",
".read": "$uid === auth.uid"
},
and this:
"accounts": {
"$uid": {
".write": "$uid === /^US_/auth.uid",
".read": "$uid === auth.uid"
},
The 2nd seems closer to working and the error is:
Error saving rules - Line 44: invalid flag after regular expression
I am wondering if this is even possible?
UPDATE
This parsed correctly, but it does not seem to work (I cannot get the rule to pass):
"accounts": {
"$uid": {
".write": "$uid === 'US_' + 'auth.uid'",
".read": "$uid === auth.uid"
},
},
Database Structure
accounts:
uid: "US_blah",
createdAt: <datetime>,
username: "MickeyMouse"

It turns out I did not need a regular expression. This works:
"accounts": {
"$uid": {
".write": "$uid === 'US_' + auth.uid",
".read": "$uid === auth.uid"
},

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 rules: Unknown variable '$uid'

I want user to only access their own content, except for one child node: common
In common child node I want all signed in users to have access.
I have made the following rules:
{
"rules": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
},
"common" : {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
Firebase gives me the error:
Error saving rules - Line 8: Unknown variable '$uid'.
The error appears in this line: ".read": "auth != null && auth.uid == $uid",
Based on your question, this is your desired database structure:
{
"userIdA": { // anything here can be written by only userIdA
"name": "Tom", // this is just example data
"location": "London",
/* ... */
},
"userIdB": { // anything here can be written by only userIdB
"name": "Sarah",
"location": "New York",
/* ... */
},
/* ... other user data ... */
"common": { // anything here can be written by signed in users
"data1": "some value",
"data2": "some other value",
}
}
The rules for this structure would be:
{
"rules": {
"common" : {
".read": "auth != null", // logged in users can read
".write": "auth != null" // logged in users can write
},
"$uid": { // $uid will be the value of any key, that isn't listed above it (in this case, anything other than "common")
".read": "$uid === auth.uid", // only the matching user can read
".write": "$uid === auth.uid" // only the matching user can write
}
}
}
Note: This data structure isn't very secure. Allow read/write access to only what you need in your database. With this structure, any user could come along and open up their console and delete everything under "/common". You may consider adding ".validate" rules to make sure certain keys (such as "/common/data1") are only strings.
The $uid must be inside users Document like the example below :
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}

Firebase - limit write to authorized user

I am writing an app where I have users, and each user has trips.
I have managed to authenticate and insert user's data. Now I want to define rules for the trips list.
Currently I can't get the simulator to work even with the same definitions (getting write/read permissions to users, but failing for trips, see pics):
This is what I have that is failing:
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid",
".read": "$uid === auth.uid"
},
"trips" : {
"$uid" : {
".write": "$uid === auth.uid",
".read": "$uid === auth.uid"
}
}
}
}
}
What I actually want eventually is:
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid",
".read": "$uid === auth.uid"
},
"trips" : {
"$tid" : {
".indexOn": ["uid"],
".write": "<only if child field 'uid' is same as auth.uid>",
".read": "auth != null"
}
}
}
}
}
That's because you've nested your "trips" rules under the "users" rules. They should both be under the "rules" node. Like this:
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid",
".read": "$uid === auth.uid"
}
},
"trips" : {
"$tid" : {
".write": "$tid === auth.uid",
".read": "auth!=null",
".indexOn":"uid"
}
}
}
}

Firebase Database Rules to match row

I am using a Firebase Realtime Database. I have the following data:
I also have the rules:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"chat": {
"$key": {
".read": "data.child('memberId1').val() === auth.uid && data.child('memberId2').val() === auth.uid",
".write": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid"
}
},
The initial rule works perfectly:
".read": "auth != null",
".write": "auth != null",
Problem
The following 2 rules have no effect.
"chat": {
"$key": {
".read": "data.child('memberId1').val() === auth.uid && data.child('memberId2').val() === auth.uid",
".write": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid"
}
},
As you can see, in order to test these rules, in the first rule, I have made an impossible condition of memberId1 and memberId2 both equal to the users uid. As a result I would expect it to fail.
If I remove:
".read": "auth != null",
".write": "auth != null",
and just have:
"chat": {
"$key": {
".read": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid",
".write": "data.child('memberId1').val() === auth.uid || data.child('memberId2').val() === auth.uid"
}
},
Then access is denied. Even if I change it to:
"data.child('memberId1').val() === 'h6qQg5YfQveTaCyBEXwDMSJPqwk1'
The following is also denied:
"chat": {
"Ko7w9XTtuRVN4p6CMp7": {
".read": true,
Question
How should I structure the rules to allow that a user may only access a row where their uid matches either memberId1 or memberId2?
Thanks
UPDATE
I have the following code:
findChats(): Observable<any[]> {
return this.af.database.list('/chat/', {
query: {
orderByChild: 'negativtimestamp'
}
}).map(items => {
const filtered = items.filter(
item => (item.memberId1 === this.me.uid || item.memberId2 === this.me.uid)
);
return filtered;
});
}
My question is similar to this one. I try the following with no success:
{
"rules": {
"chat": {
"$id": {
".read": true
}
},
Firebase rules are atomic. So if you try to read /chat (and thats what you are currently doing) it will only check the /chat branch rules. Since you dont have any rule in /chat it goes for the default thats is not giving access. Therefore, your rules would only be evaluated in case you were trying to read /chat/chatId.
One possible solution you could go for is to store a list of chats which each user is part of. So you can keep your current chat branch but store another branch in the database with the following structure:
user_chats: {
uid1: {
chatId1: true,
chatId2: false
}
uid2: ...
}
And rules:
"user_chats": {
"$uid": {
".read": "auth.uid === $uid",
".write": "auth.uid === $uid"
}
}
Then you could keep your chat rules like you already have them but first get the data from /user_chats/uid and then for each chatId retrieved you you will need to read on chat/chatId.

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.

Resources