You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firestore本地模拟器中删除与更新文档安全规则测试问题排查

问题分析与解决方案

首先,咱们先揪出最可能的核心问题——安全规则的路径匹配和你测试的文档路径不匹配!

看你的安全规则:

match /posts/{postId} { 
  allow read: if true; 
  allow create: if true; 
  allow delete, update: if (resource.data.user.uid == request.auth.uid) 
}

这个规则是匹配根集合下的posts文档,但你的测试代码里操作的是嵌套子集合:

const testDoc = db 
  .collection("general") 
  .doc("spaces") 
  .collection("spaces") 
  .doc("9LbUetZxWeL1ln5hv9ug") 
  .collection("posts") 
  .doc("RtUnezdAgXUfWmRSPpkF");

也就是这个文档的完整路径是general/spaces/spaces/9LbUetZxWeL1ln5hv9ug/posts/RtUnezdAgXUfWmRSPpkF,你的安全规则根本没覆盖到这个嵌套层级的posts子集合,所以模拟器默认拒绝了操作。而你说硬编码路径能成功,应该是硬编码的路径刚好和规则里的根级posts匹配了。

另外,还有一个容易忽略的点——Firebase测试模拟器的环境隔离性:
你在模拟器UI里手动添加的文档,不会被测试用例访问到,因为每个测试用例都会初始化一个干净的独立环境。哪怕你在UI里看到文档存在,测试代码里的数据库其实是空的,除非你在测试代码里先创建这个文档并设置好user.uid字段。

具体修复步骤:

  1. 调整安全规则匹配正确的路径
    你需要修改规则来覆盖嵌套子集合的posts,有两种方式:

    • 精准匹配你的嵌套路径:
      match /general/spaces/spaces/{spaceId}/posts/{postId} {
        allow read: if true;
        allow create: if true;
        allow delete, update: if resource.data.user.uid == request.auth.uid;
      }
      
    • 如果有多个层级的posts子集合,可以用递归匹配(注意安全性,只在你需要所有posts子集合用同一规则时使用):
      match /{path=**}/posts/{postId} {
        allow read: if true;
        allow create: if true;
        allow delete, update: if resource.data.user.uid == request.auth.uid;
      }
      
  2. 在测试用例中初始化目标文档
    因为测试环境是隔离的,你需要在测试前先创建文档并设置正确的user.uid,确保和request.auth.uid一致:

    it("If creator, Allow delete/update items in the post/comment collection", async () => { 
      const db = firebase 
        .initializeTestApp({ projectId: MY_PROJECT_ID, auth: myAuth }) 
        .firestore(); 
      const testDoc = db 
        .collection("general") 
        .doc("spaces") 
        .collection("spaces") 
        .doc("9LbUetZxWeL1ln5hv9ug") 
        .collection("posts") 
        .doc("RtUnezdAgXUfWmRSPpkF");
      
      // 先创建文档并设置匹配的user.uid
      await testDoc.set({
        user: { uid: myAuth.uid }
      });
      
      // 再执行删除断言
      await firebase.assertSucceeds(testDoc.delete()); 
    });
    
  3. 验证规则加载是否正确
    确保你在测试前正确加载了安全规则,比如在测试文件开头添加:

    beforeAll(async () => {
      await firebase.loadFirestoreRules({
        projectId: MY_PROJECT_ID,
        rules: fs.readFileSync("path/to/your/firestore.rules", "utf8")
      });
    });
    

    避免测试用的是旧规则或者默认规则。

按照这几步调整后,应该就能解决你的问题了!

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:51:31