允许更新特定字段的安全规则 [英] security rules to allow update of specific fields

查看:18
本文介绍了允许更新特定字段的安全规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是安全规则的新手.我必须编写安全规则以防止用户更新除一个字段之外的文档.

假设我有一个文档

{字段 1:一个,field2 :两个,字段 3 :三个,...字段:n}

登录的用户应该只能更新 field2.使用 Firestore 安全规则.

解决方案

安全规则中没有明确的方法来验证正在发生的更新.但是您可以做的是在写操作之前验证文档中的数据.通过比较这两者,并了解文档可以包含哪些字段,您可以确保只能更新特定字段.

我经常在我的安全规则中使用这个小辅助函数:

function isUnmodified(key) {返回 request.resource.data[key] == resource.data[key]}

顾名思义,它确保在此写入请求中不会修改某个键/字段.例如,此规则只允许用户更新他们的个人资料文档,只要他们不修改 name 字段(除非他们是管理员):

允许更新:if isAdmin(request) ||(request.auth.uid == uid && isUnmodified(request, resource, 'name'));

我也有这个辅助函数,它检查特定字段是否存在:

function isNotExisting(key) {return !(key in request.resource.data) &&(!exists(resource) || !(resource.data 中的键));}

这很重要,因为有时您希望一个字段只写入一次,或者只在它已经存在时才允许更新.有时我会为此使用 isNotExisting,但这些天我发现自己更多地使用了更细粒度的操作(createupdate)而不是聚合 规则.

最后,您可以要求某些字段,如此创建规则:

 允许创建:如果 request.auth.uid == uid &&request.resource.data.keys().hasOnly(['lastIndex', 'lastUpdated']) &&request.resource.data.keys().hasAll(['lastIndex', 'lastUpdated'])

因此,如果用户指定 lastIndexlastUpdated 字段,则他们只能创建配置文件文档.如果他们指定任何额外的字段,或指定更少的字段,创建将被拒绝.

现在有了这些知识,我们可以回到您的要求,看看如何实现它.如前所述,您需要对每个单独的字段进行声明,而不要在那里使用通配符.所以如果你的文档有三个字段(field1, field2, and field3),它们必须都存在,用户只能更新field2,应该是这样的:

allow update: if request.resource.data.keys().hasAll(['field1', 'field2', 'field2']) &&isUnmodified('field1')) &&isUnmodified('field3'));


现在可能有一种更短的方法可以通过使用此处显示的 set 和 map diff 操作来执行此操作:https://firebase.google.com/support/release-notes/security-rules#february_13_2020 喜欢:

<块引用>

//此规则只允许更新a"是唯一受影响的字段允许更新:如果 request.resource.data.diff(resource.data).affectedKeys().hasOnly([a"]);

I am new to security rules. I have to write security rule to prevent a user to update a document except one field.

lets say i have a doc

{ field1 : one, field2 : two, field3 : three, . . . fieldn : n }

the user logged in should be able to update only field2. using firestore security rules.

解决方案

There is no explicit way in security rules to validate the update that is happening. But what you can do is validate the data in the document before and after the write operation. By comparing those two, and by knowing what fields the document can contain, you can ensure that only specific fields can be updated.

I often use this little helper function in my security rules:

function isUnmodified(key) {
  return request.resource.data[key] == resource.data[key]
}

As its name implies, it ensures that a certain key/field is not modified in this write request. For example, this rule then only allows a user to update their profile document, as long as they don't modify the name field (unless they're an admin):

allow update: if isAdmin(request) || 
  (request.auth.uid == uid && isUnmodified(request, resource, 'name'));

I also have this helper function, which checks whether a specific field exists:

function isNotExisting(key) {
  return !(key in request.resource.data) && (!exists(resource) || !(key in resource.data));
}

This is important, because sometimes you want to allow a field to be only written once, or only allow it to be updated if it already exists. Sometimes I use isNotExisting for that, but I find myself more these days using the more granular actions (create, update) over the aggregate write rule.

Finally, you can require certain fields, as in this creation rule:

  allow create: if request.auth.uid == uid &&
    request.resource.data.keys().hasOnly(['lastIndex', 'lastUpdated']) &&
    request.resource.data.keys().hasAll(['lastIndex', 'lastUpdated']) 

So a user can only create a profile document if they specify lastIndex and lastUpdated fields. If they specify any additional fields, or specify fewer fields, the creation will be rejected.

Now with this knowledge, we can go back to your requirement, and see how to implement it. As said before, you will need to make a statement on each individual field, without having a wildcard in there. So if your document has three fields (field1, field2, and field3), which must all exist, and the user can only update field2, that'd be something like:

allow update: if request.resource.data.keys().hasAll(['field1', 'field2', 'field2']) &&
  isUnmodified('field1')) && isUnmodified('field3'));


There may nowadays be a shorter way to do this by using the set and map diff operations that are shown here: https://firebase.google.com/support/release-notes/security-rules#february_13_2020 like:

// This rule only allows updates where "a" is the only field affected
allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(["a"]);

这篇关于允许更新特定字段的安全规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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