我想确保可以(从客户端)创建新用户,但只有经过身份验证的用户才能读取或写入现有对象。
我有一个简单的规则集:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid === $uid",
".write": "!data.exists() || auth.uid === $uid"
}
}
}
}
我正在调用createUser
,然后在回调中我试图在我自己的users
对象中添加一个条目:
const usersRef = ref.child('users');
const userEntry = {
[userData.uid]: {
created: new Date().getTime()
}
};
usersRef.set(userEntry)
我原以为即使用户尚未登录,他们也应该拥有!data.exists()
的写入权限。但我收到PERMISSION_DENIED
错误。
如果我在".write": true
级别设置users
,那么它会级联(并覆盖?)我的内部规则会赢吗?
修改
即使使用以下内容也会失败:
"users": {
"$uid": {
".read": true,
".write": true
}
}
感谢。
答案 0 :(得分:2)
我想我最初误解了这个问题。在您当前的回调中,由于set的工作方式,您试图覆盖整个用户级别。
你真的想要只设置不存在的东西:
const userRef = ref.child('users').child(userData.uid);
const userEntry = {
created: new Date().getTime()
};
userRef.set(userEntry);
然后,我认为您现有的规则会起作用。
答案 1 :(得分:1)
我认为这是一个令人困惑的问题,因为创建用户和写入数据库是完全不同的事情。所以我将在我的应用程序中展示我是如何做到的。
我使用以下规则来确保每个用户只能在firebase(documentation)中写入自己的节点:
{
"rules": {
"users": {
"$user_id": {
".write": "$user_id === auth.uid"
}
}
}
}
要记住的一件事是set()将替换该路径上的任何现有数据。因此,请确保使用用户的uid而不是用户节点。
最后,我想指出你在问题中发布的规则存在一个巨大的缺陷:
".write": "!data.exists() || auth.uid === $uid"
此规则声明如果还没有任何数据,您可以编写或者您有正确的uid。本声明的第一部分是问题,因为 ANYONE 可以在没有任何数据时写入此位置。另外因为$ uid是dynamic path,你可以添加任何内容:
"users": {
"WoWIjustMadeThisUp": {
"nice": "Some huge value making you go over your limit"
}
}
如果您希望用户只编写初始值,之后无法编辑,只需使用validate rule至check if there is already data at that location。