9
votes

I'm currently trying to build small app on firebase as an evaluation of it. It looks interesting and super productive, but I have one problem with firestore rules.

I have one collection (games) with objects looking like this:

{
    "name":String,
    "description":String,
    "owners": 
    {
        "uid": String
        "uid2": String
    }
}

And rules set like this:

service cloud.firestore {
    match /databases/{database}/documents {
        match /games {
            match /{game} {
                allow write: if request.auth != null && request.resource.data.owners[request.auth.uid] == 'ADMIN';
                allow update: if request.auth != null && resource.data.owners[request.auth.uid] == 'ADMIN';
                allow read: if request.auth != null && resource.data.owners[request.auth.uid] == 'ADMIN';
            }
        }
    }
}

While write, update work fine. Read only works for single documents. When I try to read a collection I get access error as if user did not have right to it. The part that makes it not work is

resource.data.owners[request.auth.uid] == 'ADMIN'.

Adding a where("owners."+auth.uid,"==", 'ADMIN') to collection query does not help either.

What am I doing wrong here? Is there a suggested approach in firebase firestore for similar scenario?

EDIT: I tried adding 'get' and 'list' rules like this:

allow list: if request.auth != null;

allow get: if request.auth != null && resource.data.owners[request.auth.uid] == 'ADMIN';

It didn't work as expected. I expected it to allow me to list documents with where but if there is a document that I could not get I expected to get "Missing or insufficient permissions." What I was able to do was to list ALL documents but not read some of them directly (get rule works when trying to fetch single document but not when listing them from a collection).

EDIT 2: Looks like according to @MikeMcDonald my expectation was correct, but it is currently bugged. Waiting for the fix.

EDIT 3: It is now working fine with rules to get and list set in this way:

allow get, list: if request.auth != null && resource.data.owners[request.auth.uid] == 'ADMIN';

1
Note that write is a superset of update, so your currently write rule overwrites the update. Change it to create and you'll get a little closer to your intended goal. - Mike McDonald
@MikeMcDonald thanks, I will do that. I also found (after reading a bit closer) that there are two "reads". get and list later I will try to allow broader list maybe that it something that I need. Thanks! - Mariusz Zawadzki
read is the umbrella containing get and list. I've confirmed that the above is a bug--it should work, but we're not handling array members properly here. I'll follow up here once the fix is out. - Mike McDonald
@MikeMcDonald thanks. For now it is not super critical for me as I'm starting my advanture with firebase but would be nice to be able to do this. Waiting for the good news about the fix :-) - Mariusz Zawadzki
I've confirmed the bug is fixed now, so you should be able to use nested properties correctly. - Mike McDonald

1 Answers

0
votes

I think create and update works because they are part of write and condition 1 covers it.