men*_*e23 13 firebase firebase-security google-cloud-firestore
对于我的生活,我无法理解为什么以下导致false允许写入.假设我的users集合是空的,我正在从我的Angular前端编写以下表单的文档:
{
displayName: 'FooBar',
email: 'foo.bar@example.com'
}
Run Code Online (Sandbox Code Playgroud)
我目前的安全规则:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
function isAdmin() {
return resource.data.role == 'ADMIN';
}
function isEditingRole() {
return request.resource.data.role != null;
}
function isEditingOwnRole() {
return isOwnDocument() && isEditingRole();
}
function isOwnDocument() {
return request.auth.uid == userId;
}
allow read: if isOwnDocument() || isAdmin();
allow write: if !isEditingOwnRole() && (isOwnDocument() || isAdmin());
}
}
}
Run Code Online (Sandbox Code Playgroud)
一般来说,我希望没有用户能够编辑自己的角色.普通用户可以编辑自己的文档,管理员可以编辑任何人.
Stubbing isEditingRole()for false给出了预期的结果,所以我把它缩小到那个表达式.
写入不断变回虚假,我无法确定原因.任何想法或修复都会有所帮助!
编辑1
我试过的事情:
function isEditingRole() {
return request.resource.data.keys().hasAny(['role']);
}
Run Code Online (Sandbox Code Playgroud)
和
function isEditingRole() {
return 'role' in request.resource.data;
}
Run Code Online (Sandbox Code Playgroud)
和
function isEditingRole() {
return 'role' in request.resource.data.keys();
}
Run Code Online (Sandbox Code Playgroud)
编辑2
请注意,最终,管理员将为用户设置角色,因此角色最终可能存在于文档中.这意味着,根据下面的Firestore文档,请求将具有role密钥,即使不在原始请求中也是如此.
将资源中存在的请求中未提供的字段添加到
request.resource.data.规则可以测试一个字段是否通过比较修正request.resource.data.foo,以resource.data.foo知道的是,在各个领域resource也将出现在request.resource即使它不是在写请求提交.
据此,我认为"编辑1"中的三个选项被排除在外.我确实试过了这个建议request.resource.data.role != resource.data.role而且也没有用......我很茫然,我开始怀疑Firestore中是否存在错误.
所以最后,我似乎假设它resource.data.nonExistentField == null会返回false,当它实际返回一个时Error(根据这个和我的测试)。所以我原来的解决方案可能遇到了这个问题。这是令人费解的,因为根据文档,相反的应该起作用,但也许文档指的是“不存在”的值,而不是键 - 一个微妙的区别。
我仍然没有 100% 的清晰度,但这就是我最终得到的结果:
function isAddingRole() {
return !('role' in resource.data) && 'role' in request.resource.data;
}
function isChangingRole() {
return 'role' in resource.data && 'role' in request.resource.data && resource.data.role != request.resource.data.role;
}
function isEditingRole() {
return isAddingRole() || isChangingRole();
}
Run Code Online (Sandbox Code Playgroud)
另一件让我感到困惑的事情是,根据文档,我不应该需要 中的&& 'role' in request.resource.data部分isChangingRole(),因为它应该由 Firestore 自动插入。尽管情况似乎并非如此,因为删除它会导致我的写入因权限问题而失败。
它有可能成为澄清/打破写伸到改善create,update以及delete零件,而不是只allow write: if !isEditingOwnRole() && (isOwnDocument() || isAdmin());。
小智 6
我用它来解决它writeFields.请试试这条规则.
allow write: if !('role' in request.writeFields);
Run Code Online (Sandbox Code Playgroud)
就我而言,我list用来限制更新字段.它也有效.
allow update: if !(['leader', '_created'] in request.writeFields);
Run Code Online (Sandbox Code Playgroud)
如果您创建自定义函数来检查更新,则规则将更具可读性和可维护性。例如:
service cloud.firestore {
match /databases/{database}/documents {
function isUpdatingField(fieldName) {
return (!fieldName in resource.data && fieldName in request.resource.data) || resource.data[fieldName] != request.resource.data[fieldName];
}
match /users/{userId} {
//read rules here...
allow write: if !isUpdatingField("role") && !isUpdatingField("adminOnlyAttribute");
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5541 次 |
| 最近记录: |