Attilio
Attilio

Reputation: 583

Firebase database Rules o how to filter data

the goal I would to achieve is to show to an authenticated user a list of "Events" shared with other users, and in particular, only the events where the user itself is member of.

the initial structure I had in mind was:

events:{ 
   "eventId1":{ 
      "title":"some text",
      "members":{
          "myAuthUID":true,
          "anotheUserUId":true
      }
   }
   "eventId2":{ 
      "title":"some text",
      "members":{
          "anotheUserUId":true
      }
   }
}

the rules I put in place is the following one. but it failed the porpouse:

{
  "rules": {
    ".read":"auth.uid !== null",
    ".write": "auth.uid !== null",
    "events":{
      "$evtId":{
       ".read":"data.child('members').child(auth.uid).exists()",
        ".write": "data.child('admins').hasChild(auth.uid)",


      }
    }
  }
}

calling /events all the events are showm

calling /events/eventId2 with myAuthUID it succeed.

the result must be, for sure, to show only the eventId1 to muAuthUser

could you please help me to structure better the data model and/or refund the rule?

meanwhile I'll look for a solution to this simple problem :)

thanks

Upvotes: 0

Views: 518

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598887

First things first: that top-level ".read":"auth.uid !== null" means that all authenticated users can read the entire database. Once you've granted a permisson on a certain level in the database, you can't take that permission away at a lower level. So your .read rule on /events/$evtId is useless at the moment.

The next step is that rules are not filters. Firebase checks your rules when you attach the listener, and the entire condition will be evaluated at that time (and only at that time). In practice this means that security rules cannot be used to filter data. This has been asked frequently before, so I recommend you check out some of those previous questions on the topic.

Recently Firebase added the ability to secure the queries that you allow on a certain node. So you could allow reads from /users, but then only if they order/filter on a certain property. For more on this, see the documentation on query based rules. However, I'm not sure this will allow your use-case. There was a similar question moments ago, so I recommend monitoring that one too, in case someone answers there: How to filter by orderByChild containing a string in Firebase query-based rules

My usual solution for your use-case: your current data model allows you to efficiently read/query the members for an event. It does not allow you to efficiently read the events for a member. To allow the latter, add an additional data structure:

members
  memberId1:
    events
      eventId1: true
      eventId2: true
  memberId2:
    events
      eventId1: true
      eventId3: true

Now this is a lot easier to secure.

Upvotes: 1

Related Questions