0

Long-story short, I would like unique roomIds and roomNames. Therefore, I would like to add a firebase validation rule to disallow any room object writes to the DB if the roomName exists.

This is the firebaseDb JSON:

{
  "rooms" : {
    "-M8z0o2NkOuAYoqa2Yhn" : {
      "roomId" : "-M8z0o2NkOuAYoqa2Yhn", // push().getKey();
      "roomName" : "blueBUCKET",
    },
    "-M8zBrzRYfGE-iZaIoAV" : {
      "roomId" : "-M8zBrzRYfGE-iZaIoAV", // push().getKey()
      "roomName" : "redBUCKET",
      }
    }
  },
}

This is my intended validation:

"rooms" : {
        "$roomId" : { 
          ".read" : "auth !== null",
            ".write" :  "!data.exists()  ||
                                data.child('userList'+'/'+auth.uid).exists()",
            ".validate" : "root.child('rooms/'+$roomId+'/roomName').val() !== newData.child('roomName').val()"
        }
      }

Unfortunately, it does not exhibit the correct behavior when I used the rules playground. Given the below, the simulated set should be disallowed given a room 'blueBUCKET' already exists.

Location: /rooms/-M8zBrzRYfGE-iZaIoAV
Data: { "roomName": "blueBUCKET" }
Authenticated: Yes w. UserId: QwKjHPsLdrcOrkiOLRs6pYZTOnE2

To be thorough, I played around with the rules playground further with the above parameters and this was the behavior. Clearly my rule is unable to reconcile the $roomId wildcard... Did I misplace my 'validate' assertion? or is this a matter of re-writin the rule?

// PASSED AS EXPECTED
".validate" : "root.child('rooms/-M8zBrzRYfGE-iZaIoAV/roomName').val() === 'redBUCKET'"
".validate" : "root.child('rooms/'+$roomId+'/roomName').val() === 'redBUCKET'"
".validate" : "root.child('rooms/-M8z0o2NkOuAYoqa2Yhn/roomName').val() === 'blueBUCKET'"
// FAILED - UNKNOWN WHY?
".validate" : "root.child('rooms/'+$roomId+'/roomName').val() === 'blueBUCKET'"
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • There is no way to enforce that a specific value is unique among all other values. To enforce uniqueness, you must have a node where each child **key** is the room name. See my answer here for a longer explanation: https://stackoverflow.com/questions/35243492/firebase-android-make-username-unique and Marein's answer here: https://stackoverflow.com/a/29983839 – Frank van Puffelen Jun 04 '20 at 14:31
  • Since you want both IDs and keys to be unique, you'll need to have two nodes: one where the IDs are the key (that's what you currently have), and one where the names are the key. In your security rules you then validate that both are updated in tandem. – Frank van Puffelen Jun 04 '20 at 14:34
  • Thank you very helpful! I really appreciate your links to previous Q&As; not an easy question to find the answer to given how many results are returned by my key search terms. – Emily Hodge Jun 05 '20 at 15:45
  • Yeah, it often depends on knowing the right search terms. I'll gladly use my advantage on that front to find you good links. – Frank van Puffelen Jun 05 '20 at 15:50

0 Answers0