Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.9k views
in Technique[技术] by (71.8m points)

firebase - Firestore Security Rules - allow read subcollection based on its parent document data

I am implementing a chat app with Firestore, and I have a document for each chatroom in a collection "chats/" which have a subcollection "messages/" with all the messages in the room.

For accessing this subcollection, I need to check that the user is allowed to read it, checking that he is in the array of members which is in the parent document.

/chats
    /chatId
        /messages (subcollection)
            /messageId
        - members array (field)

Currently, I am doing this:

function isSignedIn() {
   return request.auth.uid != null;
}

match /chats/{chatId} {
    function isUserInChatRoom() {
      let userId = request.auth.uid;
      // A user is in the chatroom if he is in its members list
      return userId in resource.data.members;
    }
      
    // Only signed users which are in the chatroom can read its data
    allow read: if isSignedIn() && isUserInChatRoom(); 
       
    // The client side cannot modify the chats collection
    allow write, update, delete: if false;
      
    match /messages/{document=**} {
      // Only signed users which are in the chatroom can read its messages
      allow read: if isSignedIn() && isUserInChatRoom();
    }
}

But, it seems that isUserInChatRoom() doesnt work in the messages subcollection.

How can I achieve this?

question from:https://stackoverflow.com/questions/65854728/firestore-security-rules-allow-read-subcollection-based-on-its-parent-document

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I am not really into security rules syntax but you can try this (based on the docs)

match /chats/{chatId} {
  function isUserInChatRoom() {
    let userId = request.auth.uid;
    // A user is in the chatroom if he is in its members list
    return userId in resource.data.members;
  }

  function getChatRoomData() {
     return get(/databases/$(database)/documents/chats/$(chatId)).data;
  }
      
  // Only signed users which are in the chatroom can read its data
  allow read: if isSignedIn() && isUserInChatRoom(); 
       
  // The client side cannot modify the chats collection
  allow write, update, delete: if false;
      
  match /messages/{document=**} {
    function canReadMessages() {
      let userId = request.auth.uid;
      // A user can read the chatroom messages if he is a member of the chatroom
      return userId in getChatRoomData().members;
    }
        
    // Only signed users which are in the chatroom can read its messages
    allow read: if isSignedIn() && isUserInChatRoom();
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...