允许首次在 Firebase 中创建数据,然后限制访问
Allow first-time creation of data in Firebase, then restrict access
我正在寻找一种解决方案,允许首次在 Firebase 中创建数据,然后限制对该数据的所有者(或管理员)的访问。本质上,我已经为一家企业创建了一个注册流程,它在 Firebase 中创建了一个用户,并为该企业创建了一个关联用户。不幸的是,根据我当前的架构和安全规则,我遇到了 permission_denied
错误。这是我当前的模式,它是由 EmberFire 使用 business
和 employee
模型之间的 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())"
}
}
}
}
任何人都可以推荐一组更新的安全性 rules/schema 以允许在注册期间最初创建数据,然后仅供该数据的 owner/admin 访问吗?
注意:我目前是 运行 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);
});
}
});
此外,这里有一个数据快照,可以说明我所描述的内容:
您的安全规则需要 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
link 在单独的写入中添加或删除,因此可能有 2 或更多 写入。
就您的代码而言,business/<id>/employees<employee_id>
link 首先保存,这意味着在第二次传递时 - 在编写主 business/<id>
哈希时 - !data.exists()
你的部分规则失败了。这很好,因为员工已创建并 linked 到业务,但 role = 99
检查也失败了。
我正在寻找一种解决方案,允许首次在 Firebase 中创建数据,然后限制对该数据的所有者(或管理员)的访问。本质上,我已经为一家企业创建了一个注册流程,它在 Firebase 中创建了一个用户,并为该企业创建了一个关联用户。不幸的是,根据我当前的架构和安全规则,我遇到了 permission_denied
错误。这是我当前的模式,它是由 EmberFire 使用 business
和 employee
模型之间的 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())"
}
}
}
}
任何人都可以推荐一组更新的安全性 rules/schema 以允许在注册期间最初创建数据,然后仅供该数据的 owner/admin 访问吗?
注意:我目前是 运行 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);
});
}
});
此外,这里有一个数据快照,可以说明我所描述的内容:
您的安全规则需要 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
link 在单独的写入中添加或删除,因此可能有 2 或更多 写入。
就您的代码而言,business/<id>/employees<employee_id>
link 首先保存,这意味着在第二次传递时 - 在编写主 business/<id>
哈希时 - !data.exists()
你的部分规则失败了。这很好,因为员工已创建并 linked 到业务,但 role = 99
检查也失败了。