'Cloud Firestore rules issues outside of console

I've got this set of Firestore rules :

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents/{path=**} {
     match /mycollections/{item} {
        function isSignedIn() {
          return request.auth != null
            && request.auth.token.firebase.sign_in_provider != 'anonymous';
        }
       
        function isInRoles(rsc, roles) {
            // return request.auth.uid in request.resource.data.users;
          return rsc != null 
          && rsc.data.roles[request.auth.uid] == "owner";
            //&& rsc.data.roles[request.auth.uid] in roles;
        }


        function isOneOfRoles(rsc, array) {
          return isSignedIn() && isInRoles(rsc, array);
        }

        function isValidNewItem() {
          return request.resource.data.roles[request.auth.uid] == 'owner'
             && request.auth.uid in request.resource.data.users;
        }
        
        function isNewSharedUser() {
            return request.resource.data.roles[getAuthLogin()] == 'writer'
             && request.auth.uid in request.resource.data.users
             && resource.data.shareLink == request.resource.data.shareLink;
        }

        function onlyContentChanged() {
          // Ensure that title and roles are unchanged and that no new
          // fields are added to the document.
          return request.resource.data.title == resource.data.title
            && request.resource.data.roles == resource.data.roles
            && request.resource.data.keys() == resource.data.keys();
        }

        // Split writing into creation, deletion, and updating. Only an
        // owner can create or delete a story but a writer can update
        // story content.
        allow create: if isValidNewItem();
        allow delete: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)), ['owner']);
        allow update: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)), ['owner'])
                      || (isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)), ['writer']) && onlyContentChanged())
                      || isNewSharedUser();
        allow read: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)), ['owner', 'writer', 'reader']);


                // example for permissions
        match /items/{subItem} {
                    allow delete: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)),
                                      ['owner', 'writer']);
            allow update: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)),
                                      ['owner', 'writer']);
          allow read: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)),
                                      ['owner', 'writer', 'reader']);
          allow create: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)),
                                        ['owner', 'writer']);
        }

                // example for permissions
        match /comments/{comment} {
          allow read: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)),
                                      ['owner', 'writer', 'commenter', 'reader']);
          allow create: if isOneOfRoles(get(/databases/$(database)/documents/mycollections/$(item)),
                                        ['owner', 'writer', 'commenter'])
                        && request.resource.data.user == request.auth.uid;
        }
     }
  }
}

With an authenticated user I can insert new list like this,

db.collection('mycollections').add({
  name: 'item ' + Date.now(),
  roles: roles, 
  users: [user.uid],
});

With looks like this in Firestore documents explorer

// doc id "CuwoleyStA5O3rY6Q5de"
{
  "roles": {"05CJ88QtXng1NzWQWJkMRB1bkRP2": "owner"}
  "name": "Ma nouvelle liste 1646895620631"
  "users": ["05CJ88QtXng1NzWQWJkMRB1bkRP2"]
}

After that, I can access it trough the Firestore console using the "rules tester"

enter image description here

But in my app, logged in with an authenticated user, I can't access it the collections of this user in /mycollections/*, I always end up with a an error of "Missing or insufficient permissions".

// query 
db.collection("mycollections").where('users', 'array-contains', user.uid)
  .onSnapshot((querySnapshot) => { });

=> Error in snapshot listener: FirebaseError: Missing or insufficient permissions.

Where's the rules error? the read access does check that there is a roles for this user which is right, and there is no details to debug the permissions issue.



Solution 1:[1]

Below is the syntax you can use to allow the authenticated user to read and write their own data as per explained in documentation

service cloud.firestore {
     match /databases/{database}/documents {
       // Make sure the uid of the requesting user matches name of the user
       // document. The wildcard expression {userId} makes the userId variable
       // available in rules.
       match /users/{userId} {
         allow read, update, delete: if request.auth != null && request.auth.uid == userId;
         allow create: if request.auth != null;
       }
     }
   }

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 Monali Ghotekar