假设我有一个带有 restaurants
子集合的 menus
集合。餐厅权限设置在餐厅文档中,如下所示:
餐厅
{
"roles": {
"user123": "Owner"
}
}
有权访问餐厅的任何人也可以访问其任何子集合,包括 menus
子集合。这是安全规则:
安全规则
match /restaurants/{restaurantId}/{document=**} {
allow read: if resource.data.roles[request.auth.uid] > '' ;
}
查询餐厅列表可以这样完成,效果很好:
餐厅查询
firebase
.firestore()
.collection('restaurants')
.where(`roles.${uid}`, '>', '');
现在如何查询 menus
子集合?我知道 Firestore 需要根据查询推断权限,而无需查看基础数据。从逻辑上讲,这应该是可能的,因为任何有权访问 restaurant
的人也可以访问 menus
子集合。但是我如何编写这个 menus
子集合查询,以便 Firestore 可以推断出这一点?我能想到的最合乎逻辑的查询是这样的:
查询菜单子集合(不起作用)
firebase
.firestore()
.doc(`restaurants/${restaurantId}`) // user has access to this restaurant
.collection('menus');
...但这在权限被拒绝的情况下不起作用。
答案 0 :(得分:1)
事实证明,我需要在 restaurant
级别创建 2 条安全规则才能实现我想要的:
match /restaurants/{restaurantId} {
allow read: if resource.data.roles[request.auth.uid] > ''
}
match /restaurant/{restaurantId}/{document=**} {
allow read: if get(/databases/$(database)/documents/restaurants/$(restaurantId)).data.roles[request.auth.uid] > '';
}
为了查询用户有权访问的餐馆,第一条规则是必要的。单独的第二个查询不起作用,尽管我不确定为什么。这是第一条规则的查询:
firebase
.firestore()
.collection('restaurants')
.where(`roles.${uid}`, '>', '');
第二条规则对于所有子集合查询都是必需的。举个例子:
firebase
.firestore()
.collection(`restaurants/${restaurantId}/menus`);
第二条规则允许子集合查询的事实非常有趣,因为 Firestore 需要读取 restaurant
文档才能允许此查询。这与其声称它不查看查询的基础数据相矛盾,但如果它只需要读取路径中的一个文档,它看起来似乎确实如此。