Firebase 安全规则限制除一个路径之外的所有路径的访问?

Gen*_* Bo 5 firebase-security google-cloud-functions google-cloud-firestore

问题:

对于下面不同的顶级 Firestore 集合,如何限制对除其中一个路径之外的所有路径的访问?

我们正在 Firestore 中构建数据架构,以支持多所学校教师的聊天应用程序。

顶级 Firestore 系列包括:

  • /siteAdminUsers
  • /schools
  • /schools/{schoolId}/teachers
  • /schools/{schoolId}/chats

以下是我们现在正在尝试的安全规则设置 - 我们在其中检查:

  1. 有效的用户授权
  2. userClaim 变量中存在预期值request.auth.token.chatFlatList

但是,读取侦听器/messages被阻止。

错误信息:

FirebaseError:[code=permission-denied]:权限缺失或不足


service cloud.firestore {
  match /databases/{database}/documents {

    match /{document=**} {
      allow read, write: if false;
    }

    match /schools/{schoolId}/chats/{discussionId}/messages {
      allow write: if false;
      allow read: if request.auth != null
                  && request.auth.token != null
                  && request.auth.token.chatFlatList.val().contains($discussionId);
    }
}
Run Code Online (Sandbox Code Playgroud)

细节

我们使用云函数来进行所有数据读/写,因此几乎在每种情况下我们都可以阻止所有客户端访问。

一个例外是聊天讨论,我们需要在移动客户端中设置一个快照侦听器以了解何时有新消息。

子集注释:

在学校,为学校工作人员(教师、行政人员等)举办讨论会

/schools/{schoolId}/chats/{discussionId}
Run Code Online (Sandbox Code Playgroud)

每个讨论文档包含:

  1. 参与者教师 ID 列表
  2. 实际消息的子集合,其中每个文档都是单独的发布消息:

/schools/{schoolId}/chats/{discussionId}/messages

用户从 Cloud Function 获取代码

查看云函数日志,我们已经验证了 userClaim 已被设置。

/schools/{schoolId}/chats/{discussionId}
Run Code Online (Sandbox Code Playgroud)

更新#1

尝试了以下变体,其中规则跳过/省略对 userClaim 和 auth.token 的检查。

但是,仍然存在相同的权限错误。

return firebaseAdmin
    .auth()
    .setCustomUserClaims(
        uid, {
            chatFlatList: 'id1 id2 id3'
        }
    );
Run Code Online (Sandbox Code Playgroud)

Gen*_* Bo 0

这是一个解决方案(似乎有效),其中包括检查chatFlatList 用户声明变量(来自原始问题)的子字符串:

        match /schools/{schoolId}/chats/{discussionId}/messages {
          allow write: if false;
          allow read: if request.auth != null
          && request.auth.token.chatFlatList.matches(discussionId);
        }
Run Code Online (Sandbox Code Playgroud)

弄清楚这一点要归功于:

  1. 基于自定义参数的 Firebase 存储规则

    • 这里的帖子显示没有任何$符号来访问路径变量。我记得在安全规则示例代码示例中看到过这一点 -也许它特定于数据库层?
  2. https://firebase.google.com/docs/reference/security/storage/#string

  3. https://regex-golang.appspot.com/assets/html/index.html

    • 在这里尝试一些示例输入,以了解如何创建正则表达式。