0

I am trying to restrict writing to two related firebase nodes. I have a the following data structure on firebase:

"mainsibblings" : {
    "-L9ygIWI-TKeNZvQ-TmP" : {
      "MACaddress" : "111111111111",
    },
},
"slavesibbling" : {
    "111111111111" : {
      "onMainSibling" : "-L9ygIWI-TKeNZvQ-TmP",
    }
}

The slavesibbling pushkey is a unique MAC Address (freely created and updated by the user).

Conditions:

1) user should have permission to write a new mainsibbling and slavesibbling

2) shouldn't have permission to overwrite neither (mainsibbling & slavesibbling) if slavesibbling key (in this case: "111111111111") already exists.

3) the "owner" should be able to update both node even after he creates them

So if someone types a MAC Address that is registered already, the child nodes can't be updated, but if the user (referenced in ownerID) want to update a MAC Address he has created he should be able to do it.

How do I write the firebase database rules to control this? I am trying this to prevent duplicates but it's not working:

 "mainsibblings": {
    ".read": true,
    "$pushKey": {
       ".write": "data.child('MACaddress').val() != newData.child('MACaddress').val()",  
    }
},
"slavesibbling": {
    "$MACaddress":{         
        ".read": true,
        ".write": "!data.hasChild(newData.val())",     
  }
}

This is the write operation I want to allow/disallow (I have replaced the MACaddress variable for a hardcoded MACaddress):

function AddSibblings(newMainSib, newSlaveSib) {  
  var MACaddress = "111111111111";
  var ownerID = "QXXds7d33ceyecc4inoe33p_3";
  mainRef.child(MACaddress).set(this.newMainSib);
  otherRef.child(MACaddress).set(this.newSlaveSib)

  mainRef.child(MACaddress).child('ownerID').set(ownerID);
  otherRef.child(MACaddress).child('ownerID').set(ownerID);
  otherRef.child(MACaddress).child('onMainSibbling').set(MACaddress);
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

0

There is no way in Firebase security rules to find whether a specific value exists in a list of children. If you want to ensure that a value is unique, you should use that value as the key of a collection.

For example in your case you can easily change the data to use the MAC address as the key for both mainsiblings and slavesiblings:

"mainsiblings" : {
    "111111111111" : {
      "MACaddress" : "111111111111",
    },
},
"slavesibbling" : {
    "111111111111" : {
      "onMainSibling" : "111111111111",
    }
}

And

"mainsiblings" : {
    "111111111111" : {
      "MACaddress" : "111111111111",
    },
    "223344556677" : {
      "MACaddress" : "223344556677",
    }
},
"slavesibbling" : {
    "111111111111" : {
      "onMainSibling" : "111111111111",
    },
    "223344556677" : {
      "onMainSibling" : "223344556677",
    }
}

Since property names are by definition unique in JSON, there is no way to have duplicate MAC addresses in this data structure.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Even if one of the nodes (in this case the "slavesibbling") has the reference key? Something like: `if slavesibbling.key is somevariable then don't allow writing to both mainsibbling & slavesibbling`? – Joao Alves Marrucho Apr 13 '18 at 13:41
  • or in something closer to firebase rules like: `"mainsibbling": { ".write": "root.child('slavesibbling').$MACaddress != newData.child('MACaddress') ", }` – Joao Alves Marrucho Apr 13 '18 at 13:47
  • Hmm... on second reading your second JSON sample **can't** happen since `slavesibbling` now has the `111111111111` property twice. No database rules are needed to enforce this: JSON by definition requires property/child names to be unique. I'm not really clear on your question anymore: can you add the **minimal** code to your question of a write operation that you want to disallow? – Frank van Puffelen Apr 13 '18 at 14:11
  • I have added the code. Notice that I have changed the push Key of the mainSiblling as you suggested if it makes it any easier. However I would like to understand both ways – Joao Alves Marrucho Apr 13 '18 at 14:27
  • There are still some variables in there for which I don't fully understand what they mean. Please reduce the code to something self-contained, without any external variables (just reproduce the problem with hard-coded values). I.e. "with this JSON, this write should be allowed, but this write should be rejected" – Frank van Puffelen Apr 13 '18 at 15:06
  • Sorry about that. Done – Joao Alves Marrucho Apr 13 '18 at 15:14
  • Sorry, I still don't understand. I've taken your rules and code, added the rules to my database, and the code here: https://jsbin.com/boceqol/1/edit?js,console. Can you modify the code to reproduce the problem? – Frank van Puffelen Apr 13 '18 at 17:01