允许更新时,如何保护Firestore文档上的字段?

时间:2019-04-19 23:55:00

标签: firebase google-cloud-firestore firebase-security-rules

使用Firebase Firestore,我将聊天室详细信息存储在包含某些数据的文档中,例如:

roomName
roomAvatar
createDate
isDeleted

我的应用程序和规则要求在文档的“创建”上设置这些字段。但是,我也希望授权用户也可以“更新”该文档。

我已经进行过检查,仅允许某些用户更新文档并确认不允许他们修改“ createDate”之类的字段。但是,我似乎无法通过强制FiledValue.delete()或使用ref.set(objectMissingCreateDate)来创建强制授权用户不会删除“ createDate”字段的规则。

最后,如果他们只想更新一个或两个字段,我认为不需要客户端在更新中传递所有数据字段。

我有一个“更新”规则,如下所示:

allow update: if isAuthenticated() && isMemberOfRoom() && 
  (
    (!("roomName" in request.resource.data) || 
      request.resource.data.roomName == resource.data.roomName || 
      hasRoomPermission("UpdateRoom")) &&
    (!("roomAvatar" in request.resource.data) || 
      request.resource.data.roomAvatar == resource.data.roomAvatar || 
      hasRoomPermission("UpdateRoom")) &&
    (!("createDate" in request.resource.data) || 
      request.resource.data.createDate == resource.data.createDate) &&
    (!("isDeleted" in request.resource.data) || 
      request.resource.data.isDeleted == resource.data.isDeleted || 
      hasRoomPermission("DeleteRoom"))
  );

主要问题是保护数据免受传入FieldValue.delete()或使用[Android] docRef.set()的授权用户的影响,而缺少必需的值。

我什至会接受为非管理员客户端关闭FieldValue.delete()和破坏性的“设置”操作的功能。

1 个答案:

答案 0 :(得分:0)

借助Doug和Puff的评论,我意识到自己做错了。

首先,我不知道仅传递几个字段的更新(或带有合并选项的集合)将导致其余字段从数据库的request.resource复制到resource

第二,集合(无合并)或传递FieldValue.delete()request.resource缺少现有文档字段的唯一方法。

有了这些新知识,我将以前的规则更新为以下内容:

allow update: if isAuthenticated() && isMemberOfRoom() && 
  (
    ("roomName" in request.resource.data && 
      (request.resource.data.roomName == resource.data.roomName || 
      hasRoomPermission("UpdateRoom"))) &&
    ("roomAvatar" in request.resource.data && 
      (request.resource.data.roomAvatar == resource.data.roomAvatar || 
      hasRoomPermission("UpdateRoom"))) &&
    ("createDate" in request.resource.data && 
      request.resource.data.createDate == resource.data.createDate) &&
    ("isDeleted" in request.resource.data && 
      (request.resource.data.isDeleted == resource.data.isDeleted || 
      hasRoomPermission("DeleteRoom")))
  );

这些新规则现在将createDate锁定为客户端,同时允许通过权限测试的客户端编辑roomNameroomAvatarisDeleted 。如果对象缺少这些字段之一,它也将不允许使用FieldValue.delete()更新这些字段或调用docRef.set(object)