【问题标题】:How to restrict Firestore document update to only increment by one in rules?如何将 Firestore 文档更新限制为仅在规则中增加一?
【发布时间】:2021-06-24 15:32:10
【问题描述】:

我知道 Firestore 规则允许对请求数据的特定字段和数据类型进行规则检查,但我也想控制正在更新的字段的具体差异。

例如,我在文档上有一个计数器。我只希望计数器在每次请求时增加一,不多也不少。

我在 firebase 控制台的规则操场上尝试了这个,它可以工作:

match /myCollection/{myDoc} {
  allow update: if(request.resource.data.diff(resource.data).affectedKeys().hasOnly(["counter"])
    && request.resource.data.counter is int &&
    request.resource.data.counter == resource.data.counter + 1);
}

然后在我调用的代码中:

docRef.update({
  counter: firebase.firestore.FieldValue.increment(1)
}

由于权限被拒绝而被阻止。

我的猜测是规则将其注册为函数而不是文档值上的 int,这会导致它失败。 (这是有道理的)

如何在不先阅读文档的情况下正确验证规则中的这个客户端增量操作?

【问题讨论】:

    标签: firebase google-cloud-firestore firebase-security


    【解决方案1】:

    当文档具有counter 的先前值时,您的规则有效。但是,如果在原始文档中省略了counter,您的规则将失败。这是因为在安全规则中访问地图上缺少的属性会引发错误,这将使您的规则失败。

    您要么需要在初始文档上强制使用 counter 字段(确保修复现有文档),要么允许 counter 在初始文档上是可选的。

    在创建和更新时需要counter

    match /myCollection/{myDoc} {
      allow create: if "counter" in request.resource.data
                    && request.resource.data.counter is int;
      allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(["counter"])
                    && request.resource.data.counter is int
                    && request.resource.data.counter == resource.data.counter + 1;
    }
    

    更新时需要counter,可以在初始文档写入中省略:

    match /myCollection/{myDoc} {
      allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(["counter"])
                    && request.resource.data.counter is int
                    && request.resource.data.counter == resource.data.get("counter", 0) + 1;
    }
    

    【讨论】:

    • 这不是问题。当我尝试存在计数器的文档时,它仍然失败。问题是我正在使用 firestore increment doc field value 函数,因此请求资源在实时代码中未被验证为 int。在规则操场之外尝试一下。
    • @MrDrew 我确实在我的沙盒网站上对此进行了测试,没有问题。确保在测试时将参数传递给increment(),因为不使用值会尝试将NaN 写入未通过int 检查的服务器。但我会在当天晚些时候重新审视它,看看你所描述的是否正在发生。
    • 您是否真的对此进行了测试并成功了?我仔细检查过,仍然收到客户的许可拒绝。我再次对其进行了测试,仅删除了 int 检查并保留了 request.resource.data.counter == resource.data.counter + 1; 检查,该检查在没有拒绝请求的情况下有效,因此我知道在更新调用中使用字段增量函数时 int 检查失败。
    • @Mr.Drew 我清除了集合,在/myCollection/test 使用数据{ "counter": 0 } 创建了一个新文档,然后使用firebase.firestore().doc("myCollection/test").update({ "counter": firebase.firestore.FieldValue.increment(1) }).then(()=>console.log("done"),(err)=> console.error("rejected",err)) 将其递增,使用上述创建/更新规则没有问题在 Firebase JS SDK 的 v8.7.0 上阻止逐字复制。
    • 那时我不知道该说什么,无论是否使用:request.resource.data.counter is int 规则,我都做了同样的事情,当规则中存在 int 检查时,它会在我的客户端返回权限被拒绝。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 2018-06-21
    • 1970-01-01
    相关资源
    最近更新 更多