Last active
July 13, 2024 20:23
Firebase security rules for a simple chat room model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"chat": { | |
// the list of chats may not be listed (no .read permissions here) | |
// a chat conversation | |
"$key": { | |
// if the chat hasn't been created yet, we allow read so there is a way | |
// to check this and create it; if it already exists, then authenticated | |
// user (specified by auth.id) must be in $key/users | |
".read": "auth != null && (!data.exists() || data.child('users').hasChild(auth.id))", | |
// list of users authorized to participate in chat | |
"users": { | |
// if the list doesn't exist, anybody can create it | |
// if it already exists, only users already in the list may modify it | |
".write": "!data.exists() || data.hasChild(auth.id)", | |
"$acc": { | |
// for now the value is just a 1, later it could be a read/write/super privilege | |
".validate": "newData.isNumber()" | |
} | |
}, | |
// timestamps recording last time each user has read this chat | |
"last": { | |
"$acc": { | |
// may only written by the authenticated user and if user is in $key/users | |
".write": "$acc === auth.id && root.child('chat/'+$key+'/users').hasChild($acc)", | |
".validate": "newData.isNumber()" | |
} | |
}, | |
"messages": { | |
"$msg": { | |
// to write a message, it must have all three fields (usr, ts, and msg) | |
// and the person writing must be in $key/users | |
".write": "root.child('chat/'+$key+'/users').hasChild(auth.id)", | |
".validate":"newData.hasChildren(['ts', 'usr', 'msg'])", | |
"usr": { | |
// may only create messages from myself | |
".validate": "newData.val() === auth.id" | |
}, | |
"msg": { | |
".validate": "newData.isString()" | |
}, | |
"ts": { | |
".validate": "newData.isNumber()" | |
} | |
} | |
} | |
} | |
} | |
} |
Please also note, that when writing to users you need to use update
not set
as this gotcha:
Also note
".write": "!data.exists() || data.hasChild(auth.id)",
should be
".write": "!data.exists() || data.hasChild(auth.uid)",
thank me later
The only thing I would like to add to this is a way for any user in the chat to delete the entire conversation which is not possible as they would have to have had access to the whole conversation, which would break the more granular write rules.
Probably needs a cloud function with a custom token, if anyone has an idea how to do that.
How do you include a list of users in realtime database?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I would also recommend creating all timestamps with cloud functions to account for differences in time zones and computer clocks. Also if the user updates his last read value, that should also be server updated