首页 > 解决方案 > 用于检查角色或公司的 Firestore 规则功能

问题描述

在我们启动生产之前,我需要在我的应用程序中实施基于角色的授权。我有一个功能可以检查用户是否仅从他们的公司访问数据。我还需要确保具有“SuperUser”、“Tester”或“Manager”角色的用户也可以访问数据,即使他们不是公司的一部分。我查看了其他基于角色的实现,但它们似乎没有解决这种必须检查公司或角色的情况。

我在这里有 OR 语句的规则:

allow read: if exists(/databases/$(database)/documents/companies/$(company)/users/$(request.auth.uid)) 
|| hasRole(['SuperUser', 'Manager', 'Tester']);

我有这个作为hasRoles的功能:

function hasRole(roles) {
    return get("/databases/$(database)/documents/companies/Seva Development/users/$(request.auth.uid)").data.roles.hasAny(roles);
}

当我添加此函数时,即使 OR 语句的左侧为真,用户也会被拒绝访问。我只能假设该功能有问题,但我一直无法从 firebase 文档中找到。

我尝试访问的文档如下所示:

firebase 控制台数据库

如何修改此功能以允许我检查用户是否是我们组织的一部分并具有指定的角色之一?

如果你有这个角色但不是公司的一部分,这很有效:

allow read: if isUserCompany(company) 
                        || hasRole(['SuperUser', 'Manager', 'Tester']);

但如果你是公司的一员并且没有这个角色,它就会失败。我想不通的是,如果您是公司的一员但没有这个角色,这是否可行:

allow read: if isUserCompany(company) 

所以左边有效,右边有效。但他们不能一起工作。

如果我写它也有效:

allow read: if isUserCompany(company) || false; 

这让我假设如果角色不存在,问题一定出在 hasRole 函数上。我尝试编写一个函数来首先检查角色,但它仍然失败。

标签: firebasegoogle-cloud-firestorefirebase-security

解决方案


问题是您将字符串传递给 get() 而不是路径。请注意,参考文档中get()说参数是Path. 根据路径的文档:

可以通过两种方式创建路径。第一个是以正斜杠 / 开头的“原始”形式:

/路径/到/资源

第二种是使用 path() 函数从字符串转换:

路径(“路径/到/资源”)

如果你想将一个字符串组合成一个路径(因为你在某处有一个空格),你必须使用 path() 函数。或者,您可以使用该bind()函数插入其中包含空格的值。使用路径():

function hasRole(roles) {
    return get(path("databases/" + database + "/documents/companies/Seva Development/users/" + request.auth.uid)).data.roles.hasAny(roles);
}

请注意,路径的字符串形式缺少前导斜杠,所有变量都需要通过连接添加。

或者您可以从“Seva Development”中删除空格并使用路径的原始形式。


推荐阅读