我想我做错了什么,但我不知道是哪一部分。。。谢谢你给我的澄清。
所以我有一个名为Bases的集合,看起来像这样:
{
"id1": {
"name": "My base 1",
"roles": {
"idUser_123": {
"name": "John"
}
}
},
"id2": {
"name": "My base 2",
"roles": {
"idUser_456": {
"name": "Jane"
}
}
}
}
idUser_123登录并希望访问他的收藏。所以我会:db.collection('bases').get()
我用匹配规则来确保约翰没有读到简的底数。这就是我认为我错的地方,因为我使用规则是为了过滤。
match /bases/{document=**}{
allow read: if request.auth.uid in resource.data.roles;
}
失败,因为资源为null。。。我试着这样做:
match /bases/{baseId}{
allow read: if request.auth.uid in resource.data.roles;
}
当请求特定文档时,这在模拟器中起作用,但当我从客户端获得没有baseId的get((时失败,因为我想要它们。
那么,我应该如何处理这个非常基本的用例(IMO(呢?
我不能把所有用户的baseId都放在user.token中,因为它会很快超过1000字节。
我可以创建另一个集合Roles来创建baseId和我的用户之间的关系,但对于一个简单的用例来说,这似乎过于复杂了。
或者我可以在服务器上提出请求并过滤where("roles", "has", user.uid)
?在我看来,很快就无法实现在客户端获取数据的目的。。。
任何关于如何解决这一问题的建议都将不胜感激!非常感谢:(
这里有两个问题。
首先,您的查询要求接收基地中的所有文档,但您的规则不允许任何人简单地接收所有文档。重要的是要认识到Firestore安全规则不是过滤器。他们不会从查询中剥离文档——这实际上是不可伸缩的。如果规则要求谁可以根据某些文档的内容查询这些文档,则查询必须使用符合规则要求的筛选器。
其次,您的数据的结构化方式不能使客户端根据用户的UID仅对某些文档执行筛选。Firestore没有可以检查映射字段是否存在的查询。它只能检查贴图值。您可能需要重新构造文档数据,以便客户端可以使用筛选器执行查询,从而仅获取当前用户的文档。
如果角色是一组UID:
"id1": {
"name": "My base 1",
"roles": [ "idUser_123" ]
},
然后客户端可以在该字段上进行过滤:
firebase.firestore()
.collection("bases")
.where("roles", "array-contains", uid)
你可以在规则中强制使用这个过滤器:
match /bases/{document=**} {
allow read: if request.auth.uid in resource.data.roles;
}
但你可能想做一些不同的事情。