2
votes

I'm building an angular firebase web app based on a chat. Simplified example of my structure:

|__ messages
       |__ room1
            |__ msg1
                  |__ author: ""
                  |__ message: ""
                  |__ user1: "user1"
                  |__ user2: "user2"
                  |__ user3: "user3"
|__ users
      |__ room1
            |__ user1: ...
            |__ user2: ...
            |__ user3: ...

I'm trying to write the rules ".write" for writing a new message (without cloud functions) that must have an author, a message and a number of users' id varying (here user1, user2, user3) which are here under /users (= a list of users varying). No problem with the author and the message but how can I do the part varying ? Is it even possible without cloud functions ?

This is what this part of the rules look now:

"$other": {
            ".validate": "$other === newData.val() && root.child('users/'+newData.val()).exists()"
          }

(if you have followed me so you should understand $other represents user1, user2 and user3 in my example).

EDIT:

Based on the example above, let's imagine a user user4 joined the room 1:

|__ messages
       |__ room1
            |__ msg1
                 |__ author: ""
                 |__ message: ""
                 |__ user1: "user1"
                 |__ user2: "user2"
                 |__ user3: "user3"
|__ users
      |__ room1
           |__ user1: ...
           |__ user2: ...
           |__ user3: ...
           |__ user4: ...

And now a user write a message:

|__ messages
      |__ room1
           |__ msg1
                 |__ author: ""
                 |__ message: ""
                 |__ user1: "user1"
                 |__ user2: "user2"
                 |__ user3: "user3"
           |__ msg2
                 |__ author: ""
                 |__ message: ""
                 |__ user1: "user1"
                 |__ user2: "user2"
                 |__ user3: "user3"
                 |__ user4: "user4"
|__ users
      |__ room1
           |__ user1: ...
           |__ user2: ...
           |__ user3: ...
           |__ user4: ...

The message must follow list of users.

1
Did you try the rule you gave? Because that's basically how a $ variable works: the rules under that apply to all child nodes for which no explicit name match exists. I would typically put the users under a users subnode though, just to make things more explicit. - Frank van Puffelen
Yes I did. The problem here is I can write a message with user1 and/or user2 and/or user3 or without all of them: this is the part missing checking that all of them are here. - Emerica
Ah, that means that you still want to add a newData.hasChildren(...) to the parent node's .validate rule. I'll write up an answer. - Frank van Puffelen

1 Answers

-1
votes

You want a few things here:

  1. The node must have user1, user2 and user3 properties.
  2. The value of those properties must exist as a key under /users

The relevant snippet of your rules:

"messages": {
  "$messageId": {
    ".validate": "newData.hasChildren('author', 'message', 'user1', 'user2', 'user3')",
    "author": {
      ".validate": "newData.isString()",
    }
    "message": {
      ".validate": "newData.isString()",
    }
    "$other": {
      ".validate": "$other === newData.val() && root.child('users/'+newData.val()).exists()"
    }

  }
}