gre*_*g0r 8 firebase firebase-security google-cloud-firestore firebase-cli
我正在使用mocha
和 Firestore Emulator对 Cloud Firestore 规则进行测试,问题是如何在运行测试之前初始化一些测试数据?
为了测试我的规则,我首先需要初始化一些测试数据。问题是我在使用Emulator时无法将任何数据放入文档中,文档只有id
. 我没有找到建立在规则测试,测试数据的任何例子的文档,所以我试图同时使用
makeDocumentSnapshot
来自@firebase/testing
通过和创建文档管理应用与创造initializeAdminApp
。
用例:
要访问 中的文档/objects/{object_id}
,用户必须经过身份验证并具有read
权限:get('/objects/{object_id}/users/{$(request.auth.uid)}').data.read == true
。此外,object
必须可用:get('/objects/{object_id}').data.available == true
.
因此,为了测试我的规则,我需要一些具有用户权限的预设测试数据。
预期的数据库结构:
objects collection:
object_id: {
// document fields:
available (bool)
// nested collection:
users collection: {
user_id: {
// document fields:
read (bool)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的规则示例:
objects collection:
object_id: {
// document fields:
available (bool)
// nested collection:
users collection: {
user_id: {
// document fields:
read (bool)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的测试示例:
service cloud.firestore {
match /databases/{database}/documents {
match /objects/{object} {
function objectAvailable() {
return resource.data.available;
}
// User has read access.
function userCanReadObject() {
return get(/databases/$(database)/documents/objects/$(object)/users/$(request.auth.uid)).data.read == true;
}
// Objects Permission Rules
allow read: if objectAvailable() && userCanReadObject();
allow write: if false;
// Access forbidden. Used for permission rules only.
match /users/{document=**} {
allow read, write: if false;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
测试运行的控制台输出:
1) User with permission can read objects data
0 passing (206ms)
1 failing
1) Tests for Rules
Testing
User with permission can read objects data:
FirebaseError:
false for 'get' @ L53
Run Code Online (Sandbox Code Playgroud)
为了检查创建的测试数据,我await firebase.assertSucceeds(testObj.get());
在行前添加了以下代码:
const firebase = require('@firebase/testing');
const fs = require('fs');
// Load Firestore rules from file
const firestoreRules = fs.readFileSync('../firestore.rules', 'utf8');
const projectId = 'test-application';
const test = require('firebase-functions-test')({ projectId, databaseName: projectId });
describe('Tests for Rules', () => {
let adminApp;
const testData = {
myObj: {
id: 'test',
data: {
available: true,
},
},
alice: {
id: 1,
data: {
read: true,
},
},
};
before(async () => {
// Load Rules
await firebase.loadFirestoreRules({ projectId, rules: firestoreRules });
// Initialize admin app.
adminApp = firebase.initializeAdminApp({ projectId }).firestore();
// Create test data
await adminApp.doc(`objects/${testData.myObj.id}`).set(testData.myObj.data);
await adminApp
.doc(`objects/${testData.myObj.id}/users/${testData.alice.id}`)
.set(testData.alice.data);
// Create test data with `firebase-functions-test`
// test.firestore.makeDocumentSnapshot(testData.myObj.data, `objects/${testData.myObj.id}`);
// test.firestore.makeDocumentSnapshot(
// testData.alice.data,
// `objects/${testData.myObj.id}/users/${testData.alice.id}`,
// );
});
beforeEach(async () => {
await firebase.clearFirestoreData({ projectId });
});
after(async () => {
// Shut down all testing Firestore applications after testing is done.
await Promise.all(firebase.apps().map(app => app.delete()));
});
describe('Testing', () => {
it('User with permission can read objects data', async () => {
const db = firebase
.initializeTestApp({ projectId, auth: { uid: testData.alice.id } })
.firestore();
const testObj = db.doc(`objects/${testData.myObj.id}`);
await firebase.assertSucceeds(testObj.get());
});
});
});
Run Code Online (Sandbox Code Playgroud)
输出如下:
obj data: test undefined
user data: 1 undefined
Run Code Online (Sandbox Code Playgroud)
我也尝试从 中删除代码beforeEach
,结果是一样的。
您必须在应用规则之前添加数据。
您可以在这里找到详细信息
const firebase = require('@firebase/testing');
const fs = require('fs');
let db
let projectId = `my-project-id-${Date.now()}`
async function setup(auth) {
const app = await firebase.initializeTestApp({
projectId: projectId,
auth: auth
});
db = app.firestore();
let data = {
'users/alovelace': {
first: 'Ada',
last: 'Lovelace'
}
}
// Add data before apply rules
for (const key in data) {
const ref = db.doc(key);
await ref.set(data[key]);
}
// Apply rules
await firebase.loadFirestoreRules({
projectId,
rules: fs.readFileSync('firestore.rules', 'utf8')
});
}
test('logged in', async () => {
await setup({ uid: "alovelace" })
let docRef = db.collection('users');
// check if there is data
let users = await docRef.get()
users.forEach(user => {
console.warn(user.id, user.data())
});
let read = await firebase.assertSucceeds(docRef.get());
let write = await firebase.assertFails(docRef.add({}));
await expect(read)
await expect(write)
});
afterAll(async () => {
Promise.all(firebase.apps().map(app => app.delete()))
});
Run Code Online (Sandbox Code Playgroud)
firestore.规则
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read:if request.auth.uid != null;
allow write: if false
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5404 次 |
最近记录: |