Firestore分支子集合members权限规则失效,应用请求报权限不足错误
Firestore子集合读取权限验证失败问题解决
问题描述
在Firestore的branch集合下创建了members子集合,尝试读取members数据时,实际应用代码始终返回:
FirebaseError: Missing or insufficient permissions.
Rules playground测试单个文档读取正常,但集合查询失败。将规则中依赖resource.data.company_id的逻辑替换为userId != null后,查询可正常执行。
当前规则代码:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{path=**}/members/{member} { function isCompanyAdmin(companyId, userId) { return companyId != null; // 此逻辑失效 //return userId != null; // 此逻辑正常 } allow read: if request.auth != null && isCompanyAdmin(resource.data.company_id, request.auth.uid); } } }
应用端JS代码:
const branchRef = doc(db, "branch", branch_id); const memberRef = collection(branchRef, "members"); const q = query(memberRef); const querySnapShot = await getDocs(q); querySnapShot.forEach((doc) => { console.log(doc.id, " => ", doc.data()); });
问题根源
Firestore的集合查询与单个文档读取的规则验证逻辑存在差异:
- Rules playground测试的是单个文档读取,此时
resource.data指向该文档的实际数据,规则可正常评估。 - 集合查询时,Firestore要求规则能确保查询返回的所有文档都符合权限要求。如果规则依赖单个文档的
resource.data,但查询未添加对应的过滤条件,Firestore无法逐个验证文档权限,会直接拒绝查询请求。
解决方案
方案1:调整查询语句,添加匹配规则的过滤条件
在查询中添加company_id非空的过滤条件,让Firestore能验证查询结果符合规则要求:
const q = query(memberRef, where("company_id", "!=", null));
方案2:修改规则,从父文档获取company_id
由于members是branch的子集合,可通过父branch文档获取company_id,避免依赖子文档的resource.data:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /branch/{branch_id}/members/{member_id} { function isCompanyAdmin() { // 读取父branch文档的company_id字段 return get(/databases/$(database)/documents/branch/$(branch_id)).data.company_id != null; } allow read: if request.auth != null && isCompanyAdmin(); } } }
方案3:优化规则逻辑(若需用户与公司关联)
如果需要验证用户属于该公司,可结合用户文档的信息(假设用户文档存储在users集合,包含company_id字段):
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /branch/{branch_id}/members/{member_id} { function isCompanyAdmin() { let branchCompanyId = get(/databases/$(database)/documents/branch/$(branch_id)).data.company_id; let userCompanyId = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.company_id; return branchCompanyId == userCompanyId; } allow read: if request.auth != null && isCompanyAdmin(); } } }
内容的提问来源于stack exchange,提问作者kcodem01
相关产品推荐
相关产品推荐

