'How to use Flutter (StreamBuilder) query with Firestore rules?

I have a admin app and a user app. All data go in one database and I want to make sure that admin have only permission to ready there own users and not from other admins. So my solution was to give the admin a id and if the admin create a new user in the software, the user will get the same id (not userID just a random id for "assignment").

Firebase rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    //User
    match /Users/{userID}{
      allow create: if false;
      allow delete, write: if isUserOfAdmin(userID);
      allow read: if isUserOwner(userID);
      allow update: if isValidUserRequest(); 

      function isUserOwner(userID){
        return isUserOfAdmin(userID) || isLoggedInUser();
      }

      function isUserOfAdmin(userID){
        return isLoggedInUserAdmin() && (get(/databases/$(database)/documents/Users/$(userID)).data.adminID == getAdminIDofLoggedInAdmin());
      }
      function getAdminIDofLoggedInAdmin(){
        return get(/databases/$(database)/documents/Admins/$(request.auth.uid)).data.adminID;
      }

      function isLoggedInUser(){
        return isUserLoggedIn() && get(/databases/$(database)/documents/Users/$(request.auth.uid)) != null;
      }
      function isLoggedInUserAdmin(){
        return isUserLoggedIn() && get(/databases/$(database)/documents/Admins/$(request.auth.uid)) != null;
      }
    }
  }

Important here is the allow read:.

In admin software:

body: SafeArea(
  child: FutureBuilder(
    future: firebase.getAdminID(),
    builder: (context1, snapshot1) {
      final adminID = snapshot1.data;
      print(adminID.toString() + " snapshot 3");
      if (snapshot1.hasData) {
        print(adminID.toString() + " snapshot 4");
        return StreamBuilder(
             stream:
                 base
                .collection('Users')
                .where('adminID', isEqualTo: adminID)
                .snapshots(),
            builder: (BuildContext context,
                AsyncSnapshot<QuerySnapshot> snapshot) {
              if (snapshot.hasData) {

The Error: [cloud_firestore/permission-denied] Missing or insufficient permissions.

Side note, in PlayGround of Firebase Firestore rules, my request is working. I rename some functions/methods etc. so maybe I read over some renaming. The prints proved that the adminID was requested.

Struggling 3 days with help from friends but no solution yet. I would be really thankful about some help.



Solution 1:[1]

The rules are the problem. I had to use resource.data.adminID instead of get(/databases/$(database)/documents/Users/$(userID)).data.adminID

With get you can search for a specific thing everywhere in the database. With resource you search in the path ( for my example match /Users/{userID}{}) and firebase is looking once for the adminID in every doc.

Simple as that xD

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 niklasknuf