I've been trying to build a system where users can be assigned to groups and groups can be assigned to resources. If a user is a member of a particular group, that user can access all resources shared with that group.
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.
A db structure and query which successfully handles this is:
<collection>
[doc]
<users>
[userId]: {
groups: [groupId, groupId...]
}
<groups>
[groupId]: {
members: [userId, userId...]
}
<resources>
[resourceId]: {
accessibleBy: [groupId, groupId...]
}
and the Firestore query:
db.collection('/resources').where("accessibleBy", "array-contains-any", [...aUsersGroups])
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.
match /resources/{resourceId} {
allow read: if resource.data.accessibleBy.hasAny(get(/databases/$(database)/documents/users/$(request.auth.uid)).data.groups);
}
It is worth noting that the above rule does work for individual Firestore get() requests.
Some options I have considered:
- I have contemplated normalising our data structure by group, but I imagine this would require lots of duplication of data which could become unmanageable.
- 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.
- 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.
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.
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! :)
Aucun commentaire:
Enregistrer un commentaire