gpt4 book ai didi

google-cloud-firestore - 使用 Firestore 安全规则限制写入嵌套对象的字段

转载 作者:行者123 更新时间:2023-12-02 02:51:03 26 4
gpt4 key购买 nike

tl;dr:我认为 Set需要一种获取元素的方法 (set.toList()[0]),但也许我遗漏了什么!


您好!我正在开发一个使用 Firestore 处理大量小对象(信用卡交易)的预算应用程序。为了限制读取次数,将每个事务存储为单独的文档没有意义,因为用户可能一次需要约数百个事务。

相反,我有一个容器来保存许多交易,如下所示:

/user/{user_id}/transactions/{container_id}

container: {
transactions: {
transaction_id_1: {
amount: 8.25,
note: 'chipotle lunch'
},
transaction_id_2: {
amount: 12.01
}
}
}

这很好用,但我认为安全规则不适用于写入。我想允许用户修改某些字段 (note) 但不允许其他字段 (amount)。如果每笔交易都是一份文件,我们可以用 MapDiff 来做到这一点,但嵌套使它更难。

由于我们不能编写 for 循环,如果我们将自己限制为每次写入一个更新的事务,那么使用嵌套的 MapDiffs 应该是完全可能的,如下所示:

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents/{document=**} {

function allowTransactionUpdate() {
let transactionId = <transaction ID of the single transaction being updated>;

// Limit fields updated for container.
return request.resource.data.diff(resource.data).changedKeys()
.hasOnly(['transactions']) &&

// Make sure only one transaction changed.
request.resource.data.transactions.diff(resource.data.transactions)
.changedKeys().hasOnly([transactionId]) &&

// Verify the transaction already exists.
transactionId in resource.data.transactions &&

// Only allow certain fields to be updated on that transaction.
request.resource.data.transactions[transactionId]
.diff(resource.data.transactions[transactionId]).affectedKeys()
.hasOnly(['note']);
}

match /transactions/{transMonthId} {
allow update: if allowTransactionWrite();
}

allow read, write: if false;
}
}

如果我们可以使用 MapDiff 获取在 container.transactions Map 中更改的事务,这会很好用:

let transactionId = request.resource.data.transactions
.diff(resource.data.transactions).changedKeys()[0];

关键缺失部分是最后一位:[0]。目前,Sets没有提供获取元素的方法,这意味着将某些东西转换为 Set(以及因此使用 MapDiff 的任何东西)是死胡同:您永远无法真正知道 Set 中的值是什么。它只能与其他 Set 进行比较。

否则……我是不是漏掉了什么?还有另一种方法可以限制嵌套更新的字段吗?


其他选项是:

  • 使用自定义后端来执行此写入,这是可行的但令人遗憾,因为 Firestore 的一大优势是最少的后端 + 安全规则的执行。
  • 将用户可编辑的属性放在一个容器文档中,将不可编辑的属性放在另一个容器文档中,但这会加倍读取并给客户端订阅增加恼人的复杂性。
  • 接受这是不可能的,并为每个交易使用一个文档,这将导致阅读量增加 100 倍。 ;)

最佳答案

对于正在寻找有关嵌套对象和 MapDiff 示例的任何其他人

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {

function affectedKeys(keys){
return request.resource.data.diff(resource.data).affectedKeys().hasOnly(keys)
}

function affectedKeysObj(obj1Key, obj2Key, keys){
return request.resource.data[obj1Key].diff(resource.data[obj2Key]).affectedKeys().hasOnly(keys)
}

match /{document=**} {
allow read, write: if false;
}
match /users/{uid}{
allow get: if request.auth.uid == uid;
allow update: if request.auth.uid == uid
&& ! affectedKeys(["meta"])
&& affectedKeys(["userData"])
&& affectedKeysObj("userData", "userData", ["bio", "displayName"]);
}
}
}

在这种情况下,我希望用户能够在 userData map 中编辑 ["bio", "displayName"],但我也想禁止编辑 map 。

但是关于这个问题,Doug Stevensons 是对的,我只是补充说这就是我对嵌套对象使用 MapDiff 的方式。

关于google-cloud-firestore - 使用 Firestore 安全规则限制写入嵌套对象的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61978239/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com