在所有情况下都允许创建和读取但是如果 firebase 实时数据库中不存在数据则不允许更新

Allow Create And Read in all the cases But don't allow update if the data does not exist in firebase real time database

我正在使用 fiebase 开发聊天模块,我的结构如下。

我的主节点是mychatexperiment

里面我有另一个节点 ChatListing 和一些其他的聊天键。

今天我在我的结构中设置了 setValues,当我在没有任何节点的情况下传递我的 url 时,它删除了我在父节点中的所有数据。

我要的是设置规则

  1. 任何情况下都可以创建节点
  2. 任何情况下都可以更新节点
  3. 无论如何都不能删除节点
  4. 一个只能更新或设置ChatListing里面的数据

我正在尝试使用它,但它不起作用。知道如何实现这些东西。

{
  "rules": {
         ".write": "!data.exists() || !newData.exists()",
         "read" : true
   }
}

注意:我没有使用任何身份验证,因此需要在没有任何身份验证的情况下实施规则

修改要求:

我有一个结构,其中有一个父节点,在其中我有多个通过 firebase 生成的聊天键,在聊天键中我有一个单独消息的节点。 第二件最重要的事情是我有一个名为 chatlisting 的节点,我在其中以独特的格式存储我的 userids 如果我的 userid 是 5 那么在 chatlisting 中我存储 5 并且在 5 中我有所有的聊天键节点与我有关。

{
  "ChatListing": {
    "1126_2": { //userUnique key 

      "MjmhpHb6qR7VSkYzbjI": { // 1126 userid has this chat key and inside this chat last msg was welcome and its unread count is 0 
        "UnReadCount": 0,
        "lastmessage": "Welcome",
        "lastmessagetime": 1631870264251
      }
    },
    "4184_1": {
      "MjmhpHb6qR7VSkYzbjI": { // 4184 userid has this chat key as well and inside this chat last msg was welcome and its unread count is 1 
        "UnReadCount": 1,
        "lastmessage": "Welcome",
        "lastmessagetime": 1.6318646965369204E12
      }
    }

  },
  "MjmhpHb6qR7VSkYzbjI": { // chat key
    "-MjmhpQbBaL7EbHPHayA": { // mesg key
      "data": "Thankyou",
      "time": 1.6318646965369204E12,
      "type": 0,
      "user": 4184   // the msg is sent by this user
    },
    "-Mjn21A4067dT4emYe05": {  // another msg in the same chat
      "data": "Welcome",
      "time": 1631870264251,
      "type": 0,
      "user": 1126 // the msg is sent by this user
    }
  }
}

我想要的是在父节点(ChatList 节点除外)内设置任何人都不能运行更新、设置或删除的规则。任何人都可以在父节点中创建聊天密钥和读取聊天密钥,他们无能为力。

但在聊天列表中,他们可以执行创建读取、设置和更新(而不是删除),因为我需要针对用户聊天更新此节点中的最后一条消息。

因此,重复使用我的 other answer 所涵盖的要点,您将应用这些规则使用:

{
  "rules": {
    "ChatListing": {
      "$userid": { // the user's unique ID
        // anyone who knows this user ID can read their messages
        ".read": true,

        "$chatid": { // a chatroom the user is in

          // data stored here MUST have this shape (with nothing else)
          // {
          //   UnReadCount: number,
          //   lastmessage: string,
          //   lastmessagetime: number
          // }

          // Data may be created or updated, but not deleted

          ".validate": "newData.child('UnReadCount').isNumber() && newData.child('lastmessage').isString() && newData.child('lastmessagetime').isNumber()",

          "UnReadCount":     { ".write": "newData.exists()" },
          "lastmessage":     { ".write": "newData.exists()" },
          "lastmessagetime": { ".write": "newData.exists()" }
        }
      }
    },
    // when using $ keys at the same level as defined keys,
    // this rule will catch everything that doesn't match
    // the above rules
    "$chatId": { // a chatroom where messages can be sent
      // anyone who knows this chat ID can read its messages
      ".read": true, 

      "$msgId": { // a message in this chatroom

        // Data stored here MUST have this shape (with nothing else)
        // {
        //   data: string,
        //   time: number
        //   type: number,
        //   user: string, // see note
        // }

        // Data may be created, but not edited or deleted
        // change like above if needed

        ".validate": "newData.child('data').isString() && newData.child('time').isNumber() && newData.child('type').isNumber() && newData.child('user').isString()",
        
        "data": { ".write": "!data.exists()" },
        "time": { ".write": "!data.exists()" },
        "type": { ".write": "!data.exists()" },
        "user": { ".write": "!data.exists()" }
      }
    }
  }
}

备注:

  • 不要使用数字用户 ID,因为它们很容易被猜到,随机生成一些东西。您甚至可以使用 const userId = push(getReference(getDatabase())).key。考虑使用 anonymous authentication.
  • 保护数据
  • 与您的要求不同,我已将聊天中的消息设置为不可变。一旦发送,没有人可以编辑它们。这可以防止发件人以外的其他人进入并更改消息。通过身份验证,可以允许编辑,因为它更安全。
  • 请注意,与我的 /cars example 不同的是,我没有将 ".read": true 放在数据库的根目录或 /ChatListing 中。这可以防止有人出现并 运行 以下任何一段代码提取您所有存储的数据或一次提取所有存储的用户 ID,这将允许他们找到不适合他们的消息。不过,它不会阻止暴力破解数据。
const rootRef = ref(getDatabase());

rootRef
  .then((snapshot) => {
    console.log(snapshot.val()) // all data in database!
  });

const chatListingRef = ref(getDatabase(), "ChatListing");

chatListingRef
  .then((snapshot) => {
    const usersArray = [];
    const chatIdSet = new Set();
    snapshot.forEach(userData => {
      usersArray.push(userData.key)
      userData.forEach(lastChatData => chatIdSet.add(lastChatData.key));
    });
    
    // logs all user IDs in the database!
    console.log("User IDs:", usersArray)

    // logs all chatroom IDs in the database!
    console.log("Chatroom IDs:", [...chatIdSet]) 
  });