title: Is there an access pattern that enables this many-to-many-to-many relationship that can be handled by security rules when using Firestore onSnapshot?
body: <p>I've been trying to build a system where <strong>users</strong> can be assigned to <strong>groups</strong> and groups can be assigned to <strong>resources</strong>. If a user is a member of a particular group, that user can access all resources shared with that group.</p>
  <p>A user can be part of multiple groups and a resource can be shared with multiple groups. For example, a user may be part of the 'admins' and 'development team' groups, and a resource may be shared with the 'marketing' and 'development team' groups.</p>
  <p>A db structure and query which successfully handles this is:</p>
  <pre><code>&lt;collection&gt;
      [doc]
  
  &lt;users&gt;
      [userId]: {
          groups: [groupId, groupId...]
      }
  
  &lt;groups&gt;
      [groupId]: {
          members: [userId, userId...]
      }
  
  &lt;resources&gt;
      [resourceId]: {
          accessibleBy: [groupId, groupId...]
      }
  </code></pre>
  <p>and the Firestore query:</p>
  <pre><code>db.collection('/resources').where(&quot;accessibleBy&quot;, &quot;array-contains-any&quot;, [...aUsersGroups])
  </code></pre>
  <p>This works great. However, where this gets difficult is security rules. I am using onSnapshot listeners and the rule I initially created (below) fails, I assume because it needs to check access to each document based on the 'accessibleBy' field, which would get very computationally expensive when accessing large collections.</p>
  <pre><code> match /resources/{resourceId} {
       allow read: if resource.data.accessibleBy.hasAny(get(/databases/$(database)/documents/users/$(request.auth.uid)).data.groups);
   }
  </code></pre>
  <p>It is worth noting that the above rule does work for individual Firestore get() requests.</p>
  <p>Some options I have considered:</p>
  <ul>
  <li>I have contemplated normalising our data structure by group, but I imagine this would require lots of duplication of data which could become unmanageable.</li>
  <li>I have also contemplated building a system that just uses get() calls instead of listeners but I do need realtime(ish) updates and this would probably become inefficient.</li>
  <li>Finally I have contemplated using a nodejs environment but I am not familiar with access patterns using a server and I would still be looking to achieve realtime functionality.</li>
  </ul>
  <p>I am willing to only assign users to one group (or perhaps one group, plus default read access), but I do need the functionality to share resources across multiple groups.</p>
  <p>Firestore may not be the answer to my problems here but I thought I'd ask the community before I look elsewhere. Thank you in advance! :)</p>