Reputation: 11782
I have put a rule as
(root.child('users').child(auth.uid).child('role/cafe').val() === true)
in my realtime database rules.
My user is
key {
uid: xxxx
name: xxxx
role:{
cafe: true
user: false
}
}
if auth.uid is equal to key, the rule works, however how can I modify the above rule to look for uid inside data
Upvotes: 3
Views: 2404
Reputation: 26171
It is unclear what the value of $key
is expected to be. So I'm going to assume it's just some random string that isn't used in the rules.
For each security rule, the current data of the node is accessible using the predefined variable data
. ".write"
and ".validate"
rules also have access to the to-be-written data as newData
. These are both RuleDataSnapshot objects.
Assuming that a user making changes must be the user given by the uid
property, the following rules can be used.
"rules": {
"users": {
"$key": {
".read": "auth != null && data.child('uid').val() == auth.uid",
".write": "auth != null && ((data.exists() && data.child('uid').val() == auth.uid) || (!data.exists() && newData.child('uid').val() == auth.uid)"
}
}
}
The above rules use a fail-fast approach. If a user is not logged in, the check aborts. Otherwise, the user's ID is matched against the existing data at the given node. If the data doesn't yet exist, the newly updated data must also match the current user's ID.
In case the "cafe" role is important, the following rules also require that the "cafe" is set to true
to allow read/write operations.
"rules": {
"users": {
"$key": {
".read": "auth != null && data.child('uid').val() == auth.uid && data.child('role/cafe').val() == true",
".write": "auth != null && ((data.exists() && data.child('uid').val() == auth.uid && data.child('role/cafe').val() == true) || (!data.exists() && newData.child('uid').val() == auth.uid && newData.child('role/cafe') == true))"
}
}
}
Note: If $key
is storing user info/data, I highly recommend using the user's ID as the key as security rules cannot perform queries like "does userid have admin role?" without structuring your data to allow it. If $key
is meant to be a username, instead use a username-to-userID map as it will prevent future problems. One such example is if a user wants to change their username, you can remove and link the new username to the user without ever having to move all their data.
Upvotes: 4
Reputation: 980
You can use a wild card. In your rules
"users":{
"$key":{
".read" : (root.child('users'+$key).child('role/cafe').val() === true) && (root.child('users'+$key).child('uid').val() === auth.uid ),
".write" : (root.child('users'+$key).child('role/cafe').val() === true ) &&(root.child('users'+$key).child('uid').val() === auth.uid )
}
},
The first condition checks whether the café value for the user is true the second checks whether the uid is the same
Upvotes: 2