在 Firestore 安全规则中的对象列表中过滤/某些

Posted

技术标签:

【中文标题】在 Firestore 安全规则中的对象列表中过滤/某些【英文标题】:Filter/some on list of objects in a Firestore security rule 【发布时间】:2020-09-05 18:37:18 【问题描述】:

在 Firestore 安全规则中,我正在尝试检查尝试在一个集合中创建/删除文档的用户是否也是该对象的所有者,如在另一个集合中标记的那样。基本上,我的数据看起来像这样:

users 集合中,每个用户都有一个这样的文档:

    name: 'john',
    userItems: [
        
            id: 'random-id',
            ...
        , 
        ...
    ],
    ...

items 集合(我正在为其编写规则)中,来自平台所有用户的所有项目都在那里,并且具有与元素中的id 键对应的Firestore ID items 的所有者列表。因此,如果 john 创建了一个 ID 为 random-id 的项目,他的用户文档将如下所示,并且在 items 集合中会有一个新文档,其 Firestore ID 为 random-id

我想要实现的是创建一个安全规则,其中 items 集合中的文档只有在我可以使用 get(/databases/$(database)/documents/users/$(request.auth.uid)) 访问的当前授权用户的用户文档具有一个元素时才能更新在他们的userItems 列表中,其中id 键等于request.resource.id。如果这是普通的 JS,我可能会这样做:

match /items/item 
    allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid))
        .data
        .userItems
        .some(userItem =>
            userItem.id === request.resource.id
        )

但是,Firestore List interface 非常乏味,不支持像 .some 这样的花哨操作,甚至不支持基本/手动循环(据我所知)。我一直试图想出一些聪明的方法来解决这个问题,但是即使.joining 列表和.matching 使用一些花哨的 RegExp 生成的字符串也行不通,因为我很确定地图会解析作为'[object Object]' 而不是正确地进行字符串化。

有没有办法使用标准 Firestore 规则来做到这一点,而无需重新配置我的数据库结构?

【问题讨论】:

【参考方案1】:

您尝试执行的操作无法使用安全规则。您将需要更改表示数据的方式(我建议这样做,因为列表可能不是最好的表示),或者添加更多数据以满足您的要求。

如果 random-id 在列表中是唯一的,您应该考虑使用映射而不是列表来表示它,以便您可以对规则中可用的Map 进行简单的查找。如果您的 userItems 字段是由该 ID 索引的地图,您可以改为:

allow write: if get(...).data.userItems.keys().hasAny([request.resource.id]);

如果由于某种原因您无法更改该字段,则需要将 ID 复制到一个新的列表字段中并像这样检查它:

allow write: if get(...).data.userItemIds.hasAny([request.resource.id]);

【讨论】:

以上是关于在 Firestore 安全规则中的对象列表中过滤/某些的主要内容,如果未能解决你的问题,请参考以下文章

无法为 Android 应用程序的特定经过身份验证的用户 (uid) 编写***集合(列表权限)的 Firestore 安全规则

如何检查传入号码数据是否大于或小于Firestore安全规则中的特定限制?

即使firestore安全规则中的文档字段不可用,也如何允许访问?

Firestore - 访问安全规则中的事务/嵌套数据

匿名身份验证用户的这个 Firebase/Firestore 安全规则是不是安全?

在 Cloud Firestore 中如何制作一个,只创建一次安全规则