Reputation: 131
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.
Upvotes: 1
Views: 58
Reputation: 598951
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:
mail
, numberOfFeedBack
, and username
.numberOfConnections
based on the value written.$other
rule matches all child nodes that are not matched by another/named rules already.Upvotes: 1