'Firebase rules to give access to a path based on email address
I'm writing an app where it should be possible to invite users to a family. Once the user accepts they become members.
The data looks like this:
families: {
familyKey1: {
name: "First Family Name"
},
familyKey2: {
name: "Second Family Name"
},
},
invites: {
inviteKey1: {
familyKey: "familyKey1",
email: "[email protected]"
}
},
users: {
uid1: {
familyKey: "familyKey2"
}
}
I want a logged in user to be able to access the /families/familyKeyX/ path if:
- familyKeyX exists
/users/uidX/for the currently logged in user. - There is an invite under
/invites/inviteKeyX/where the email matches the currently logged in user and the invite contains familyKeyX
The first part works fine by creating a rule as follows:
"families": {
"$familyKey": {
".read": "root.child('users').child(auth.uid).child('familyKey').val() == $familyKey"
}
}
The second part however I cannot get to work. It could have been set up the same way if I could post the email as part of the path to the object but firebase does not allow the @ sign so I had to generate the inviteKey. But that key is unknown when I write the rule and firebase doesn't allow searches or wildcards on the rule path.
I was thinking of making the path {"invites": { "familyKeyX": { "email": "[email protected]"} } }. But that is a no-go since it only allows for one invite per family. There could be multiple users with different emails with pending invites. As soon I introduce a unique key to form a list of invites I don't know the path to write the rule...
How do I solve this?
Solution 1:[1]
In Firebase security rules you can read/check data at a known path in the database. You cannot however search for data under a specific path in the database.
So while in code you could do:
root.child("invites").orderBy("email").equalTo("[email protected]")
The equivalent to this query is not possible in security rules.
In order to be able to look up whether a given email has access to the family, you will need to store the email address of the user as a key in a separate map. Since . is not allowed inside a key, you'll have to encode that - typically by replacing it with a , which is allowed in a key and conveniently cannot appear in an email address.
So:
emailToInvites: {
"user@domain,tld": {
"familyKey1": "inviteKey1"
}
},
Now with this in place, you can replace . with , in the email address and then use that to look up if an invite exists under emailToInvites.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Frank van Puffelen |
