Alexander
Alexander

Reputation: 33

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:

  1. familyKeyX exists /users/uidX/ for the currently logged in user.
  2. 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?

Upvotes: 0

Views: 266

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598728

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.

Upvotes: 1

Related Questions