StackLuuk
StackLuuk

Reputation: 35

Firebase Realtime Rules - Give access when some child contains value x?

I have been trying to get this rule to work for some time now and I just don't seem to be able to figure it out.

The structure of my data is as follows:

 games { 
    *gameid* {
        gamecode: *some gamecode*
        players {
           0 {
              playerId: *some playerid*
             }
           1 {
              playerId: *some playerid*
             }
           etc.
        }
        etc.
    }

So basically I have games, where every game has a unique id and contains the following data: gamecode, a list of players and some more data. The problem is that I want only the players in the players list of the game to have access to read ALL the players of that game, so not only themselves.

I think this requires some sort of second wildcard but I can't seem to find if this is possible in firebase rules.

Here is what I have come up with that gets the closest to being the solution:

"games": {
      "$gid": {
        "players": {
            ".read": "auth.uid != null && data.child('$uid').child('playerId').val() === auth.uid",
            ".write": false
        }
      }
    } 

This does not work, probably because it uses '$uid' as the actual id instead of a wildcard. When I replace it with the actual key of the player, it does work.

Does anyone know if and how I can do this? Thanks in advance.

EDIT:

I settled on using the uid's as actual keys for the players and using data.child(auth.uid).exists() to check if the player exists.

Upvotes: 1

Views: 266

Answers (1)

Stratubas
Stratubas

Reputation: 3067

I don't think you can use such a wildcard.

One solution would be to manually look "everywhere", like this:

"auth.uid == data.child('0/playerId').val() ||
 auth.uid == data.child('1/playerId').val() ||
 auth.uid == data.child('2/playerId').val()" // up to max allowed players

Or you can modify your data structure to something like this:

 games { 
    *gameid* {
        gamecode: *some gamecode*
        players {
           0 {
              playerId: *some playerid*
             }
           1 {
              playerId: *some playerid*
             }
           etc.
        }
        playerIds {
           somePlayerId: true
           someOtherPlayerId: true
        }
    }

so you can simply do

"data.parent().child('playerIds/'+auth.uid).exists()"

without changing your code drastically (you'd still be using players as array).

Or you can ditch the array completely:

 games { 
    *gameid* {
        gamecode: *some gamecode*
        players {
           somePlayerId {
              index: 0
              playerId: *some playerid*
             }
           someOtherPlayerId {
              index: 1
              playerId: *some other playerid*
             }
           etc.
        }
    }

and the rule becomes

"data.child(auth.uid).exists()"

(I haven't tested these, look out for typos)

Upvotes: 1

Related Questions