通过 Firestore 安全规则中的数组进行映射

Map through array in firestore security rule

我有一个包含三个集合的 firestore 数据库模式:

users
- name: string

brokers
- name: string
- members: array of User references

companies
- name: string
- brokers: array of Broker references

另外:users table 的 id 与 firebase 身份验证中的 UID 相同。

我希望 companies table 仅供属于相关经纪人成员的用户阅读。安全规则应该是什么?

例如,假设我想读取具有以下查询和数据的公司,user1 应该可以做到但 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"
      ]
    }
  }

我已经试过了,但只有当一家公司链接到一个经纪人而不是一系列经纪人时它才有效:

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());
    }
  }
}

安全规则本身不会过滤数据,而只是确保您的代码遵循您为它们设置的规则。因此,如果您的规则规定用户只能阅读他们所属的文档,则查询应该只请求他们所属的文档。这是一个常见的误解,在文档部分 rules are not filters.

中有所介绍

您似乎无法将 getBroker 规则转换为查询,因为无法对不属于查询结果一部分的数据设置条件。

顺便说一下,这两个限制的存在原因相同:由于您需要为阅读的每份文档付费,如果 Firestore 必须检查您的每个潜在文档,事情会很快变得昂贵 rule/query .

解决方案通常是将必要的数据复制到每个公司文档中,但您必须确定这是否适用于您的 use-case。