In Realtime Database, Rules apply atomically, meaning that rules at higher-level parent nodes override rules at more granular child nodes and rules at a deeper node can't grant access to a parent path. You can't refine or revoke access at a deeper path in your database structure if you've already granted it for one of the parent paths.
{
"rules": {
"foo": {
// allows read to /foo/*
".read": "data.child('baz').val() === true",
"bar": {
// ignored, since read was allowed already
".read": false
}
}
}
}
While it may not seem immediately intuitive, this is a powerful part of the rules language and allows for very complex access privileges to be implemented with minimal effort. This is particularly useful for user-based security.
However, .validate rules do not cascade. All validate rules must be satisfied at all levels of the hierarchy for a write to be allowed.
Additionally, because rules do not apply back to a parent path, read or write operation fail if there isn't a rule at the requested location or at a parent location that grants access. Even if every affected child path is accessible, reading at the parent location will fail completely. Consider this structure:
{
"rules": {
"records": {
"rec1": {
".read": true
},
"rec2": {
".read": false
}
}
}
}
Without understanding that rules are evaluated atomically, it might seem like fetching the /records/ path would return rec1 but not rec2. The actual result, however, is an error:
var db = firebase.database();
db.ref("records").once("value", function(snap) {
// success method is not called
}, function(err) {
// error callback triggered with PERMISSION_DENIED
});
references:
https://firebase.google.com/docs/rules/rules-behavior
No comments:
Post a Comment