简体   繁体   中英

Filter Firebase Realtime Database data based on authentication

I'm using Firebase Realtime Database as the datastore for an Android app, and right now I'm trying to implement some basic filtering based on user permissions.

Here's my database:

{
    "admins" : { 
        `user1hash` : true
    },
    "clients" : {
        "client1hash" : {
            "owner": "user1hash",
            "name" : "Client 1"
        },
        "client2hash" : {
            "owner": "user1hash",
            "name" : "Client 2"
        },
        "client3hash" : {
            "owner": "user2hash",
            "name" : "Client 3"
        }
    }
}

I followed the examples in the Query-based Rules section here https://firebase.google.com/docs/database/security/securing-data and defined my rules like this:

{
  "rules": {
    "clients": {
      ".indexOn": "owner",
        ".read": "auth.uid != null && (root.child('admins/' + auth.uid).val() == true || query.orderByChild == 'owner' && query.equalTo == auth.uid)",
        ".write": "auth.uid != null",
        ".validate": "newData.hasChildren(['owner']) && newData.child('owner').val() == auth.uid"
    }
  }
}

And this is my client code (Android):

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        String authUser = FirebaseAuth.getInstance().getCurrentUser().getUid();
        DatabaseReference clientsDatabase = database.getReference("clients").orderByChild("owner").equalTo(authUser).getRef();
        clientsDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                // handle success
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                // handle error
            }
        });

So basically I just want to be able to fetch all clients, but filter the results according to the access rules of the current user. Access rules are pretty simple, an user can only see the clients where he is the owner , except for admin users who can see all clients. For example if this was run by user1 which is an admin he should see all three clients, but if this is run by user2 which is a regular user he should only see client 3.

This implementation is working for admins, but I get a permissions error for regular users.

I tried the rules simulator in Firebase console, but it doesn't provide any documentation on how to use queries. Anyway I tried adding the query as a regular URL query string like /clients?orderByChild=owner&equalTo=user2hash , but this returns an empty error on the simulator with no description of the cause. The error I'm getting on the Android side doesn't have any description either, just a generic permissions error.

The problem is in this statement:

DatabaseReference clientsDatabase = 
    database.getReference("clients")
            .orderByChild("owner")
            .equalTo(authUser)
            .getRef();

Specifically that last line getRef() , which throws everything away that you've done to build the query. The above statement leaves clientsDatabase exactly the same as:

DatabaseReference clientsDatabase = database.getReference("clients");

Which explains quite well why the statement fails.

You need to keep the Query that you get back and attach your listener on that:

DatabaseReference clientsDatabase = database.getReference("clients");
Query query = clientsDatabase.orderByChild("owner").equalTo(authUser);
query.addListenerForSingleValueEvent(new ValueEventListener() { ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM