I have a firestore database schema with three collections :
users
- name: string
brokers
- name: string
- members: array of User references
companies
- name: string
- brokers: array of Broker references
Also : The ids of the users
table are the same as the UIDs in firebase authentification.
I want the companies
table to be readable only by users who are members of the related brokers. What should be the security rule ?
For example, let's say I want to read a company with the following query and data, user1
should be able to do it but not user2
:
// Query:
const company = db.collection('companies').doc('company1').get()
// Data:
"users": {
"user1": {
"name": "Elon Musk"
},
"user2": {
"name": "Jeff Bezos"
}
}
"brokers": {
"broker1": {
"name": "Broker 1",
"members": [
"users/user1"
]
}
}
"companies": {
"company1": {
"name": "SpaceX",
"brokers": [
"brokers/broker1"
]
}
}
I have tried this but it only works if a company is linked to one broker instead of an array of brokers:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function getUser() {
return /databases/$(database)/documents/users/$(request.auth.uid)
}
function userIsMember(resource) {
return "members" in resource.data && getUser() in resource.data.members
}
match /companies/{companyId} {
function getBroker() {
return get(/databases/$(database)/documents/brokers/$(resource.data.broker.id))
}
allow read: if userIsMember(getBroker());
}
}
}
CodePudding user response:
Security rules on their own don't filter data, but instead merely ensure that your code follows the rules you set for them. So if your rules say that a user can only read documents that they're a member of, the query should only request documents that they're a member of. This is a common misconception, and is covered in the documentation section rules are not filters.
It looks like you won't be able to translate your getBroker
rule into a query though, as there's no way to have a condition on data that isn't part of the results in a query.
Both of these limitations exist for the same reasons by the way: since you are charged for each document that is read, things would get expensive really quickly if Firestore had to inspect each potential document for your rule/query.
The solution usually is to replicate the necessary data into each company document, although you'll have to determine whether that'll work for your use-case.