【发布时间】:2019-09-10 14:28:56
【问题描述】:
我的应用程序将用户的角色(订阅者、编辑者或管理员)作为“角色”映射存储在 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
我 found 使用 writeFields 的一个更简单的解决方案,但 writeFields 已被弃用,因此这不是一个长期解决方案:
allow update: if isOwner(userUid) && !('roles' in request.writeFields)
同样,writeFields 已被弃用,因此不应使用。
更新 2
这个解决方案最终为我工作,用角色替换角色以匹配我的情况:https://stackoverflow.com/a/48214390/4407512
【问题讨论】:
-
查看整个文档内容(可能是屏幕截图?)和整个规则(包括匹配规范)会很有帮助,以及失败的查询的代码。我们应该能够完全重现您所提供的情况,并看到它完全像您一样失败。
-
另外,您是否在控制台模拟器中对此进行了测试?它是否为您提供了更具体的错误消息,可能表明具体失败的原因?
-
感谢您提出的好问题。我没有尝试过模拟器,当然应该有。当我这样做时,它会给出错误:“物业管理员未定义对象”。所以这就解释了。我需要在角色映射中标识 all 角色,但只为应该分配给用户的角色设置“true”。此外,更新过程必须包括每个相同的角色,以便对每个角色的相等性检查(确保没有角色更改)将通过。除非有另一种写逻辑的方法?我更新了原始帖子以包含匹配规范。
标签: google-cloud-firestore firebase-security