Firestore:集合组安全规则的文档 ID 变为空

时间:2021-06-14 06:24:13

标签: firebase google-cloud-firestore

我写了一个简单的集合组安全规则和测试代码如下。

安全规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /projects/{project_id}/members/{email} {
      allow write: if false;
    }
    match /{path=**}/members/{email} {
      allow read: if request.auth != null && request.auth.token.email == email;
    }
  }
}

测试代码:


const assert = require('assert');
const firebase = require('@firebase/rules-unit-testing');
const MY_PROJECT_ID = 'XXXXXXXX';
const member1Data = {email: 'member1@gmail.com', name: 'John Smith'};
const member1Auth = {uid: "member1_uid", email: member1Data.email};

beforeEach(async () => {
  await firebase.clearFirestoreData({projectId: MY_PROJECT_ID});
  const db = firebase.initializeAdminApp({projectId: MY_PROJECT_ID }).firestore();

  // create 2 same members data across projects
  await db.collection('projects/project-1/members')
    .doc(member1Data.email).set(member1Data);
  await db.collection('projects/project-2/members')
    .doc(member1Data.email).set(member1Data);
})

describe("Firestore rules test", () => {
  // 1 - direct access
  it( "Can get specific record", async () =>{
    const db = firebase.initializeTestApp({projectId: MY_PROJECT_ID, auth: member1Auth }).firestore();
    const doc
      = await db.collection("projects/project-1/members").doc(member1Data.email);

    await firebase.assertSucceeds(doc.get());
  });
  // 2 - use collection group
  it( "Can get 2 records", async () =>{
    const db = firebase.initializeTestApp({projectId: MY_PROJECT_ID, auth: member1Auth }).firestore();
    const result
      = await db.collectionGroup("members")
        .where("email", "==", member1Data.email).get();

    assert.strictEqual(result.size, 2);
  });
});

当我运行测试时,第一个通过了,但第二个失败了。 经过一番研究,我发现变量 {email} 在第二次测试中为 null

当我将规则更改为以下(将 email 更改为 resource.data.email 时,所有测试均已通过。

 :
match /{path=**}/members/{email} {
      allow read: if request.auth != null && request.auth.token.email == resource.data.email;
}
 :

所以我想知道为什么 {email} 变量仅在集合组查询中为空。

这个行为是文档写的吗? 谢谢。

1 个答案:

答案 0 :(得分:0)

您的第二次测试似乎没有通过此 email

Cloud Firestore 会根据查询的潜在结果集而不是所有文档的实际字段值来评估查询。

resource 变量引用请求的文档,resource.data 是存储在文档中的所有字段和值的映射。因此,当您使用 resource.data.email 时,您是在缩小范围以获得答案,而 email 过滤器不会自然地发生这种情况。

以下是差异的解释:Data validation