第一次使用firebase并设置复杂(对我而来)规则。
我有一个孩子的集合,有一个属性" parentId"。我只希望某些角色和用户阅读此表。具体来说,我希望任何教练或裁判角色能够阅读以及任何孩子的父母。
我认为问题出在" data.child(' parentId')。val()=== auth.uid"在收集级别.read。我觉得我完全按照这里的例子,但它仍然没有工作:https://www.firebase.com/docs/security/api/rule/data.html
有人能指出我在安全规则中做错了吗?
我知道安全规则不会过滤,我不相信这是特定问题的一个例子,因为我的查询特意将结果限制为我试图通过安全规则允许的内容(尽管我可能弄错了) )。
这是当前的安全规则。评论应该解释我的目标:
"children": {
// give ability of any coach or referee to read any child. Give refs ability to write to any child. Allow parent to query for their own children.
".read": "(data.child('parentId').val() === auth.uid) ||(root.child('users').child(auth.uid).child('role').val() === 'coach') || (root.child('users').child(auth.uid).child('role').val() === 'referee')",
".write": "root.child('users').child(auth.uid).child('role').val() === 'referee'",
".indexOn": ["parentId", "isApproved"],
"$child": {
// give a parent read and write access to only their specific children.
".read": "root.child('children').child($child).child('parentId').val() === auth.uid",
".write": "root.child('children').child($child).child('parentId').val() === auth.uid"
}
}
在我的代码中,我正在通过parentId查询所有子项。这是我的javascript失败,错误:permission_denied:客户没有权限访问所需的数据。":
factory.getChildrenByParent = function(parentId){
return new Promise(function(resolve, reject){
childrenRef.orderByChild('parentId').equalTo(parentId)
.once('value', function(childrenResponse){
var children = childrenResponse.val();
processChildren(children);
resolve(children);
},
function(err){
if(err){
reject(err);
}
})
})
}
评论应该解释我的目标。问题是用户无法通过父ID(等于auth.uid)查询子项。 他们可以通过以下方式查询一个:
factory.getChildById = function(id){
return new Promise(function(resolve, reject){
childrenRef.orderByKey().equalTo(id)
.once('value', function(childResult){
var childObjects = childResult.val();
processChildren(childObjects);
var child = Utilities.getFirst(childObjects);
resolve(child);
},
function(err){
if(err){
reject(err);
}
})
})
}
我尝试过使用模拟器,但我无法弄清楚.orderByChild(' parentId')的等级语法.aquantTo(parentId)和Chrome开发工具网络没有'当我开火时显示任何活动...
答案 0 :(得分:7)
您可能希望再次阅读Firebase documentation on "Rules are not filters"部分。
规则以原子方式应用。这意味着如果在该位置或授予访问权限的父位置没有规则,则读取或写入操作会立即失败。即使每个子路径都可访问,在父位置读取也会完全失败。考虑这个结构:
{
"rules": {
"records": {
"rec1": {
".read": true
},
"rec2": {
".read": false
}
}
}
}
如果不理解规则是以原子方式进行评估的,那么获取/ records / path似乎会返回rec1而不是rec2。但实际结果是错误:
ref.child("records").once("value", function(snap) {
// success method is not called
}, function(err) {
// error callback triggered with PERMISSION_DENIED
});
由于/ records /的读取操作是原子的,并且没有读取规则允许访问/ records /下的所有数据,因此会抛出
PERMISSION_DENIED
错误。如果我们在App Dashboard中的安全模拟器中评估此规则,我们可以看到读取操作被拒绝:
Attempt to read /records with auth=Success(null)
/
/records
No .read rule allowed the operation.
Read was denied.
操作被拒绝,因为没有读取规则允许访问/ records / path,但请注意,rec1的规则从未被评估过,因为它不在我们请求的路径中。要获取rec1,我们需要直接访问它:
ref.child("records/rec1").once("value", function(snap) {
// SUCCESS!
}, function(err) {
// error callback is not called
});
换句话说:只有当您拥有该位置的读取权限时才能对某个位置执行查询。
有关同样的问题: