title: Firestore query permission denied
body: <p>I've got a problem with structuring my security rules for Firestore. Specifically: </p>
  
  <p><code>db.collection("boards").whereEqualTo("roles.${me.email}", "admin")</code> always fails with <code>PERMISSION_DENIED</code> error. </p>
  
  <p>What's weird, getting single documents works like a charm. From what I understand this query will not violate any of my security rules. It should always return a subcollection of a <code>isAnyRole(resource)</code> function. </p>
  
  <p>My security rules:</p>
  
  <pre><code>service cloud.firestore {
  match /databases/{database}/documents {
  
  function isSignedIn() {
      return request.auth != null;
  }
  
  match /boards/{board} {
  
      //Board has owner and 3 possible roles:
      //* admin: can do everything, like an owner, but can be removed
      //* idea_reader: has read only access to the board and its ideas
      //* idea_editor: har write access to ideas and read access to the board itself
      function roles() {
      return ['admin', 'idea_reader', 'idea_editor'];
          }
  
      function isOwner(rsc) {
      return request.auth.uid == rsc.data.ownerId;
    }
  
    function getRole(rsc) {
      return rsc.data.roles[request.auth.token.email];
    }
  
    function isOneOfRoles(rsc, array) {
      // Determine if the user is one of an array of roles
      return isSignedIn() &amp;&amp; (getRole(rsc) in array);
    }
  
    function isAnyRole(rsc) {
      //Determine if user is any role or owner. 
      return isOwner(rsc) || isOneOfRoles(rsc, roles());
    }
  
    function isValidNewBoard() {
      // Valid if story does not exist and data is set correctly
      return resource == null
                  &amp;&amp; request.resource.data.ownerId == request.auth.uid
            &amp;&amp; request.resource.data.name != null;
    }
  
    function isValidBoardUpdate() {
      // Valid if ownerId didn't change and called by owner of admin
      return (isOwner(resource) || isOneOfRoles(resource, ['admin']))
                      &amp;&amp; resource.data.ownerId == request.resource.data.ownerId
                      &amp;&amp; request.resource.data.name != null;
    }
  
    // Owner and admin can edit. Owner can delete. 
    allow write: if isValidNewBoard() || isValidBoardUpdate();
    allow delete: if isOwner(resource);
  
    // Owner and any role can read 
    allow read: if isAnyRole(resource);
  
    match /ideas/{idea} {
      // Any role can read ideas 
      allow read: if isAnyRole(get(/databases/$(database)/documents/boards/$(board)));
  
      //Owner, admin and idea_editor can edit ideas
      allow write: if isOwner(get(/databases/$(database)/documents/boards/$(board)))
                                  || isOneOfRoles(get(/databases/$(database)/documents/boards/$(board)), ['admin', 'idea_editor']);
    }
  
  }
  
  match /{document=**} {
    allow read, write: if false;
  }
  
  }
  }
  </code></pre>