仅在Firebase Firestore中不存在的情况下创建文档

时间:2017-10-23 11:52:51

标签: google-cloud-firestore

我想要实现的目标非常简单。我只需要在数据库不存在的情况下创建用户条目。

应用流程:

  1. 使用Firebase身份验证创建用户(获取UID)
  2. 使用UID作为密钥在数据库中创建用户文档
  3. 客户端代码(创建操作):

    this.db.doc('users/' + uid).set({username: Santa})
    

    火库规则:

    service cloud.firestore {
      match /databases/{database}/documents {
        match /users/{uid} {
          allow create: if 
            request.auth != null && 
            request.auth.uid == uid && 
            !exists(/databases/$(database)/documents/users/$(uid));
          allow update: if request.auth != null && request.auth.uid == uid; 
        }
      }
    } 
    

    其他信息:

    您可能已经知道代码不起作用。每次运行客户端代码时,当前用户都会被新文档完全替换。但是,如果我从规则中删除以下行,一切都按预期工作:

    allow update: if request.auth != null && request.auth.uid == uid;

    但是现在出现了问题,如何保护用户文档中的数据免受未经授权的修改?有什么建议吗?

5 个答案:

答案 0 :(得分:7)

如果您希望仅在文档尚不存在时才允许创建文档,请使用您已有的allow create规则。由于您还有allow update规则,因此也允许更新现有数据。

以下规则应该足够了:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{uid} {
      allow create: if request.auth != null && request.auth.uid == uid;
    }
  }
} 

您不需要exists()来电,因为allow create仅适用于数据不存在的情况。

现在回答你的问题:你应该澄清你的意思。现在只有经过身份验证的用户才能修改自己的记录。如果您不想允许写入任意数据,请检查它。

以下是一些例子: https://firebase.google.com/docs/firestore/security/rules-conditions#authentication

答案 1 :(得分:1)

您现在可以使用 create 方法完成此操作:

<块引用>

create(data) → {Promise.<WriteResult>}

使用提供的对象值创建文档。如果文档存在于其位置,这将导致写入失败。

DocumentReference.create

使用 Transactions 也可以做得更好:

<块引用>

create(documentRef, data) → {Transaction}

创建由提供的 DocumentReference 引用的文档。如果指定位置存在文档,则操作将导致事务失败。

Transaction.create

答案 2 :(得分:0)

this.db.doc('users /'+ uid).set({username:Santa},{merge:true}) 它应该合并而不是替换。省略的字段将保持不变。 https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference#set

答案 3 :(得分:0)

在代码中使用逻辑,但不在规则中使用。将addOnCompleteListener添加到用户集合中,并在获取结果后执行一些操作。

getUsers.document(userUID).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> doc) {
     if(!doc.getResult().exists()){
        //add new user
    }
}                       

}

规则:

match /UsersProfile/{document=**} {
  allow read, write: if request.auth != null;
}

答案 4 :(得分:0)

我曾经用过它,而且效果很好。基本上,我确保用户通过<form method="POST" action={loginaddress}> Email: <input type="text" name="Email" /> Password: <input type="password" name="Password" /> <input type="submit" value="Registrazione" /> </form> 登录,然后检查请求的资源是否为空。如果资源已经存在,则意味着用户存在。

我添加了request.auth != null,以防您只希望用户更改自己的数据。

allow update