Hello.
I am trying to set up a ruleset for a new Firestore project where we have the following root collections:
users
organisation
Under users we have users/userid/ar/organisationid (ar for access rights)
This document should define what access rights the user have for a given organisation. The point being that many users can have access to one or more organisation in this saas application.
I want all the documents and all the subcollections under the organisation to be checked agains this access right.
This works perfectly get and write, but listing of data gives an access error, and the only way i found to restrict the list data is to add an array on the document that list the users, and also filter on this client side. This is not a solution that is maintainable for production since there will be alot of subcollections with many documents.
Is there any suggestions? Any other way i can make the listing work for firestore? Is there better way to structure the data, or anything I am missing?
Only other way i can see is to use functions to do the check server side for the listing, but then we loose the awesome stuff in @angular/fire.
Filtering client side is not good enough security.
Thank you.
Rules as of now:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth.uid == userId;
match /ar/{organisationDoc} {
allow read: if request.auth.uid == userId;
allow write: if false;
}
}
// read
match /organisations/{oId} {
allow get: if exists(/databases/$(database)/documents/users/$(request.auth.uid)/ar/$(oId));
allow list: if request.auth.uid in resource.data.users;
match /{all=**} {
allow get: if exists(/databases/$(database)/documents/users/$(request.auth.uid)/ar/$(oId));
allow list: if request.auth.uid in resource.data.users;
}
}
// write
match /organisations/{oId} {
allow create: if get(/databases/$(database)/documents/users/$(request.auth.uid)/ar/$(oId)).data.create == true;
allow update: if get(/databases/$(database)/documents/users/$(request.auth.uid)/ar/$(oId)).data.update == true;
allow delete: if get(/databases/$(database)/documents/users/$(request.auth.uid)/ar/$(oId)).data.delete == true;
match /{all=**} {
allow create: if get(/databases/$(database)/documents/users/$(request.auth.uid)/ar/$(oId)).data.create == true;
allow update: if get(/databases/$(database)/documents/users/$(request.auth.uid)/ar/$(oId)).data.update == true;
allow delete: if get(/databases/$(database)/documents/users/$(request.auth.uid)/ar/$(oId)).data.delete == true;
}
}
}
}