问题:
对于以下不同的顶级Firestore集合,如何限制对除其中一条路径以外的所有路径的访问?
我们正在Firestore中构建数据架构,以支持跨多个学校的教师的聊天应用程序。
顶级Firestore集合包括:
/siteAdminUsers
/schools
/schools/{schoolId}/teachers
/schools/{schoolId}/chats
以下是我们正在尝试的安全规则设置-我们在其中进行检查:
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);
}
}
详细信息
我们将云功能用于所有数据读写,因此在几乎每种情况下,我们都可以阻止所有客户端访问。
聊天讨论是一个例外,我们需要在移动客户端中设置快照侦听器,以了解何时有新消息。
子收藏夹:
在学校,有针对学校工作人员(老师,管理员等)的讨论会
/schools/{schoolId}/chats/{discussionId}
每个讨论文档所在的位置:
/schools/{schoolId}/chats/{discussionId}/messages
Cloud Function中的用户声明代码
查看云功能日志,我们已验证是否已设置userClaim。
return firebaseAdmin
.auth()
.setCustomUserClaims(
uid, {
chatFlatList: 'id1 id2 id3'
}
);
更新#1
尝试了以下变体,其中规则跳过/省略了对userClaim和auth.token的检查。
但是,仍然存在相同的权限错误。
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;
}
}
}
答案 0 :(得分:3)
我认为这里的问题是,您正在对称为消息的集合编写规则。
所有match语句应指向文档,而不是集合。 https://firebase.google.com/docs/firestore/security/rules-structure
您应该尝试在邮件路径之后添加/ {document = **},例如:
match /schools/{schoolId}/chats/{discussionId}/messages/{document=**} {
allow write: if false;
allow read: if request.auth != null;
}
答案 1 :(得分:1)
如果我想读写所有集合而不是一个名为“ backStage”的集合,这对我很有用;
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{collection}/{document} {
allow read: if true
allow write: if (collection != "backStage");
}
}
}
答案 2 :(得分:0)
这是一个解决方案(似乎正在工作),其中包括检查chatFlatList
用户声明变量(来自原始问题)是否存在子字符串:
match /schools/{schoolId}/chats/{discussionId}/messages {
allow write: if false;
allow read: if request.auth != null
&& request.auth.token.chatFlatList.matches(discussionId);
}
通过以下方式解决了这个问题:
Firebase storage rules based on custom parameters
$
符号来访问路径var。我记得在安全规则示例代码示例中看到过这种情况-也许它特定于数据库层吗? https://firebase.google.com/docs/reference/security/storage/#string
https://regex-golang.appspot.com/assets/html/index.html