【问题标题】:Firebase database rule to only allow one recordFirebase 数据库规则只允许一条记录
【发布时间】:2017-11-25 11:42:20
【问题描述】:

是否有 Firebase 规则,例如,我可以确保某个表中只存在一条记录。

正在进行时有记录。无法添加新的。

count() 和 length() 对于 firebase 来说似乎不存在。

【问题讨论】:

    标签: firebase firebase-realtime-database


    【解决方案1】:

    使用安全规则可以做你想做的事。

    由于您对最大子节点数的限制为 1,因此您可以利用不存在没有子节点的密钥这一事实。

    如果你使用这样的规则:

    {
      "rules": {
        "ongoing": {
          "$key": {
            ".read": "auth != null",
            ".write": "auth != null && ((newData.exists() && (!data.parent().exists() || data.exists())) || !newData.exists())"
          }
        }
      }
    }
    

    将允许写入:

    • 如果正在添加孩子并且ongoing 键不存在;或
    • 如果孩子正在更新;或
    • 如果孩子被移除。

    如果已经存在一个子元素,该规则将阻止添加另一个子元素(因为 ongoing 键已经存在)。

    【讨论】:

    • 我认为这不能解决问题。 OP 想要在进行中的节点下只有一个子节点。这些规则允许创建多个孩子。为了测试,我在 Firebase /ongoing/child_0: "test" 中创建了一个节点。然后在我的测试应用程序中,我有一个简单的 ongoingRef.child("child_1").setValue("test") ,即使已经有一个节点,它也成功写入了第二个节点。为了进一步测试,我将应用程序更改为将多个随机节点写入正在进行的节点,这也成功了。
    • 我在发布之前也对此进行了测试。对我来说,它工作得很好,并且阻止了不止一个孩子的创造。明天我可以重新审视我的测试,因为我可能有错误,但在概念层面上,我认为该规则是有道理的,所以我不明白为什么它不起作用。使用它时,请注意不能在规则之前/之上进行的级联权限授予。
    • 我明白了。我将您的规则复制并粘贴到我的“正在进行的”规则开始的地方。就在上面,我有 ".write": "auth != null"。一旦我删除它,它就可以完美地工作。很好的答案,我在你的答案“规则”中添加了一行,就在“正在进行”的上方,这样其他人就不会犯同样的错误。
    • 感谢您的宝贵时间!它对我不起作用:(我没有使用身份验证,所以这段代码应该可以工作,对吧?imgur.com/a/CZgk4
    • 哦,当我使用 .validate 而不是 .write 时它可以工作!太好了,谢谢!
    【解决方案2】:

    您不能将其表达为验证规则。您可以改为使用云函数来表达基于现有数据接受或拒绝更改的逻辑。您的客户端代码可能需要通过写入数据库的不同部分或 HTTPS 函数来调用此函数。

    【讨论】:

    • 你能看看我的解决方案吗?它有效,但感觉我可能遗漏了一些东西,使它成为更完整的 OP 解决方案。
    • 实际上,由于子节点的最大数量为 1,因此可以使用安全规则强制执行此操作。看我的回答。
    【解决方案3】:

    这可能不是您想要的,但它确实提供了解决方案:

    改变你的结构

    ongoing
       child_0
          id: "some id"
    

    ongoing
        child_count: 1
        child_0
           id: "some id"
    

    然后是规则

    {
      "rules": {
        ".read": "auth != null",
        ".write": "auth != null",
        "ongoing": {
            ".validate": "root.child('ongoing').child('child_count').val() < 1"
        }
      }
    }
    

    当你最初创建正在进行的节点时,像这样创建它

    ongoing
       child_count: 0
    

    然后在添加节点时,将 child_count 更改为 1。从那里添加或修改正在进行的节点的任何尝试都将被拒绝。

    【讨论】:

    • 您必须通过事务以原子方式完成所有这些操作,否则您的计数可能会在并发负载下被破坏。此外,您必须信任您的客户才能正确增加计数。客户端代码可能会被破坏以绕过检查并添加他们想要的任何数据而不更新计数。 Cloud Functions 可能是确保一致性的最佳方式。
    • @DougStevenson 好点!根据用例,这是一个潜在的解决方案。然而,正如 Doug 指出的那样,他的解决方案可能更长期。
    • 另见加藤几年前的回答:stackoverflow.com/questions/22644202/…
    猜你喜欢
    • 2018-10-22
    • 1970-01-01
    • 2018-04-24
    • 2018-08-12
    • 2019-09-24
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    相关资源
    最近更新 更多