这是我现在面临的 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
消息。所以问题是:是否可以像我在示例中那样将函数移到外面?我在这里犯了什么明显的错误吗?有没有更好的方法让我的规则设置得更加清晰?
附言
我还尝试将一些参数传递给该函数,包括用户和公司 ID - 不走运。
最佳答案
可以在规则文件中的任何级别定义函数。但是他们只能访问在您定义它们的范围内定义的变量。您必须作为变量传入的任何其他内容。
所以这个(无用的)函数在全局定义时有效:
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'));
关于firebase - 在 Firestore 规则中声明一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56442795/