【问题标题】:Firebase Security Rule - Access a field in other documentFirebase 安全规则 - 访问其他文档中的字段
【发布时间】:2020-12-22 14:30:49
【问题描述】:

简介

我的数据库上有这个结构

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. 将用户名(文档 ID)和 userId(文档数据)添加到用户名集合中
  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;
      });

【问题讨论】:

  • 不要描述触发此问题的代码,而是编辑您的问题以显示最小的实际代码。
  • @FrankVanPuffelen 完成

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


【解决方案1】:

我认为问题在于您在安全规则全局函数中使用了 get()。将其设为本地并改用 getAfter 来等到批量写入的“终止”。

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

看看 Doug 的回答,他解释了 get 和 getAfer 之间的区别。

【讨论】:

    猜你喜欢
    • 2022-01-19
    • 2019-07-23
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2019-08-14
    • 2018-07-04
    • 1970-01-01
    • 2018-12-15
    相关资源
    最近更新 更多