【问题标题】:Allow first-time creation of data in Firebase, then restrict access允许首次在 Firebase 中创建数据,然后限制访问
【发布时间】:2015-04-22 19:55:01
【问题描述】:

我正在寻找一种解决方案,允许首次在 Firebase 中创建数据,然后限制对该数据的所有者(或管理员)的访问。从本质上讲,我已经为一个企业创建了一个注册流程,它在 Firebase 中创建了一个用户以及该企业的关联用户。不幸的是,根据我当前的架构和安全规则,我收到了permission_denied 错误。这是我当前的架构,它是由 EmberFire 使用 businessemployee 模型之间的 hasMany belongsTo 关系生成的:

+ businesses
  + business_id (generated by EmberFire)
    - name
    + employees
      - employee_id
      - employee_id
+ employees
  + employee_id (generated by Firebase's auth system)
    - first name
    - last name
    - business_id
    - role (ex: 99 for admin)

这是我的安全规则:

{
  "rules": {
    "businesses": {
      // allows only administrators of the business to read and write business data
      "$business_id": {
        ".read": "root.child('employees/' + auth.uid + '/business').val() === $business_id && root.child('employees/' + auth.uid + '/role').val() === 99",
        ".write": "root.child('employees/' + auth.uid + '/business').val() === $business_id && root.child('employees/' + auth.uid + '/role').val() === 99"
      }
    },
    "employees": {
      // only allow employees to read/write their own data or the admin of the business they belong to
      "$employee_id": {
        ".read": "auth.uid === $employee_id || (root.child('employees/' + auth.uid + '/role').val() === 99 && root.child('businesses/' + (root.child('employees/' + auth.uid + '/business').val()) + '/employees/' + $employee_id).exists())",
        ".write": "auth.uid === $employee_id || (root.child('employees/' + auth.uid + '/role').val() === 99 && root.child('businesses/' + (root.child('employees/' + auth.uid + '/business').val()) + '/employees/' + $employee_id).exists())"
      }
    }
  }
}

任何人都可以推荐一组更新的安全规则/架构,以允许在注册期间最初创建数据,然后只有该数据的所有者/管理员可以访问?

注意:我目前正在运行 Firebase 2.2.4 和 EmberFire 1.4.4。

提前致谢, 詹姆斯

更新

这是注册过程中使用的代码:

// first, create the user account to be the admin of the business
_this.firebase.createUser({
  email: _this.get('email'),
  password: _this.get('password')
}, function(error, userData) {

  if (error) {
    flashMessages.warning(error);
  } else {

    // authenticate the user and log them in
    _this.get('session').authenticate('authenticator:firebase', {
      'email': _this.get('email'),
      'password': _this.get('password')
    }).then(function() {

      // create the business record
      var business = _this.store.createRecord('business', {
        name: _this.get('businessName')
      });

      // create the employee record and associate the firebase uid
      var employee = _this.store.createRecord('employee', {
        id: userData.uid,
        firstName: _this.get('firstName'),
        lastName: _this.get('lastName'),
      });

      // add the employee<->business relationship
      business.get('employees').then(function(employees) {
        employees.addObject(employee);
      });

      // save the records to Firebase
      employee.save().then(function() {
        business.save();
      });

    }).catch(function(error) {
      flashMessages.warning(error);
    });

  }

}); 

此外,下面是说明我所描述内容的数据快照:

【问题讨论】:

  • 嘿,James,append only 的简单方法是我们的​​ firechat 应用程序在此处的操作方式:github.com/firebase/firechat/blob/master/rules.json#L11。关键是这块:".write": "!data.exists()".
  • 感谢您的回复。那有点奏效了。我的business 模型有一个姓名和上面提到的员工列表。添加!data.exists() 后,它成功创建了business 节点employees,但name 未写入,我收到以下错误:update at /businesses/-JnY-AR9vTMjw9Q27BUB failed: permission_denied。经过一些测试,我发现如果我删除business employee 关系,name 被写入并且我没有错误。这几乎就像 EmberFire 发出了两个写请求,这会使规则无效?上面添加了代码。
  • 我看到@tstirrat 刚刚评论了相关的 Github 问题。上下文链接github.com/firebase/emberfire/issues/246

标签: javascript firebase firebase-security emberfire


【解决方案1】:

您的安全规则需要role = 99,但您从未设置它。

以下似乎可以解决您的问题:

// create the employee record and associate the firebase uid
var employee = _this.store.createRecord('employee', {
  id: userData.uid,
  firstName: _this.get('firstName'),
  lastName: _this.get('lastName'),
  role: 99
});

要回答更大的问题,是的,写入是分多个部分完成的。 hasMany 关系单独保存,以免完全覆盖其他客户端上可能发生的任何更改。更具体地说,每个 hasMany 链接在单独的写入中添加或删除,因此可能有 2 个或更多个写入。

就您的代码而言,business/&lt;id&gt;/employees&lt;employee_id&gt; 链接首先被保存,这意味着在第二次通过时 - 在编写主要的 business/&lt;id&gt; 哈希时 - 您的规则的 !data.exists() 部分失败。这很好,因为员工已创建并链接到业务,但role = 99 检查也失败了。

【讨论】:

  • 谢谢,@tstirrat!我很抱歉浪费你的时间在如此琐碎的事情上。我意识到我已经删除了模型中的属性,因为我正在玩弄东西并忘记将其放回原处。我非常想着问题在于它被拒绝了,因为!data.exists() 在第二次写入时检查失败,我什至没有费心检查条件的另一部分。再次感谢您!
猜你喜欢
  • 2021-06-24
  • 2013-06-07
  • 2010-09-25
  • 1970-01-01
  • 2015-05-31
  • 2023-02-01
  • 2017-02-26
  • 2017-05-23
  • 2023-03-19
相关资源
最近更新 更多