Home > Mobile >  Map through array in firestore security rule
Map through array in firestore security rule

Time:03-12

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.

  • Related