Firebase安全规则-访问其他文档中的字段

时间:2020-09-03 10:55:04

标签: javascript firebase google-cloud-firestore firebase-security

简介

我的数据库上有这个结构

C- usernames
   D- paola
        -> userId: 7384-aaL732-8923dsnio92202-peesK
   D- alex
        -> userId: ...
   D- adam
        -> userId: ...


 C- users
    D- userId of paola
        -> username: "paola"
        -> ...
    D- userId of alex
        -> username: "alex"
        -> ...
    D- userId of adam
        -> username: "adam"
        -> ...

我要在客户端注册用户,因此我不得不编写一些安全规则...

在我的客户代码中,我这样做:

  1. 将带有userId(文档数据)的用户名(文档ID)添加到用户名集合中
  2. 在用户集合中使用用户名和其他内容创建用户文档。

安全规则

因此,我的安全规则如下:

function isUsernameOwner(username) {
    return get(/databases/$(database)/documents/usernames/$(username)).data.userId == request.auth.uid;
}

match /users/{userId} {
   // Every people can read the users collection (might be in the sign in form)
   allow read: if true;
   
   // As the users creation is made in the client side, we have to make sure
   // it meets these requirements
   allow write: if isSignedIn() &&
        isSameUser(userId) &&
      request.resource.data.keys().hasOnly(['email', 'username', 'name', 'birthday']) &&
      isValidUsername(request.resource.data.username) &&
      isUsernameOwner(request.resource.data.username); // <------- If I remove this all works fine
}

问题

当我尝试注册时,得到“缺少权限或权限不足” ...我认为问题出在函数isUsernameOwner()中,但我不知道我在做什么错...我访问不正确吗?用户名文档中的字段userId?如果没有,那么批量写入是否可能不会顺序发生?

Pd:注册过程是使用批量写入(首先输入用户名,然后输入用户)进行的

更新

这是我进行批量写入的javascript代码:

 // Firebase.js
 createUser = (email, password, username, name, birthday) => {
    return this.auth
      .createUserWithEmailAndPassword(email, password)
      .then((currentUser) => {
        // Get the user id
        const userId = currentUser.user.uid;

        // Get a new Firestore batched write
        const batch = this.db.batch();

        // Create the new username document in the usernames collection with the user's id as field
        const usernameRef = this.db.collection("usernames").doc(username);
        batch.set(usernameRef, { userId });

        // Create the new user document in the users collection with all the relevant information
        const userRef = this.db.collection("users").doc(userId);
        birthday = firebase.firestore.Timestamp.fromDate(new Date(birthday)); // It is neccessary to convert the birthday to a valid Firebase Timestamp
        const data = {
          email,
          username,
          name,
          birthday,
        };
        batch.set(userRef, data);

        // Commit the batch
        return batch.commit();
      })
      .catch((err) => {
        throw err;
      });

1 个答案:

答案 0 :(得分:2)

我认为问题在于您正在安全规则全局函数中使用get()。将其设置为本地,然后使用getAfter来等待批处理写入的“终止”。

在这里您会看到一篇可能对您的案例有用的帖子:Firebase security rules difference between get() and getAfter()

只看道格的答案,他解释了get和getAfer之间的区别。