这是我现在所面临的Firestore安全规则问题。
首先,这是我在Firestore数据库中拥有的数据结构的示例:
userProfiles/userId/userData
companies/companyId/companyData
看起来很简单。每个userData
都包含一个名为companies
的数组,其中包含该用户有权访问的所有companyId。
现在,我需要编写规则以仅在companyId特别是用户信息公司列表中才允许读取companyData。
以下是对我来说起作用的规则:
service cloud.firestore {
match /databases/{database}/documents {
match /companies/{companyId} {
allow read: if companyId in get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
}
}
}
基于我将要拥有更多规则的事实,我想使它们更具可读性和重用性。根据此official guide,我可以创建自定义函数,并根据此article,它们可以是通用的,并且可以在主要规则框外声明。
我重构了规则,使其看起来像这样,并且对我也有效:
service cloud.firestore {
match /databases/{database}/documents {
match /companies/{companyId} {
allow read: if companyId in getUserCompanies()
}
function getUserCompanies() {
return get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
}
}
}
但是现在我想将功能移到规则块之外以使其更加清晰:
service cloud.firestore {
match /databases/{database}/documents {
match /companies/{companyId} {
allow read: if companyId in getUserCompanies()
}
}
}
function getUserCompanies() {
return get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
}
那是行不通的。没有任何错误,我只是从模拟器收到常规的Read denied
消息。
因此问题是:是否可以像我在示例中所做的那样将函数移到外部?我在这里有明显的错误吗?有没有更好的方法可以使我的规则更加明确?
P.S。 我还尝试将一些参数传递给该函数,包括用户名和公司ID-不用运气。
答案 0 :(得分:1)
这是不可能的,规则仅在定义的范围内起作用,它们非常巧妙地提到了here
答案 1 :(得分:1)
可以在规则文件中的任何级别上定义功能。但是它们只能访问在定义它们的作用域中定义的变量。您还必须将其他任何内容作为变量传递。
因此,此(无用的)函数在全局定义时有效:
function isTrue() {
return true;
}
但是这个不会,因为它无权访问request
:
function isAdmin() {
return (request.auth.token.email_verified &&
request.auth.token.email.matches(".*@google.com"));
}
我有时要做的是在函数定义中添加一个参数:
function isAdmin(request) {
return (request.auth.token.email_verified &&
request.auth.token.email.matches(".*@google.com"));
}
,然后将变量传递给调用:
allow update: if isAdmin(request) ||
(request.auth.uid == uid && isUnmodified(request, resource, 'name'));