使用Firebase规则构建数据

时间:2018-08-14 11:25:59

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

我创建了一个APP,用户可以在其中发布Tasks。注册用户可以看到其他用户的任务,但不允许用户对其进行编辑,除非用户是该任务的发布者。

直到现在我还没有设置Firebase规则,因此所有内容都可以删除或读取。我将尽我所能尝试以最好的方式进行解释。

如果我专注于该节点上的主要Task道具,则它包含3个基本道具:

  • 状态
  • posterID
  • workerID

状态不能由任务发布者或其他任何人编辑,而应由服务器功能处理。应该通过发布新任务来设置posterID,并且对任何人都不能对其进行编辑。至于阅读规则,注册用户可以阅读任务的所有道具。

我想避免将任务作为数据接受并通过对数据库的管理员权限进行设置的服务器功能,因为用户将无法以这种方式体验脱机持久性。

我想出了这个“并非真正可行的”解决方案。我一直在测试是否可以编辑用户ID未能发布的任务的状态,因为它会更改状态,因此我陷入了困境。在不应该这样做的地方。

安全规则:

   "Tasks" : {
      ".read": "auth != null",
      ".write": "auth != null", //Users can post tasks
        "$taskID":{
          // Only the owner of the task can edit its props
          ".write": "root.child('Tasks').child('$taskID').child('posterID').val() === auth.uid",
            // But the status is for nobody editable
            "status": {
                ".write": false
            }
        }
   }

代码:

  updateForeignTask() {
    firebase
      .database()
      .ref("Tasks")
      .child("-LJraTW2KV7BgcSZ8yJ6")
      .update({ status: 2 });
  }

  testingFBRules() {
    const taskID = firebase
      .database()
      .ref("Tasks")
      .push().key;

    var task_to_post = {
      taskID: taskID,
      posterID: firebase.auth().currentUser.uid,
      title: "test",
      desc: "test",
      creationDate: firebase.database().getServerTime(),
      //status: 0,
      workerID: ""
    };

    firebase
      .database()
      .ref("Tasks")
      .child(taskID)
      .set(task_to_post)
      .then(res => {
        var temp;
        alert("res : " + res);
      })
      .catch(error => {
        var temp;
        alert("err: " + error);
      });
  }

我已注释掉testingFBRules()上的状态道具,以便能够发布任务。我可以想象触发一个云功能,以在以后添加具有管理员权限的状态。但是我不确定这是否是正确的方法。

我的问题是,如何设置firebase规则以符合我的要求。并且如果不可能,我应该如何重组数据库以使其成为可能?

1 个答案:

答案 0 :(得分:1)

权限一旦被授予,就不能撤消。授予用户访问路径的权限后,他们也可以访问该路径下的所有数据。这意味着:

".write": "auth != null", //Users can post tasks
"$taskID":{
  // Only the owner of the task can edit its props
  ".write": "root.child('Tasks').child('$taskID').child('posterID').val() === auth.uid",
    // But the status is for nobody editable
    "status": {
        ".write": false
    }
}

此处的顶级规则意味着任何用户(auth != null)都可以编写所有任务。尽管有status,他们也可以写".write": false。那里的另一条.write规则似乎也没有意义,因为它似乎在尝试加强访问权限。

您通常会希望结构化数据以符合安全要求。这意味着我将在其他任务数据的单独分支中对状态进行建模:

Tasks
  $taskId
    posterId: ...
    workerId: ...
Status
  $taskId: 2

现在,您可以保护每个分支的访问权限安全,仅允许用户写入/Tasks(因为/Status由您的服务器管理)。