Firebase 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;
}
}
}

这个想法是,如果您拥有表演,则可以读取和写入该表演,或者如果您已登录,则可以创建性能。

此查询工作正常:

db.collection("performances").whereEqualTo(FieldPath.of("owner"), user.getUid())

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

db.collection("performances")
.document(performanceID)
.collection("scenes");

我假设我需要将查询限制为以下内容,但这不适用于 whereEqualTo 的输出是查询而不是集合引用,所以我无法访问"文档":

db.collection("performances")
.whereEqualTo(FieldPath.of("owner"), user.getUid())
.document(performanceID)
.collection("scenes");

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

更新 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
}
}
}
}

首先,请注意,规则不会级联,因此您的解决方案实际上向全世界开放所有子集合中的所有文档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;
}
}
}
}

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

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

allow create: if request.auth.uid != null && request.auth.uid == request.resource.data.owner;

最新更新