首页 > 解决方案 > 如何在 Firestore 规则中访问文档 ID

问题描述

在尝试使用这些规则进行查询时,我似乎无法访问 resource.id 值。当我手动输入学校 ID(注释掉的行)时,数据返回正常。我只有 1 所学校,并且文档 ID 肯定与字符串匹配。但是当我要求匹配 resource.id 值时,我的规则返回“权限不足”错误。

    rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
            //functions
        function signedIn() {
        return request.auth.uid != null;
            }
        
        function returnUID(){
        return request.auth.uid;
        }
  
  function getUserData() {
    return get(/databases/$(database)/documents/All%20Users/$(request.auth.uid)).data;
}
  
  
                match /All%20Users/{userID} {
          allow read,write: if 
          signedIn() && returnUID() == userID;
          }
  
          match /All%20Schools/{schoolID}{
            allow read, write: if
         //  signedIn() && getUserData().school == "f7asMxUvTs3uFhE08AJr"
             signedIn() && getUserData().school == resource.id
          }
          
          
    
  }
}

数据层次结构图

我的结构是这样的

所有学校/学校(文档)/教室(子集合)所有用户/用户(文档)(每个用户文档都有一个关联的教室ID)

作为参考,这是一个成功的查询

var docRef = db.collection("All Users").doc(uid).get()

和失败的那个

db.collection("All Schools/" + properties.schoolid + "/Classrooms").onSnapshot()

[更新] 工作规则集!

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
            //functions
        function signedIn() {
        return request.auth.uid != null;
            }
        
        function returnUID(){
        return request.auth.uid;
        }
  
  function getUserData() {
    return get(/databases/$(database)/documents/All%20Users/$(request.auth.uid)).data;
}
  
  
                match /All%20Users/{userID} {
          allow read,write: if 
          signedIn() && returnUID() == userID;
          }
  
          match /All%20Schools/{schoolID}{
            allow read, write: if   schoolID == 'f7asMxUvTs3uFhE08AJr'
           
          }
          match /All%20Schools/{schoolID}/Classrooms/{classId} {
  allow read, write: if getUserData().school == schoolID;
}
          match /All%20Schools/{schoolID}/Student%20List/{student} {
  allow read, write: if getUserData().school == schoolID;
}
    match /All%20Schools/{schoolID}/Staff/{staff} {
  allow read, write: if getUserData().school == schoolID;
}
  }
}

标签: firebasegoogle-cloud-firestorefirebase-security

解决方案


以下规则仅适用于“所有学校”集合的文件,而不是“教室”子集合的文件:

match /All%20Schools/{schoolID} {
  // ...
}

这就是为什么db.collection("All Users").doc(uid).get()工作和获取“教室”集合失败的原因,因为您没有为它指定任何规则。尽管您之前有一个递归通配符(在编辑问题之前),但resource对象包含那些在“教室”子集合中匹配的文档的数据,因此getUserData().school == resource.id也失败了。

话虽如此,请尝试为“教室”子集合指定规则:

match /All%20Schools/{schoolID}/Classrooms/{classId} {
  allow read, write: if getUserData().school == schoolID;
}

推荐阅读