我有一个用户集合,其中每个文档都包含一个名称字段和一个访问映射。
"users" :[
{
"mHbVq5TUY7brlleejClKm71NBGI2": {
"name": "Bob Johnson",
"access": {
"X0w1VaVIljR1Nc5u3Sbo" : true
}
}
]
我希望Firestore规则仅在不存在新文档且仅在执行此操作的人员已验证其电子邮件的情况下才允许创建新文档。对于更新,只有拥有该节点的用户才能执行更新,名称必须是字符串,并且访问映射不能更改。我测试了更新并在模拟器中创建了规则,它们按预期工作。但是,当我运行.set()时,它将完全覆盖我的整个节点并删除我无法发生的访问映射。我假设.set()实际上正在执行更新,因此符合我的更新条件。因此,如何防止某人完全覆盖我的节点。预先感谢...下面的代码。
---代码执行覆盖
db.collection("users").doc("mHbVq5TUY7brlleejClKm71NBGI2").set(
{
name: "Bill Swanson",
}
).catch(err => {
console.log(err.message)
})
---规则
function incomingData() {
return request.resource.data
}
function emailVerified() {
return request.auth.token.email_verified;
}
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
function userExists(user_Id) {
return exists(/databases/$(database)/documents/users/$(user_Id));
}
allow create: if !userExists(userId) && emailVerified();
allow update: if request.auth.uid == userId
&& !('access' in incomingData())
&& request.resource.data.name is string;
allow read: if request.auth.uid != null;
}
}
}
答案 0 :(得分:0)
使用set()时,如果不确定文档是否存在,请传递选项以将新数据与任何现有文档合并,以避免覆盖整个文档。
这里是传递选项以将更新与现有文档合并的方法。
db.collection("users")
.doc("mHbVq5TUY7brlleejClKm71NBGI2")
.set(
{
name: "Bill Swanson"
},
{
merge: true
}
).catch(err => {
console.log(err.message)
});
希望这会有所帮助。