【问题标题】:Firestore - accessing transactional/nested data in security rulesFirestore - 访问安全规则中的事务/嵌套数据
【发布时间】:2017-11-23 08:40:01
【问题描述】:

我希望有人可以帮助我解决这个问题。我真的很喜欢新的 Firestore 测试版,但目前缺少模拟器/调试器让我遇到了一个问题。

我有一组可以被赞成或反对的场景。我想限制任何人多次恶意向上投票/向下投票,所以我也有一个针对该场景的投票子集。这些只是由 userId 键入的文档,其中包含类似的哈希

{
  up: true,
  down, false
}

为了在一个请求中写入这多个项目(即场景文档和投票子集合),我使用了一个事务。

我遇到的问题是,我想验证当用户更新“积分”时,它必须附有一个投票文档,该文档设置为 true,具体取决于点数以及用户的投票是否已经存在。

在安全规则中,当我在场景文档级别(或反之亦然)进行验证时,如何读取请求中是否存在投票子集合数据?我的理解是“request.resource.data”只允许您查看正在写入的当前文档级别的数据(我可能在这里错了,但没有简单的方法可以检查,并且文档中没有任何内容)。到目前为止,这是我的安全规则示例:

service cloud.firestore {
  match /databases/{database}/documents {
    // Scenarios
    match /scenarios/{scenarioId} {
        allow read;
      // Only allow write if all of these are true
      allow write: if request.auth.uid == request.resource.data.userId &&
                                            // points    
                                    request.resource.data.points == 0;
      allow update: if request.auth.uid != null &&
                       (
                        request.resource.data.points >= (resource.data.points - 2) ||
                        request.resource.data.points <= (resource.data.points + 2)
                       )
                       // TODO: Only allow write to points IF accompanied by a "votes" document for that userId
      // Votes
      match /votes/{voterId} {
        allow write: if voterId == request.auth.uid;
      }
    }
  }
}

请注意,当前 +/- 2 分的验证是因为如果用户已经对某个场景投了反对票,他们可以通过执行赞成票(删除现有反对票 + 新的反对票)增加 2 分。投票)。一旦我知道如何访问“投票”详细信息,此验证将变得更加复杂:)

【问题讨论】:

  • 有人吗??
  • 我也有同样的问题,你找到解决办法了吗?
  • 很遗憾没有,我向 Firebase 团队报告了此事,但​​从未得到回复

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


【解决方案1】:

如果你仍然遇到这个问题,你可以尝试使用安全规则中的exists()函数:

allow update: if !exists(/databases/$(database)/documents/scenarios/$(scenarios)/votes/$(request.auth.uid));

或者,如果数量不会达到 firestore 文档配额,您可能需要考虑将 uid 列表存储在数组中以检查文档本身的规则:

//your document structure
points: 0
someData: xx
voted: [id1, id2, id3 .. n]

//in the rules
allow update: if !(request.auth.uid in resource.data.voted);

使用这种方法,您需要有一个后台工作人员将用户 ID 添加到数组中,并防止用户使用以下方法写入已投票的数组:

allow update: if request.resource.data.voted == resource.data.voted;

【讨论】:

  • 我认为使用 exists 的问题是 1. 那是为了检查现有数据(但我需要验证请求中的数据),2. exists 将执行另一个“读取”,我想最小化我的阅读用法。如果能够检查事务中的数据(Firebase 允许的方式),那就太好了。在文档本身中存储一个数组是可行的,但同样,这意味着每次有人进行投票时我都需要使用云功能和额外的写入。它会消耗我的写入/云函数调用配额,感觉有点笨拙。感谢您的建议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-21
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
相关资源
最近更新 更多