0

In an iOS messaging app I am creating, an outline of the structure for the messages node is as follows

    "messages": {
        "$uid":{
            ".read": "auth.uid == $uid",
            "$messageId":{

                // insert .write rule here

                "toUid":{
                    // if its a group message then there would be multiple "$toUid" children
                    "$toUid":{

                    },
                },
                "fromUid":{
                    "$fromUid":{

                    }
                },
                "timeStamp":{

                },
                "group":{
                    "isGroupMessage":{

                    },
                    "groupId":{

                    }
                }
            }
        }
    },

I would like to add a write rule after $messageId to ensure that the "$toUid" or "$fromUid" is equal to the $uid .

any ideas how I can do this?

Is the following the best way to do it:

 ".write": "newData.child('toUid').hasChild($uid) || newData.child('fromUid').hasChild($uid)",

** I have gone with the solution below - changes structure but is the quickest / safest security rules for us to use for now.

The MVP is initially not going to have group messages (may be irrelevant but the logic could be different) - so alternatively I could add a wildCard child variable "$friendUid" and then have the following rule below that.

 "$messageId":{
    "$friendUid":{
    ".write": "$uid == auth.uid || $friendUid == auth.uid",
Edward
  • 2,864
  • 2
  • 29
  • 39
  • 1
    You cannot in a security check if a list contains a specific value. You can only check if a specific key exists. So your first `.write` snippet indeed seems the right approach. Are you having problems with it? – Frank van Puffelen Mar 07 '17 at 15:04
  • 1
    @FrankvanPuffelen think I've figured it out thanks. I'm going to add an extra layer with a "$friendUid" wildcard variable, which just seems the easiest / most secure way for us going forward. issue was more thinking about features further down the line, which is irrelevant with no users :) (haven't released yet) – Edward Mar 07 '17 at 15:29
  • 1
    Sounds good Edward. Can you post your solution as an answer? Self-answers are encouraged on Stack Overflow and a great way to build your reputation. – Frank van Puffelen Mar 07 '17 at 18:28
  • @FrankvanPuffelen I have added my answer below and will make it accepted answer when I can. As a cheeky side note, any chance you can check this question out - http://stackoverflow.com/questions/42653967/firebase-storage-custom-metadata-security-rule-for-list-of-uids – Edward Mar 08 '17 at 17:12

1 Answers1

2

So this is how I decided to structure my Firebase database rules for my messages node. I added an extra child node with a wildcard variable of "$friendUid", in order to easily refer to it and lockdown my messages branch.

    "messages": {
        "$uid":{
            ".read": "auth.uid == $uid",
            "$messageId":{
                "$friendUid":{
                    ".write": "$uid == auth.uid || $friendUid == auth.uid",
                    ".validate": "root.child('friends/'+$uid+'/'+$friendUid).exists()",

                    "toUid":{
                        "$toUid":{
                            ".validate": "$toUid == $friendUid || $toUid == $uid"
                        },
                    },
                    "fromUid":{
                        "$fromUid":{
                            ".validate": "$fromUid == $friendUid || $fromUid == $uid"
                        },
                    },
                    "timeStamp":{
                        ".validate":"newData.isNumber()"
                    },
                    "$other":{
                        ".validate": false
                    }
                }
            }
        }
    },
Edward
  • 2,864
  • 2
  • 29
  • 39