Firestore 安全规则 - 如何检查字段是否被修改? [英] Firestore Security Rules - How can I check that a field is/isn't being modified?

查看:20
本文介绍了Firestore 安全规则 - 如何检查字段是否被修改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就我的一生而言,我无法理解为什么以下内容会导致允许写入的 false.假设我的 users 集合开始时为空,并且我正在从我的 Angular 前端编写以下形式的文档:

For the life of me, I cannot understand why the following is resulting in a false for allowing writes. Assume my users collection is empty to start, and I am writing a document of the following form from my Angular frontend:

{
  displayName: 'FooBar',
  email: 'foo.bar@example.com'
}

我当前的安全规则:

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());
    }
  }
}

一般来说,我希望没有用户能够编辑他们自己的角色.普通用户可以编辑自己的文档,而管理员可以编辑任何人的文档.

In general, I want no users to be able to edit their own role. Regular users can edit their own document otherwise, and admins can edit anyone's.

false 存根 isEditingRole() 给出了预期的结果,所以我把它缩小到那个表达式.

Stubbing isEditingRole() for false gives the expected result, so I've narrowed it down to that expression.

写入不断返回错误,我无法确定原因.任何想法或修复都会有所帮助!

The write keeps coming back false, and I cannot determine why. Any ideas or fixes would be helpful!

编辑 1

我尝试过的事情:

function isEditingRole() {
  return request.resource.data.keys().hasAny(['role']);
}

function isEditingRole() {
  return 'role' in request.resource.data;
}

function isEditingRole() {
  return 'role' in request.resource.data.keys();
}

编辑 2

请注意,最终管理员将为用户设置角色,因此角色最终可能存在于文档中.这意味着,根据下面的 Firestore 文档,请求将有一个 role 键,即使它不在原始请求中.

Note that eventually, admins will set a role for users, so a role could eventually exist on a document. This means that, according to the Firestore docs below, the request will have a role key, even if wasn't in the original request.

资源中存在的请求中未提供的字段添加到request.resource.data.规则可以通过比较request.resource.data.fooresource.data.foo 来测试一个字段是否被修改,知道resource 也会出现在 request.resource 中,即使它没有在写请求中提交.

Fields not provided in the request which exist in the resource are added to request.resource.data. Rules can test whether a field is modified by comparing request.resource.data.foo to resource.data.foo knowing that every field in the resource will also be present in request.resource even if it was not submitted in the write request.

据此,我认为排除了编辑 1"中的三个选项.我确实尝试了 request.resource.data.role != resource.data.role 的建议,但这也不起作用......我不知所措,开始怀疑是否真的有Firestore 中的错误.

According to that, I think the three options from "Edit 1" are ruled out. I did try the suggestion of request.resource.data.role != resource.data.role and that's not working either... I'm at a loss and am beginning to wonder if there's actually a bug in Firestore.

推荐答案

所以最后,我似乎假设 resource.data.nonExistentField == null 会返回 false,当它实际返回一个 Error(根据 this 和我的测试).所以我原来的解决方案可能遇到了这个问题.这是令人费解的,因为相反的应该根据 文档 工作,但是也许文档指的是不存在"的值,而不是键 - 一个微妙的区别.

So in the end, it seems I was assuming that resource.data.nonExistentField == null would return false, when it actually returns an Error (according to this and my tests). So my original solution may have been running into that. This is puzzling because the opposite should work according to the docs, but maybe the docs are referring to a value being "non-existent", rather than the key -- a subtle distinction.

我仍然没有 100% 的清晰度,但这就是我最终得到的效果:

I still don't have 100% clarity, but this is what I ended up with that worked:

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();
}

另一件让我感到困惑的事情是,根据文档,我不需要 &&isChangingRole() 中 request.resource.data 部分的 'role',因为它应该由 Firestore 自动插入.尽管情况似乎并非如此,因为删除它会导致我的写入因权限问题而失败.

Another thing that still puzzles me is that, according to the docs, I shouldn't need the && 'role' in request.resource.data part in isChangingRole(), because it should be inserted automatically by Firestore. Though this didn't seem to be the case, as removing it causes my write to fail for permissions issues.

通过将写入分成createupdatedelete 部分,而不仅仅是<代码>允许写入:如果 !isEditingOwnRole() &&(isOwnDocument() || isAdmin());.

It could likely be clarified/improved by breaking the write out into the create, update, and delete parts, instead of just allow write: if !isEditingOwnRole() && (isOwnDocument() || isAdmin());.

这篇关于Firestore 安全规则 - 如何检查字段是否被修改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆