Uncaught Error in snapshot listener: FirebaseError: Missing or insufficient permissions for chatRooms

Uncaught Error in snapshot listener: FirebaseError: Missing or insufficient permissions for chatRooms

我在 Cloud Firestore 中存储了一些聊天室,需要对其进行保护,但我很难做到这一点。我在 React 中的状态看起来是这样的:

export class Messages extends React.Component {
    constructor(props) {
    super(props);
    this.boardID = this.props.settings.id;
    this.mainChatRef = database
      .collection("boards")
      .doc(boardID)
      .collection("chats")
      .doc("MAIN")
      .collection("messages");
    this.chatRoomsRef = database
      .collection("boards")
      .doc(boardID)
      .collection("chats");
    }

我在 React 中的查询如下所示:

latestMessages = (messageSnapshot) => {
    const message = [];
    messageSnapshot.forEach((doc) => {
      const { text, createdAt, uid } = doc.data();
      message.push({
        key: doc.id,
        text,
        createdAt,
        uid,
      });
    });
    this.setState({
      dataSource: message,
    });
}
queryRooms = async () => {
    const recentQuery = await this.chatRoomsRef
            .where("uidConcat", "in", [
              this.props.user.uid + this.state.value.objectID,
              this.state.value.objectID + this.props.user.uid,
            ])
            .get();
          for (const qSnap of recentQuery.docs) {
            const messagesRef = this.chatRoomsRef
              .doc(qSnap.id)
              .collection("messages")
              .orderBy("createdAt")
              .limitToLast(30);
            messagesRef.onSnapshot(this.latestMessages);
          }
}

我的数据库结构:

boards(collection)
  {boardId}
    chats (collection)
      MAIN 
      {chatId_1}
      {chatId_2}
        uidArray (has only two UIDs since it's for private chat)
        uidConcat: user1_uid+user2_uid
        messages(collection)
          {message1}
            createdAt
            text
            uid_creator
            uidArray (has UID of user1 and user2)

我试过这样保护我的板子:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /boards/{boardId} {
      allow read, write: if request.time < timestamp.data(2050, 5, 1);
      match /chats/MAIN/messages/{messagesId=**} {
        allow read, create: if request.auth.uid !=null;
      }
      match /chats/{chatId} {
        allow read, write: if request.auth.uid !=null;
        match /messages/{messagesId=**} {
          allow read: if (request.auth.uid in get(/databases/{database}/documents/boards/
                      {boardId}/chats/{chatId}/messages/{messageId}).data.uidArray) 
                      && request.query.limit <= 30 && request.query.orderBy.createdAt == 'ASC';
          allow write: if request.auth.uid != null;
        }
      }
    }
  }
}

我希望任何经过身份验证的人都可以始终访问板的主要聊天以及我编写它的方式。对于私人房间,我不断收到错误消息。我已经阅读了文档并且我知道 Security rules are not filters 这就是为什么我添加了一堆 AND 语句以试图使我的证券与我在 React 中编写的代码查询非常相似但我仍然不断得到 Uncaught Errors in snapshot listener: FirebaseError: Missing or insufficient permissions .我目前正在编写我的规则以在消息集合中的文档级别进行保护,但理想情况下我想在聊天集合中的文档级别进行保护并检查我的 request.auth.uid 是否在文档字段 uidArray 中,如下所示:

match /chats/{chatId=**} {
  allow read, write if request.auth.uid in resource.data.uidArray
}

我想保护聊天集合中的文档会更安全,但任何保护消息的方法都非常受欢迎。

问题是您正试图根据以下行中的每一行数据在您的规则中进行动态查找:get(/databases/{database}/documents/boards/{boardId}/chats/{chatId}/messages/{messageId}).data.uidArray)

这里要理解的关键点是规则在执行查询时不查看实际数据。获取操作有点不同,因为只有一条记录要获取,但对于查询,它只检查查询以确保它无法获取与您的规则不匹配的数据;它实际上从不加载要检查的数据。这在文档 here and there's a good video overviewing this here. A deeper dive is here.

中有所介绍

基于角色的访问是一个复杂的主题,考虑到解决方案的广泛性以及它们对您的用例的具体性,可能不容易在 Stack Overflow 中回答。但是一个天真的替代方法是列出 /chats/{chatId} 中的成员并使用这样的规则:

   match /chats/{chatId} {
     // scoped to chats/{chatId} doc
     function isChatMember(uid) {
        // assumes this document contains an array of
        // uids allowed to read the messages subcollection
        return uid in resource.data.members;
     }

     match /messages/{messagesId=**} {
        allow read: if isChatMember(request.auth.uid)
     }
   }