0

I try to return to the user the list of his chat with a rule. So I don't know the id of the conversations. I have tried several methods but none of them work because you have to know the chat id.

Database :

{
  "Chats" : {
    "-MPnCVZSVi5C3QbHnXl3" : {
      "messages" : [ {
        "createdAt" : 1609324431814,
        "text" : "Gggwdhj",
        "user" : "3Oi1atf8l2P4Vgsb8tZOGxpUg7q2"
      } ],
      "name" : "toto",
      "users" : {
        "3Oi1atf8l2P4Vgsb8tZOGxpUg7q2" : true
      }
    }
  }
}

Rules :

   {
      "rules": {
           
         "Chats": {
            
              ".read": "data.child('users').hasChild(auth.uid)",
              ".write": "true"
            
    
          }
      }
    }

Result : enter image description here

But when I access from the react native application. Access to chats does not pass for an authenticated user(uid : 3Oi1atf8l2P4Vgsb8tZOGxpUg7q2)

*The read failed: Error: permission_denied at /Chats: Client doesn't have permission to access the desired data.

Rules :

{
  "rules": {
     "Chats": {
        "$uid":{
          ".read": "data.child('users').hasChild(auth.uid)",
          ".write": "true"
        }

      }
  }
}

Query :

 firebase.database().ref('Chats')
        .limitToLast(20)
        .on('child_added', snapshot => {
            callback(this.parse(snapshot))
        }, function (errorObject) {
            console.log("The read failed: " + errorObject);
        });
khpo
  • 11
  • 2
  • You've included a picture of the JSON tree and security rules in your question. Please replace them with the actual JSON and rules as text, which you can easily get by clicking the Export JSON link in the overflow menu (⠇) of [your Firebase Database console](https://console.firebase.google.com/project/_/database/data/). Having these as text makes them searchable, allows us to easily use them to test with your actual data and use them in our answer and in general is just a Good Thing to do. – Frank van Puffelen Dec 30 '20 at 14:52
  • In addition: please show the code of how you're reading from the database. Security rules only have meaning in combination with the code that triggers them. – Frank van Puffelen Dec 30 '20 at 14:53

1 Answers1

0

If you want to apply a certain rule/set of rules to all child nodes, you can use a $ wildcard like this:

{
  "rules": {           
     "Chats": {
        "$chatId": {
           ".read": "data.child('users').hasChild(auth.uid)",
           ".write": "true"
        }            
     }
  }
}

For more on this, see the Firebase documentation on $ wildcard variables. In general I'd recommend reading the Firebase docs on security rules end-to-end as they're not that long, and a few hours spent there now will save you much more time down the line.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thank you for your reply. But I do not know the id of the conversation. I want to list the conversations that contain the uid of the connected user – khpo Dec 30 '20 at 21:20
  • That requires a query, which is not possible in the Firebase console and rules playground. But my answer shows how to secure chat child nodes so that only a user that is in each room has access to them. – Frank van Puffelen Dec 30 '20 at 21:41
  • After the rule change the chats are no longer accessible – khpo Jan 04 '21 at 21:40
  • That is correct. With these rules you can no longer read the `Chats` node. If you want to allow the user to read a subset of the nodes under `Chat`, have a look at https://firebase.google.com/docs/database/security/rules-conditions#query-based_rules – Frank van Puffelen Jan 05 '21 at 00:30
  • I tried this option but it works if I had a property with the auth.id but it is an array of users. Each Chat contains an array of users. Thanks for your help – khpo Jan 05 '21 at 08:01
  • Yeah, I indeed don't think you can create a query to get the chats for a specific user with your current data model. And since security rules don't filter data on their own, that means you can't secure access to the entire `Chats` node. Consider adding an additional top-level structure mapping users to chats, like I've shown [here](https://stackoverflow.com/questions/40656589/firebase-query-if-child-of-child-contains-a-value). That way you can secure `/chats/$chatId` as I've shown above, and use the new structure to find what individual chat nodes to access. – Frank van Puffelen Jan 05 '21 at 15:25