I am trying to set up a ruleset for a new Firestore project where we have the following root collections:
users
organisations
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 for 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 usersids, 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 firestore 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;
}
}
}
}
firestore. rules // is a file used to define the security rules for your Firestore database. firestore.
New document with same ID should not be allowed in the same collection. It should be possible to fetch an already existing document from a previous import.
To be honest, without Firebase Authentication, it's not possible to accept writes to a database without Authentication and also avoid abuse, since anyone could write anything from anywhere on the internet. This could also cost you large amounts of money if someone discovers your "open" database.
The service cloud. firestore declaration scopes the rules to Firestore, preventing conflicts between Firestore Security Rules and rules for other products such as Cloud Storage. The match /databases/{database}/documents declaration specifies that rules should match any Firestore database in the project.
See documentation
Control Access with Custom Claims and Security Rules
The Firebase Admin SDK supports defining custom attributes on user accounts. This provides the ability to implement various access control strategies, including role-based access control, in Firebase apps. These custom attributes can give users different levels of access (roles), which are enforced in an application's security rules.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With