繁体   English   中英

允许用户使用 Firestore 安全规则更新自己的文档(但不是角色)

[英]Allow user to update his own document (but not the roles) using Firestore security rules

我的应用程序将用户的角色(订阅者、编辑者或管理员)存储为 Firestore 用户集合中用户文档中的“角色”映射。 角色映射如下所示:

// Roles map for a subscriber
{
subscriber: true 
}

// Roles map for a editor
{
editor: true 
}

// Roles map for administrator
{
administrator: true 
}

我还可以根据需要在用户文档的角色映射中放置多个(或全新的)角色字段。

我希望用户能够在不更改角色映射的情况下更新他们的个人资料。 因此,对于安全规则,我尝试通过检查用户是否为所有者以及之前和之后的角色是否完全相同来确保这一点。 但是我在尝试更新时总是遇到权限错误。 以下是规则:

match /users/{userUid} {
  allow update: if 
  (
    isOwner(userUid) &&
    (
      (request.resource.data.roles.administrator == resource.data.roles.administrator) &&
      (request.resource.data.roles.editor == resource.data.roles.editor) &&
      (request.resource.data.roles.subscriber == resource.data.roles.subscriber)
    )
  );
}

第一个isOwner(user)条件如下所示:

function isOwner(uid) {
    return (isSignedIn() && (request.auth.uid == uid));
}

我相信这部分可以正常工作,因为当我只用它运行时,它就可以工作。

我怀疑我的问题可能是在写入之前或之后角色字段之一(例如订户)不存在的情况下,它无法通过相等性检查。 所以我也尝试添加一个条件以允许现有对象没有该字段,但它仍然不起作用:

match /users/{userUid} {
  allow update: if 
  (
    isOwner(userUid) &&
    (
      (!request.resource.data.roles.administrator || request.resource.data.roles.administrator == resource.data.roles.administrator) &&
      (!request.resource.data.roles.editor || request.resource.data.roles.editor == resource.data.roles.editor) &&
      (!request.resource.data.roles.subscriber || request.resource.data.roles.subscriber == resource.data.roles.subscriber)
    )
  );
}

在此先感谢您的帮助。


更新 1

找到了一个使用writeFields的更简单的解决方案,它有效,但 writeFields 已被弃用,因此这不是一个长期解决方案:

allow update: if isOwner(userUid) && !('roles' in request.writeFields)

同样,writeFields 已被弃用,因此不应使用。


更新 2

这个解决方案最终对我有用,用角色替换角色以匹配我的情况: https ://stackoverflow.com/a/48214390/4407512

您现在可以使用地图差异来解决此问题,而无需使用已弃用的“writeFields”

allow update: if isOwner(userUid) && !('roles' in request.resource.data.diff(resource.data).affectedKeys());

request.resource.data是一个 Map 类型的对象。 正如您所说,您可以确保属性始终存在,或者您可以在使用它们之前检查属性是否存在于 Map 中。 Map 对象上的in操作会让您知道属性是否存在。 有关详细信息,请参阅地图文档。

"administrator" in request.resource.data   // true if administrator property exists

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM