【问题标题】:Firebase database rules: How to prevent a certain child from being deleted (a.k.a NOT NULL)?Firebase 数据库规则:如何防止某个子项被删除(又名 NOT NULL)?
【发布时间】:2017-05-04 11:52:14
【问题描述】:

我正在尝试在 firebase 中定义一个模式,以防止某些子属性为空(如 SQL 中的 NOT NULL 约束)。

架构应如下所示:

Property | allow null | type
---------+------------+--------
name     | false      | string
phone    | false      | string
alias    | true       | string
birthday | true       | number (timestamp) 

此外,只有用户自己才能读取和写入自己的联系人。

目前数据库中有一些虚拟数据:

{
  "contacts" : {
    "user1" : {
      "contact1" : {
        "alias" : "Bobby",
        "name" : "Bob",
        "phone" : "12312324"
      }
    }
  }
}

我想出的解决方案是这样的:

{
  "rules": {
    "contacts": {
      "$user": {
        "$contact": {
          ".read": "auth.uid == $user",
          ".write": "auth.uid == $user && newData.hasChildren(['name', 'phone'])",
          "name": {
            ".validate": "newData.isString()"
          },
          "phone": {
            ".validate": "newData.isString()"
          },
          "alias": {
            ".validate": "newData.isString()"
          },
          "birthday": {
            ".validate": "newData.isNumber()"
          },
          "$other": {
            ".validate": "false"
          }
        }
      }
    }
  }
}

这种方法的问题在于,每次我想修补某个值(例如别名)时,由于newData.hasChildren(['name', 'phone'] 规则,我必须提供非空属性(未更改)。

虽然我可以访问我的应用程序中的整个对象,但这是一个令人讨厌的不便。

有没有更好的方法来解决这个问题?

【问题讨论】:

  • Firebase 没有架构,因此通常最好不要在 NoSQL 数据库上强制使用 SQL 概念 - 思考并设计您的 NoSQL 结构!例如;试图防止某些子属性为空。为什么?如果没有数据会发生什么?如果要确保它有数据,什么数据? Firebase 不允许空字符串,因此这意味着您需要有一些东西作为子值占位符。在 NoSQL 的情况下,缺少子节点通常比占位符好。在代码中处理这些情况; if !phoneChildNode.exists() then let phoneVar = "no phone provided"

标签: firebase firebase-realtime-database firebase-security


【解决方案1】:

这种方法的问题在于,每次我想要修补某个值(例如别名)时,由于newData.hasChildren(['name', 'phone'] 规则,我必须提供非空属性(未更改)。

您似乎误解了规则中newData 的含义。来自reference documentation of newData

RuleDataSnapshot 对应于如果允许写入将产生的数据。

因此,如果您仅将单个属性写入已包含所有属性的位置,newData 变量将包含所有属性:未指定属性的现有值,以及您正在编写的属性的新值.

【讨论】:

  • 那为什么模拟器显示写入被拒绝(使用虚拟数据)? screenshot
  • 因为您正在模拟整个用户的set() 操作。这将替换整个联系人,包括 namephone 属性。要模拟update(),请将"value" 写入contacts/user1/contact1/alias
  • 谢谢,这消除了很多困惑和沮丧。
猜你喜欢
  • 2021-04-03
  • 1970-01-01
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
  • 2021-05-15
  • 1970-01-01
相关资源
最近更新 更多