用于存储包含数组的查询的Firestore安全规则 [英] Firestore Security Rules for Query with Array Contains

查看:49
本文介绍了用于存储包含数组的查询的Firestore安全规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Flutter app in which users can make posts and tag the post as belonging to a group. Posts are stored in a global collection and each has a Post.groupId field:

/posts/{postId}

根据我的Firestore安全规则和查询,仅允许用户阅读帖子所属的组(即帖子的groupId字段),并且只能阅读该帖子.批准的网上论坛用户存储在:

Based on my Firestore security rules and queries, users are only allow to read posts if they are in the group for which the post is tagged (i.e the posts's groupId field). Approved group users are stored in:

/groups/{groupId}/users/{userId}

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

I could query the posts from a particular user's group like:

_firestore.collection('posts').where('groupId', isEqualTo: 'groupA')...

以上操作均正常.

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

I am attempting to make an improvement in which a post can be tagged in multiple groups instead of just one, so I am replacing the single Post.groupId field with a Post.groupIds array. A user should be able to read a post if he/she is a member of ANY of the groups from Post.groupIds. I attempt to read all posts tagged with a particular group with the following query from my Flutter app:

_firestore.collection('posts').where('groupIds', arrayContains: 'groupA')...

根据这些安全规则,我不断收到以下异常Missing or insufficient permissions:

I keep receiving the following exception Missing or insufficient permissions with these security rules:

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]))
            );
}

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

With these security rules I can read a single post but I cannot make the above query. Is it possible to have security rules which allow me to make this query?

更新1

添加了isSignedIn()getActiveUserId()安全规则功能以保持完整性.

Added isSignedIn() and getActiveUserId() security rules functions for completeness.

更新2

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

Here is the error I am receiving when I attempt to execute this query with the Firestore Emulator locally:

     FirebaseError: 
Function not found error: Name: [size]. for 'list' @ L215

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

Line 215 corresponds to the allow read line within this rule:

match /posts/{postId} {
    allow read: if canActiveUserReadAnyGroupId(resource.data.groupIds);
}

推荐答案

Firestore目前似乎不支持此方案的安全规则(感谢您对Doug Stevenson的跟踪).我想出了一种解决限制的机制,并希望在其他人正在处理此问题的情况下进行分享.它需要一个额外的查询,但使我不必为了避免安全规则而使用Admin SDK创建Web API.

It appears Firestore does not currently support security rules for this scenario at the moment (thanks for your help tracking this down Doug Stevenson). I have come up with a mechanism to work around the limitation and wanted to share in case someone else is dealing with this issue. It requires an extra query but keeps me from having to create a Web API using the Admin SDK just to get around the security rules.

帖子的存储方式如下(简化):

Posts are stored as follows (simplified):

/posts/{postId}
- userId
- timestamp
- groupIds[]
- message
- photo

现在,我要添加一个额外的帖子引用集合,该集合仅存储指针信息:

Now I am adding an additional post references collection which just stores pointer information:

/postRefs/{postId}
- userId
- timestamp
- groupIds[]

posts集合将具有安全性规则,该规则将进行所有验证,以确保用户至少在标记该帖子的组之一中. Firestore能够正确处理简单的get请求,但暂时无法正确处理list请求.

The posts collection will have security rules which does all the validation to ensure the user is in at least one of the groups in which the post is tagged. Firestore is able to handle this properly for simple get requests, just not list requests at the moment.

由于postRefs集合仅存储ID,而不存储可能包含在帖子中的敏感信息,因此可以放宽其安全规则,以便仅验证用户已登录.因此,用户将在以下位置执行帖子查询postRefs集合以检索要从posts集合延迟加载的有序postId的列表.

Since the postRefs collection stores only ID's, and not sensitive information which may be in the post, its security rules can be relaxed such that I only verify a user is logged in. So, the user will perform post queries on the postRefs collection to retrieve a list of ordered postId's to be lazily loaded from the posts collection.

客户向普通posts馆藏中添加/删除帖子,然后有一个Cloud Function将ID信息复制到postRefs馆藏中.

Clients add/delete posts to/from the normal posts collection and then there is a Cloud Function which copies the ID information over to the postRefs collection.

这篇关于用于存储包含数组的查询的Firestore安全规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆