【问题标题】:Declaring a function in Firestore rules在 Firestore 规则中声明函数
【发布时间】:2019-06-04 11:17:07
【问题描述】:

这是我现在面临的 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 - 不走运。

【问题讨论】:

标签: firebase google-cloud-firestore firebase-security


【解决方案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'));

【讨论】:

    【解决方案2】:

    不可能,规则只在它们定义的范围内起作用,他们非常巧妙地提到了here

    【讨论】:

    • 感谢您的回答
    猜你喜欢
    • 1970-01-01
    • 2019-07-19
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 2019-12-12
    相关资源
    最近更新 更多