I have added new security rules for my Firebase database, here they are:
{
"rules": {
"Users" : {
"$uid" : {
".read" : "auth != null && auth.uid == $uid",
"numberOfConnections" : {
".write" : "(auth != null && auth.uid == $uid) && (newData.val() - data.val() == 1 || newData.val() == 0)",
},
"mail" : {
".write" : "auth != null && auth.uid == $uid",
},
"numberOfFeedBack" : {
".write" : "auth != null && auth.uid == $uid",
},
"username" : {
".write" : "auth != null && auth.uid == $uid",
}
}
},
"Feedback" : {
"$uid" : {
".read" : "auth != null && auth.uid == $uid",
".write" : "auth != null && auth.uid == $uid",
}
},
}
}
When I write with updateChildValues in FeedBack it works, but when I write in Users I get a denied permission.
Here is the code:
// This don't work -> Permission Denied
static func createNewUsersDb(userId : String, username : String, mail : String) {
let update : [String : Any] = [
"/Users/\(userId)/username" : username,
"/Users/\(userId)/mail" : mail,
"/Users/\(userId)/numberOfConnections" : 0,
"/Users/\(userId)/numberOfFeedBack" : 0
]
dbRef.updateChildValues(update)
}
//This work
private static func createNewFeedBackDb(_ informationForFeedback : String){
let now = DateFormatter()
now.dateStyle = .medium
now.timeStyle = .medium
now.locale = Locale(identifier: "EN-en")
let update : [String : Any] = [
"/Users/\(userId!)/numberOfFeedBack" : ServerValue.increment(NSNumber(value : 1)),
"/FeedBack/\(userId!)" : [
"date" : now.string(from: Date()),
"information" : informationForFeedback
]
]
dbRef.updateChildValues(update)
}
It seems that it's because I didn't write a ".write" rule for Users.uid but I don't understand why it's blocking since I don't write when in the child nodes for which I did set a ".write" rule.
Also, if I write a ".write" rule in Users.uid, Firebase's rule handling would cause my sub-rule for numberOfConnections to be ignored.
That's why I specified the same ".write" rule for all child nodes of Users.uid except numberOfConnections, it seems a bit overkill but it's the only way I found.
I'm not exactly sure why your write rules don't work, since you're only writing to allowed paths/values as far as I can see. However, I'd typically implement the case differently, which may solve your problem anyway:
"Users" : {
"$uid" : {
".read" : "auth != null && auth.uid == $uid",
".write" : "auth != null && auth.uid == $uid",
"numberOfConnections" : {
".validate" : "(newData.val() - data.val() == 1 || newData.val() == 0)",
},
"mail" : {
".validate" : true
},
"numberOfFeedBack" : {
".validate" : true
},
"username" : {
".validate" : true
},
"$other" : {
".validate" : false
}
}
So now you only check for authorization once (on /Users/$uid) and then use validation checks to:
Allow mail, numberOfFeedBack, and username.
Allow numberOfConnections based on the value written.
Reject any other child nodes - the $other rule matches all child nodes that are not matched by another/named rules already.
Related
I have a database tree like so
users
-UID
--items
---all the data
I would like to add something under UID like shared:another-UID and allow the other UID to read and write everything under items.
For example:
users
-UID
--shared:different_UID
--items
---all the data
My current rules are like this
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
How would I change my rules to allow this?
In that case your rules would become:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && (auth.uid == $uid || data.child('shared').val() === auth.uid)",
".write": "auth != null && (auth.uid == $uid || data.child('shared').val() === auth.uid)"
}
}
}
}
So in words: the user can read/write this data if the key is the same as their user ID, or if their user ID is stored in the shared property under the data.
i want to give access to users profile to specific users that are set by the users themselves
in this rules i want to let $userid to be able to access $user_id data
(if $user_id exist in allow_list/$userid/), i tried root.child('allow_list/'+auth.uid+'/$user_id').exists())" but its not working
this is my rules for now, not working
"users_private": {
"$user_id": {
".write": "auth != null && $user_id === auth.uid",
".read":"(auth != null) && ($user_id === auth.uid
|| root.child('allow_list/'+auth.uid+'/$user_id').exists())"
}
},
"allow_list":{
"$userid": {
//ignore these rules they are working
".read":"auth != null && $userid === auth.uid" ,
"$user_id": {
".write": "($userid == auth.uid || $user_id == auth.uid )&&
( $userid!=$user_id)",
}
}
},
I found out how, hope this help someone.
I added .child, so the rule will be like this:
|| root.child('allow_list/'+auth.uid+'/').child($user_id).exists())
What's wrong with this? It says
Error saving rules - Line 12: Expected '{'.
Which regards the .body line, right after the :
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"v1": {
"v2": {
"$v3": {
"v4": {
"$v5": {
".body": "newData.isString() && newData.val().length > 0 && newData.val().length < 10"
}
}
}
}
}
}
}
I got it.
The last part should have been
"body": {
".validate": "newData.isString() && newData.val().length > 0 && newData.val().length < 10"
}
I am trying to get the list of branches from Firebase database(in this example [branch1,branch2]) in Swift language,
when I observe the top node ("branches") it returns nothing and even the first print function is not being called, but if I observe one of the branches like branch1 it works fine.
now how can I retrieve the list of branches ([branch1,branch2])
let ref = FIRDatabase.database().reference()
ref.child("branches").observe(.value, with: { snapshot in
print("+++++++++++++++++ ")
print("++++++++++++\(snapshot.hasChildren())")
for child in snapshot.children{
let branch = child as! FIRDataSnapshot
let branchName = branch.key as! String
print("\(branchName)")
}
}
enter image description here
{ "Users" : {
"6dICrkbVVJWzVZ00Vq4y9Fm2Qcg2" : {
"branches" : {
"branch1" : true
},
"isAdmin" : true
},
"M0C1XUyboPg5zbgQi24nh3SlJri1" : {
"branches" : {
"branch2" : true
}
} },"branches" : {
"branch1" : {
"address" : "NDG",
"campaigns" : {
"valentine's day" : true
},
"manager" : "y",
"rate" : {
"average" : 0,
"bad" : 0,
"good" : 0
},
"users" : {
"6dICrkbVVJWzVZ00Vq4y9Fm2Qcg2" : true,
"M0C1XUyboPg5zbgQi24nh3SlJri1" : {
"isAdmin" : true
}
}
},
"branch2" : {
"address" : "downtown montreal",
"manager" : "x",
"rate" : {
"average" : 0,
"bad" : 0,
"good" : 0
},
"users" : {
"M0C1XUyboPg5zbgQi24nh3SlJri1" : true,
"Z6b5WalkNWZLMVdwGPHi3vSvSRU2" : {
"isAdmin" : true
}
}
} }, "campaigns" : {
"valentine's day" : {
"branches" : {
"branch1" : true
}
} }}
and the working code for getting branch1 is :
ref.child("branches").child("branch1").observe(.value, with: { snapshot in
let address = snapshot.childSnapshot(forPath: "address").value
print("\(address)")
}
and it will print the right result (NDG)
security rules :
{ "rules": {
"Users":{
"$uid":{
".read":"auth.uid == $uid || root.child('Users').child(auth.uid).child('isAdmin').val()==true",
".write":"auth.uid == $uid || root.child('Users').child(auth.uid).child('isAdmin').val()==true"
}
}, "branches":{
"$branchId":{
".read" : "auth.uid == true || root.child('Users').child(auth.uid).child('isAdmin').val()==true || root.child('branches').child($branchId).child('users').child(auth.uid).exists()",
".write" : "auth.uid == true || root.child('Users').child(auth.uid).child('isAdmin').val()==true || root.child('branches').child($branchId).child('users').child(auth.uid).child('isAdmin').val()==true"
}}}}
Thanks to #vzsg I found out that the problem was with the permission and rules. so I changed the rules and I get the result easily
{ "rules": {
"Users":{
"$uid":{
".read":"auth.uid == $uid || root.child('Users').child(auth.uid).child('isAdmin').val()==true",
".write":"auth.uid == $uid || root.child('Users').child(auth.uid).child('isAdmin').val()==true"
}
}, "branches":{
".read": " root.child('Users').child(auth.uid).child('isAdmin').val()==true" ,
".write" : "root.child('Users').child(auth.uid).child('isAdmin').val()==true ",
"$branchId":{
".read": " root.child('branches').child($branchId).child('users').child(auth.uid).exists()",
".write" : "root.child('branches').child($branchId).child('users').child(auth.uid).child('isAdmin').val()==true"
}} }}
Need help understanding what wrong with the "Tracking" rule. I'm able to read that data even though it's marked as .read : false.
{
"rules": {
"User": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
},
"Purchase": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
},
"Parm": {
".read": true,
".write": false
},
"Tracking": {
".read": false,
".write": true
}
}
}
This is being done on an IOS app. Here’s the code:
Firebase *ref = [FBase referenceForTrackingDeviceId:sysparm.deviceId];
[ref observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
if (snapshot.exists) {
DLog(#"got it");
} else {
DLog(#"No data");
}
}];
From the debugger:
(lldb) po ref https://<My-Firebase>/Tracking/E8C0C8FB-DE20-4017-9C74-3A6DAD6D4DC7 (lldb) po snapshot.exists YES