【发布时间】:2019-11-25 14:00:56
【问题描述】:
我有一个 Flutter 应用程序,用户可以在其中发布帖子并将帖子标记为属于某个组。帖子存储在一个全局集合中,每个都有一个Post.groupId 字段:
/posts/{postId}
根据我的 Firestore 安全规则和查询,用户只有在帖子被标记的组(即帖子的 groupId 字段)中才能阅读帖子。批准的组用户存储在:
/groups/{groupId}/users/{userId}
我可以查询来自特定用户组的帖子,例如:
_firestore.collection('posts').where('groupId', isEqualTo: 'groupA')...
以上一切正常。
我正在尝试改进一个帖子可以标记在多个组中而不是一个组中,因此我将单个 Post.groupId 字段替换为 Post.groupIds 数组。如果用户是来自Post.groupIds 的任何组的成员,他/她应该能够阅读帖子。我尝试从我的 Flutter 应用程序中使用以下查询读取所有标记为特定组的帖子:
_firestore.collection('posts').where('groupIds', arrayContains: 'groupA')...
我不断收到以下异常 Missing or insufficient permissions 与这些安全规则:
match /posts/{postId} {
allow read: if canActiveUserReadAnyGroupId(resource.data.groupIds);
}
function isSignedIn() {
return request.auth != null;
}
function getActiveUserId() {
return request.auth.uid;
}
function isActiveUserGroupMember(groupId) {
return isSignedIn() &&
exists(/databases/$(database)/documents/groups/$(groupId)/users/$(getActiveUserId()));
}
function canActiveUserReadAnyGroupId(groupIds) {
return groupIds != null && (
(groupIds.size() >= 1 && isActiveUserGroupMember(groupIds[0])) ||
(groupIds.size() >= 2 && isActiveUserGroupMember(groupIds[1])) ||
(groupIds.size() >= 3 && isActiveUserGroupMember(groupIds[2])) ||
(groupIds.size() >= 4 && isActiveUserGroupMember(groupIds[3])) ||
(groupIds.size() >= 5 && isActiveUserGroupMember(groupIds[4]))
);
}
使用这些安全规则,我可以阅读单个帖子,但无法进行上述查询。是否有允许我进行此查询的安全规则?
更新 1
为完整性添加了isSignedIn() 和getActiveUserId() 安全规则功能。
更新 2
这是我尝试在本地使用 Firestore 模拟器执行此查询时收到的错误:
FirebaseError:
Function not found error: Name: [size]. for 'list' @ L215
第 215 行对应此规则中的 allow read 行:
match /posts/{postId} {
allow read: if canActiveUserReadAnyGroupId(resource.data.groupIds);
}
【问题讨论】:
-
当您运行查询时,它只查找
groupIds包含groupA的文档,然后返回该文档。无需检查整个groupIds数组,因为您只是在寻找groupA。因此您只需要检查isSignedIn() && exists(/databases/$(database)/documents/groups/$(groupId)/users/$(getActiveUserId()))。 -
@Nathan,根据 OP 的问题,用户访问帖子的方式是他们是否可以访问任何组。检查所有组似乎是必要的
-
@DanFein 我的错,你是对的。
-
您可能会超过 firebase 对单文档请求和查询请求的 exists() 和 get() 调用的最大数量(只有 10 个)。超过限制会导致权限被拒绝错误。
-
另请注意,有一个规则模拟器可让您在本地测试规则,并提供更详细的消息以帮助您了解发生了什么。 cloud.google.com/firestore/docs/security/test-rules-emulator
标签: firebase flutter google-cloud-firestore firebase-security