【发布时间】:2018-09-14 04:48:21
【问题描述】:
初步方法/问题
用户将能够写入他自己的用户节点。然后用户必须能够写出他/她想要的任意数量的建筑物和任意数量的部门(还有房间 但为了清楚起见,我暂时将其放在一边)。用户应该能够读取(和写入)他自己的用户节点、建筑物和部门,但不能读取(和写入)其他用户的节点、建筑物和部门。
基本上:
用户 > 用户的建筑物 > 建筑物的部门(总读写权限)
用户>另一个用户的东西(根本没有权限)
这是数据库结构:
{
"buildings" : {
"-L9Bc9aazn3mNiW1elJk" : {
"address" : "",
"comments" : "",
"hasDepts" : {
"-L9FwBmYEnkZQzdFJ4lU" : true
},
"name" : "J house",
"ownerID" : "6hwNde08Wuaa9bfReR28niSbOsF3"
}
},
"depts" : {
"-L9FwBmYEnkZQzdFJ4lU" : {
"comments" : "",
"inBuilding" : "-L9Bc9aazn3mNiW1elJk",
"name" : "Dep 1"
},
},
"users" : {
"6hwNde08Wuaa9bfReR28niSbOsF3" : {
"isAdmin" : {
"-L9Bc9aazn3mNiW1elJk" : true,
}
}
}
初步方法
每个 users 节点都有一个子节点 isAdmin,其中包含该用户创建的 buildings 的所有按键。使用相同的逻辑,buildings' 节点包含一个 hasDepts 节点,其中包含用户在该建筑物中创建的 depts 的所有按键.
如果您能提供帮助,我将不胜感激。有人在吗?
我正在使用 vue.js 像这样写入 firebase:
addBuilding: function () {
let userId = firebase.auth().currentUser.uid;
let buildingKey = buildingsRef.push().key;
this.newBuilding.ownerID = userId;
buildingsRef.child(buildingKey).set(this.newBuilding);
usersRef.child(userId).child('isAdmin').child(buildingKey).set(true);
}
迄今为止最接近的解决方案/@André Kool(部分使用初始方法)
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
},
},
"buildings": {
"$pushKey" : {
".read": "root.child('buildings').child($pushKey).child('ownerID').val() === auth.uid",
".write": "!data.exists() || root.child('buildings').child($pushKey).child('ownerID').val() === auth.uid"
}
},
"depts": {
"$pushKey": {
".read": "root.child('buildings').child(root.child('depts').child($pushKey).child('inBuilding').val()).child('ownerID').val() === auth.uid",
".write": "root.child('buildings').child(root.child('depts').child($pushKey).child('inBuilding').val()).child('ownerID').val() === auth.uid"
}
},
}
通过@André Kool 的尝试,模拟器允许它读取/写入 buildings/$pushKey 节点。然而,虽然它一创建就在前端显示节点,但当我们刷新浏览器或添加新建筑物时,节点会从前端消失(保留在数据库中)。 Firebase 也不允许写入 depts 节点。有什么线索和可能的解决方案吗?
更新:另一种方法。
1) 确保 buildings 和 depts 节点都具有 ownerId 子节点,如下所示:
{
"buildings" : {
"-L9HIbKu5fIe8rfoePgi" : {
"address" : "",
"comments" : "",
"hasDepts" : {
"-L9HIdScisDItysCnMlm" : true
},
"name" : "building 1",
"ownerID" : "6hwNde08Wuaa9bfReR28niSbOsF3"
}
},
"depts" : {
"-L9HIdScisDItysCnMlm" : {
"comments" : "",
"inBuilding" : "-L9HIbKu5fIe8rfoePgi",
"name" : "dep 1",
"ownerID" : "6hwNde08Wuaa9bfReR28niSbOsF3"
}
},
"users" : {
"6hwNde08Wuaa9bfReR28niSbOsF3" : {
"isAdmin" : {
"-L9HIbKu5fIe8rfoePgi" : true
},
"name" : "João Alves Marrucho",
"userEmail" : "joaomarrucho@hotmail.com"
}
}
}
2) 使用 ownerId 授权对所有建筑物和部门进行读写:
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
},
},
"buildings": {
"$id": {
".read": "data.child('ownerID').val() == auth.uid" ,
".write": "data.child('ownerID').val() == auth.uid"
}
},
"depts": {
"$id": {
".read": "data.child('ownerID').val() == auth.uid" ,
".write": "data.child('ownerID').val() == auth.uid"
}
},
}
3) 这种方法的新问题!
根据上述规则,使用模拟器,在我看来,firebase 不允许用户读/写 buildings 节点,但它允许读/写 buildings /$pushKey 节点。 firebase 是否需要用户能够读取/写入父节点(buildings)和子节点(buildings/$pushKey)?如果是这样,您如何防止用户删除(.set)整个 buildings 节点?
我问这个是因为如果我们在 $wildcards 之前添加 ".read": true, ".write": true 它会写入预期的数据库结构 同时使级联上的下一个规则完全无用...所以这不好,但至少它暗示了部分解决方案可能存在的位置。
"users": {
".read": true, <<<<<<
".write": true, <<<<<<
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
},
}, // but is should also be able to write to his own buildings
"buildings": {
".read": true, <<<<<<
".write": true, <<<<<<
"$id": {
".read": "data.child('ownerID').val() == auth.uid" ,
".write": "data.child('ownerID').val() == auth.uid"
}
},
"depts": {
".read": true, <<<<<<
".write": true, <<<<<<
"$id": {
".read": "data.child('ownerID').val() == auth.uid" ,
".write": "data.child('ownerID').val() == auth.uid"
}
},
}
(其他想法) 我不明白为什么用户不应该能够读取/写入 buildings 父节点(前提是规则阻止他删除整个 buildings 节点并且仅授予他对他创建的 buildings/$pushKeys 的完全访问权限)。这很复杂吗?我可能弄错了,但是 firebase 是否不需要在 知道哪个属于用户之前扫描 buildings 节点?
如果firebase规则不能像这样解决这个问题,那就意味着理论上,用户需要在其中读取和写入自己的内容到实时数据库的每个firebase应用程序(通常情况下)都需要将信息存储在users.uid 节点,使其对他/她可用。这似乎违背了“让你的数据库尽可能平坦”的 firebase 一般指令,而且它也不能很好地处理具有数据库引用且在 firebase 中有子项的任何函数都需要 data.snapshots 噩梦般的迭代这一事实。 此外,如果你不能设计一个浅层结构,并且用户 id 会不断变化,你将如何在 Apps firebase 配置中编写数据库引用: const buildingRef = db.ref('users/'+ userId!!!!+'/buildings'); : >How to constrain read/write rules to the users that create the nodes while keeping this structure? 必须有一种无需向后弯腰就能做到这一点的好方法。 ?
【问题讨论】:
-
“我知道这看起来很乱” - 我完全同意这一点。您能否编辑您的问题,说明您想要什么(例如:用户可以读/写他们自己的用户节点、每座建筑物,以及他们拥有的建筑物的唯一部门),并可能减少一些解释性文字。过多的解释/阐述实际上会使它更难理解。
-
关于不支持的 javascript 的第一个错误:你有一个 .在最后一个孩子之后:
.child.('isAdmin')",这应该是.child('isAdmin')", -
感谢@André 的提示。我已经删除了所有凌乱的代码,只留下了问题。
-
你能把你最后的规则尝试放回你的问题吗?类似“我试过这个(规则)但我得到了这些错误”
-
您在问题中包含了 JSON 树的图片。请将其替换为作为文本的实际 JSON,您可以通过单击 your Firebase Database console 中的导出 JSON 链接轻松获得该文本。将 JSON 作为文本使其可搜索,让我们可以轻松地使用它来测试您的实际数据并在我们的答案中使用它,一般来说这只是一件好事。
标签: firebase firebase-realtime-database vue.js firebase-authentication authorization