Firestore安全规则:在文档中的数组中搜索用户的id。
Firestore安全规则:在文档中的数组中搜索用户的id。
首先,对于我的糟糕英语表示抱歉,这不是我的母语...
我正在使用Firestore数据库在Firebase中构建一个简单的应用程序。在我的应用中,用户是小组的成员。他们可以访问其他用户的数据。
为了不查询太多文档(每个用户一个文档,在小组文档的子集合中),我选择将用户的数据添加到小组文档内的数组中。
这是我的小组文档:
{
"name":"fefefefe",
"days":[false,false,false,false,true],
"members":[
{"email":"eee@ff.com","id":"aaaaaaaa","name":"Mavireck"},
{"email":"eee2@ff.com","id":"bbbbbbbb","name":"Mavireck2"},
],
}
如何在安全规则中检查用户是否在一个小组中?
我应该使用对象吗?
我真的不想使用用户的子集合,因为我很快就会达到免费配额的限制...
谢谢您花时间阅读!
编辑:
感谢您的答复。我将把它更改为对象:
"Members": { uid1 : {}, uid2 : {} }
Firestore安全规则:在文档中搜索用户的id的数组的出现原因和解决方法
问题的出现原因:
该问题的出现是因为需要在Firestore的安全规则中,允许某个用户读取/写入集合中的某个文档,前提是该用户存在于另一个集合的数组中。
解决方法:
为了解决这个问题,可以使用以下代码来实现:
service cloud.firestore {
match /databases/{database}/documents {
match /repositories/{accountId} {
allow read, write: if request.auth.uid in get(/databases/$(database)/documents/accounts/$(accountId)).data.users
}
}
}
这段代码中,使用了get()
函数来获取另一个集合中的文档,然后通过判断当前用户的uid是否存在于该文档中的users数组中,来决定是否允许读取/写入操作。
然而,需要注意的是,使用get()
函数会导致额外的读取操作,即使规则拒绝了请求,也会计入费用。所以需要注意这一点。
另外,有其他用户提供了一种不需要额外读取操作的解决方法,但是该方法只适用于访问特定资源的情况,而上述解决方法适用于任何资源的访问。
通过以上解决方法,我们可以在Firestore的安全规则中实现对某个用户id在文档的数组中进行搜索的功能。这样可以实现只允许特定用户访问特定资源的需求。同时,需要注意使用get()
函数可能会产生额外的读取操作。
问题出现的原因:
用户想要在Firestore的安全规则中搜索一个文档中数组中的用户ID,但尝试了多种方法却无法实现。
解决方法:
1. 使用resource.data.members[request.auth.uid] != null来检查数组中是否存在用户ID。
2. 使用子集合来实现权限控制,通过在子集合中检查用户ID是否存在来控制用户对文档的读取权限。
3. 在实际应用中测试代码,因为模拟器对于数组操作有一些问题。
4. 针对集合查询,需要将解决方法与适当的查询绑定起来。
下面整理成一篇文章:
Firestore安全规则:在文档的数组中搜索用户ID的方法
在Firestore中,有时我们希望根据用户ID来控制对文档的读取权限。下面是一些解决这个问题的方法。
方法一:使用数组中的用户ID来控制权限
一般情况下,我们可以编写如下规则来实现:
service cloud.firestore { match /databases/{database}/documents { match /collection/{documentId} { // 如果 `members` = [uid1, uid2, uid3],则允许读取 // 无法遍历集合并检查成员 allow read: if request.auth.uid in resource.data.members; // 也可以使用 `members` = {uid1: {}, uid2: {}} 的形式 allow read: if resource.data.members[request.auth.uid] != null; } } }
方法二:使用子集合来控制权限
如果你想根据用户是否在房间中来控制对消息的读取权限,可以使用子集合来实现:
service cloud.firestore { match /databases/{database}/documents { // 如果用户在房间中,则允许读取消息 match /rooms/{roomId} { match /documents/{documentId} { allow read: if exists(/databases/$(database)/documents/documents/$(documentId)/users/$(request.auth.uid)); } match /users/{userId} { // 允许用户操作文档的规则 } } } }
问题解决方案:
用户反馈了一些问题,以下是针对这些问题的解决方法:
- 当使用resource.data.members[request.auth.uid] != null;
时,无法实现预期的结果。可以尝试使用resource.data.members[request.auth.uid].name != null;
或resource.data.members[(request.auth.uid)] != null;
来进行判断。
- 进行了本地测试,if(doc.data()['members'][(firebase.auth()currentUser.uid)] != null){console.log("not null)}
始终输出"not null"。
- 需要注意的是,allow read: if resource.data.membres[(request.auth.uid)] != null;
无法实现预期的结果,而allow read: if resource.data.membres != null;
可以实现。
- 如果你只在提供的模拟器中进行测试,建议在实际应用中进行测试,因为模拟器在处理数组时存在一些问题。
通过Firestore的安全规则,我们可以根据用户ID来控制对文档的读取权限。可以使用数组中的用户ID来进行权限控制,也可以通过子集合来实现。在实际应用中,需要注意模拟器对数组操作的问题,并将解决方法与适当的查询绑定起来,以实现集合查询的权限控制。