Firebase Firestore子集合安全查询

use*_*561 2 android firebase google-cloud-firestore

我的Cloud Firestore数据库中有以下规则:

service cloud.firestore {
  match /databases/{database}/documents {
    match /performances/{performanceId} {
      allow read, update, delete: if request.auth.uid == resource.data.owner;
      allow create: if request.auth.uid != null;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这样的想法是,您可以在拥有表演的情况下对其进行读写操作,也可以在登录后创建一个表演。

此查询工作正常:

db.collection("performances").whereEqualTo(FieldPath.of("owner"), user.getUid())
Run Code Online (Sandbox Code Playgroud)

但是,如果我想获取“场景”子集合的内容,则会收到错误消息:“ com.google.firebase.firestore.FirebaseFirestoreException:PERMISSION_DENIED:缺少权限或权限不足。” 这是以下查询:

db.collection("performances")
            .document(performanceID)
            .collection("scenes");
Run Code Online (Sandbox Code Playgroud)

我假设我需要将查询限制为如下所示,但这将不能作为whereEqualTo是查询而不是CollectionReference的输出,因此我无法访问“文档”:

db.collection("performances")
   .whereEqualTo(FieldPath.of("owner"), user.getUid())
   .document(performanceID)
   .collection("scenes");
Run Code Online (Sandbox Code Playgroud)

那么,有谁知道如果主集合具有安全规则,我应该如何访问子集合?

更新1(因为以下注释中的代码未格式化)

我想我可能想出了一个解决方案。我没有意识到我的安全规则默认情况下会拒绝从子集合中读取数据,因此将其更改为允许对表演中的场景进行所有读写都可以使其正常工作:

service cloud.firestore {
      match /databases/{database}/documents {
        match /performances/{performanceId} {
      allow read, update, delete: if request.auth.uid == resource.data.owner;
      allow create: if request.auth.uid != null;

      match /scenes/{sceneId} {
        allow read, write: if true
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*ath 5

首先,请注意,规则不会层叠,因此您的解决方案实际上scenes会向世界打开所有子集合中的所有文档,而不仅仅是父文档的所有者。

您需要使用“ get()规则”中的方法检查父文档的权限。

service cloud.firestore {
   match /databases/{database}/documents {
      match /performances/{performanceId} {
         allow read, update, delete: if request.auth.uid == resource.data.owner;
         allow create: if request.auth.uid != null;

         function parentDoc() {
             return get(/databases/$(database)/documents/performances/$(performanceId)).data;
         }

         match /scenes/{sceneId} {
            allow read, write: if parentDoc().owner = request.auth.uid;
         }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

在子收集规则中,我们使用先前捕获的路径段来查找我们需要检查的父文档。

最后,您可能还希望收紧create规则。当前,它允许某人创建其他人(或没有人)拥有的文档。我怀疑你想要那个。通过检查请求者的ID是否在传​​入文档中,您可以防止潜在的错误,这些错误允许创建用户无法阅读的文档:

allow create: if request.auth.uid != null && request.auth.uid == request.resource.data.owner;
Run Code Online (Sandbox Code Playgroud)