Firestore 规则:属性 未在对象上定义。对于 'list' @ L6

Firestore rules: Property is undefined on object. for 'list' @ L6

我在尝试按字段查询子查询时遇到问题,我已经尝试了模拟器和 firebase 支持(仍在进行中,但还没有解决方案)。

当运行以下查询时:

const queryByNumber = query(
  collectionGroup(this.firestore, 'residents'), 
  where('cellNumber', '==', number)
);
return from(getDocs(queryByNumber)); 

此查询有以下错误:

Property cellNumber is undefined on object. for 'list' @ L6

目前的规则是这样的

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{path=**}/residents/{residentDoc} {
        allow write: if resource.data.cellNumber == request.auth.token.phone_number;
        allow read: if request.auth.token.phone_number == resource.data.cellNumber;
        //allow read; //temp permission till support fix
      }
      match /Units/{unitNumber} {
        allow read: if request.auth != null;
        function residentDoc(residentId) {
            return get(/databases/$(database)/documents/Units/$(unitNumber)/residents/$(residentId))
        }
        
        match /pets/{petId} {
          allow write: if residentDoc(request.resource.data.residentId).data.cellNumber == request.auth.token.phone_number;
          allow read: if request.auth != null;
        }
      }
    }
}

这是目前的 firestore 数据结构:

我曾尝试更改我的查询以在 where 子句中包含 array-contains,但变化不大。

注意:没有 if 检查的 allow read 允许检索数据,因此查询确实有效,只是保护它的规则不是`

问题出在您的规则中:

request.auth.token.phone_number in resource.data.cellNumber

Firestore 安全规则中的 in 操作仅针对地图和 lists/arrays 定义,但您的 cellNumber 字段是一个简单的字符串值,未定义 in 操作如你所见here.

如果要检查令牌中的phone数字是否与字段的值相同,请使用==而不是in。如果要测试是否是in字段,可以考虑使用matches method on the string.

另见:

问题是另一个查询在第一个查询被触发后试图获取所有驻留数据,这导致它无法通过规则,因为第二个查询不再由 cellNumber 查询。我已将规则更改为 UID 验证,因为它将始终提供