我写了一个简单的集合组安全规则和测试代码如下。
安全规则:
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}
变量仅在集合组查询中为空。
这个行为是文档写的吗? 谢谢。
答案 0 :(得分:0)
您的第二次测试似乎没有通过此 email
。
Cloud Firestore 会根据查询的潜在结果集而不是所有文档的实际字段值来评估查询。
resource
变量引用请求的文档,resource.data
是存储在文档中的所有字段和值的映射。因此,当您使用 resource.data.email
时,您是在缩小范围以获得答案,而 email
过滤器不会自然地发生这种情况。
以下是差异的解释:Data validation