首页 > 解决方案 > Firestore 范围查询 - 将规则与“where”子句匹配

问题描述

我想根据字符串字段查询 Firestore 集合,返回该字段以用户身份验证令牌上的自定义声明开头的所有文档。我能够使用这个答案来创建一个使用>=<运算符以及后继键的查询,当我放松我的 Firestore 规则时,这对我很有效。

我想锁定我的规则集,以便用户只能访问以他们的自定义声明开头的文档。

我已经阅读了规则不是过滤器文献,根据我的理解,我只需要编写规则,以便我的查询永远不会返回违反规则的数据。

所以这就是我试图做的没有太大成功的事情:

我有一个 Firestore 集合,其中包含如下所示的文档:

{
   "id": 1,
   "namespace": "foo.bar"
}

每个用户对其身份验证令牌都有一个自定义声明,假设它是my_namespace.

我这样写了一个 Firestore 规则:

function hasNamespaceAccess(request, resource){
        //allow if data.namespace starts with request.token.my_namespace
        return resource.data.namespace.matches(request.auth.token.my_namespace + ".*");
    }


      match /path_to_my_objects/my_collection/{my_obj} {
        allow read, write: if hasNamespaceAccess(request, resource);
    }

我的查询,在简化以使这篇文章尽可能简洁之后,看起来像这样:

return db
        .collection('my_collection')
        .where('namespace', '>=', 'foo.') //the namespace "query values" are hard coded for clarity here
        .where('namespace', '<', 'foo.c')

调用 Firestore 时使用的令牌肯定有"my_namespace": "foo"

我的期望

我的 Firestore 规则说,用户可以访问任何namespace以“foo”开头的文档——文档"namespace": "foo.bar"符合这一点。

我的查询应该只返回命名空间在“foo”之间的文档。和“foo.c”。同样,我的文件符合这一点。我相信,这个查询永远不会返回不符合我的 Firestore 规则中的正则表达式字符串的文档。

因此,我希望得到我的文档的结果集。

实际发生了什么

index.cjs.js:13448 快照侦听器中未捕获的错误:FirebaseError:缺少权限或权限不足。在新的 n (index.cjs.js:129) 在 index.cjs.js:10175 在 index.cjs.js:10176 在 n.onMessage (index.cjs.js:10209) 在 index.cjs.js:10115 在index.cjs.js:10146 在 index.cjs.js:5542

我尝试修改我的查询以不使用范围,并且只有where("namespace", "==" "foo.bar"), 并且这按预期工作,因此系统的其余部分似乎工作正常,但规则和过滤子句之间存在不匹配。

标签: javascriptfirebasegoogle-cloud-platformgoogle-cloud-firestore

解决方案


这里的问题不在于您的代码正在尝试访问规则不允许的数据,而是规则引擎不够聪明,无法在match无需检查实际数据的情况下证明所有情况。

>=一个有趣的替代方法是使用和运算符执行相同的检查<=。不过,我没有机会尝试,所以让我知道这对您是否有效(或无效)。


推荐阅读