用于查询包含数组的 Firestore 安全规则

dew*_*ald 5 firebase firebase-security flutter google-cloud-firestore

我有一个 Flutter 应用程序,用户可以在其中发布帖子并将帖子标记为属于一个组。帖子存储在一个全局集合中,每个帖子都有一个Post.groupId字段:

/posts/{postId}
Run Code Online (Sandbox Code Playgroud)

根据我的 Firestore 安全规则和查询,如果用户在帖子被标记的组(即帖子的groupId字段)中,则只允许他们阅读帖子。批准的组用户存储在:

/groups/{groupId}/users/{userId}
Run Code Online (Sandbox Code Playgroud)

我可以查询来自特定用户组的帖子,例如:

_firestore.collection('posts').where('groupId', isEqualTo: 'groupA')...
Run Code Online (Sandbox Code Playgroud)

以上这些都正常工作。

我正在尝试进行改进,其中可以在多个组中而不是一个组中标记帖子,因此我将单个Post.groupId字段替换为Post.groupIds数组。如果用户是来自 的任何组的成员,则他/她应该能够阅读帖子Post.groupIds。我尝试使用 Flutter 应用程序中的以下查询阅读所有标记为特定组的帖子:

_firestore.collection('posts').where('groupIds', arrayContains: 'groupA')...
Run Code Online (Sandbox Code Playgroud)

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]))
            );
}
Run Code Online (Sandbox Code Playgroud)

有了这些安全规则,我可以阅读一篇文章,但无法进行上述查询。是否有允许我进行此查询的安全规则?

更新 1

新增isSignedIn()getActiveUserId()对完整性的安全规则的功能。

更新 2

这是我尝试在本地使用 Firestore 模拟器执行此查询时收到的错误:

     FirebaseError: 
Function not found error: Name: [size]. for 'list' @ L215
Run Code Online (Sandbox Code Playgroud)

第 215 行对应allow read于此规则中的行:

match /posts/{postId} {
    allow read: if canActiveUserReadAnyGroupId(resource.data.groupIds);
}
Run Code Online (Sandbox Code Playgroud)

Dou*_*son 2

如果我不得不猜测,我会说 groupIds 实际上不是 List 类型对象,这意味着文档中的字段也不是数组。如果它是字符串,则此代码将不起作用,因为字符串没有size()在规则语言中调用的方法。

如果您不能 100% 确定字段的类型,则需要检查规则中的类型并确定如何处理它。您可以使用is运算符来检查类型。例如,groupIds is list如果您实际上正在使用它,则将是布尔值 true。

在您的规则中,您可以使用该debug()函数将某些表达式的值转储到日志中。它将返回相同的值。因此,您可以说debug(groupIds) != null打印该值并检查它是否为空。