Skip to content

Commit 85c7351

Browse files
authored
BE-7008 Added test cases for the direct-shared records (#97)
* Added test cases for the direct-shared records * Moved the beforeEach hook out of the Owned Records test suite
1 parent 7e9be5a commit 85c7351

1 file changed

Lines changed: 154 additions & 19 deletions

File tree

keeperapi/src/__tests__/vault.test.ts

Lines changed: 154 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ describe('Sync Down', () => {
1717
username: string,
1818
accountUid: Uint8Array,
1919
}
20+
let anotherUserA: {
21+
username: string,
22+
accountUid: Uint8Array,
23+
}
2024
beforeAll(async () => {
2125
connectPlatform(nodePlatform)
2226
dataKey = platform.getRandomBytes(32)
@@ -25,27 +29,31 @@ describe('Sync Down', () => {
2529
username: 'keeper@keepersecurity.com',
2630
accountUid: platform.getRandomBytes(16)
2731
}
32+
anotherUserA = {
33+
username: 'another@keepersecurity.com',
34+
accountUid: platform.getRandomBytes(16)
35+
}
36+
})
37+
beforeEach(() => {
38+
storage = {
39+
get: jest.fn(),
40+
addDependencies: jest.fn(),
41+
delete: jest.fn(),
42+
removeDependencies: jest.fn(),
43+
put: jest.fn(),
44+
saveObject: jest.fn(),
45+
saveKeyBytes: jest.fn(),
46+
} as unknown as VaultStorage;
47+
mockSyncDownCommand = jest.fn()
48+
auth = {
49+
dataKey,
50+
eccPrivateKey: eccKeyPair.privateKey,
51+
eccPublicKey: eccKeyPair.publicKey,
52+
executeRest: mockSyncDownCommand,
53+
} as unknown as Auth;
54+
syncDownResponseBuilder = new SyncDownResponseBuilder();
2855
})
2956
describe('Owned Records', () => {
30-
beforeEach(() => {
31-
storage = {
32-
get: jest.fn(),
33-
addDependencies: jest.fn(),
34-
delete: jest.fn(),
35-
removeDependencies: jest.fn(),
36-
put: jest.fn(),
37-
saveObject: jest.fn(),
38-
saveKeyBytes: jest.fn(),
39-
} as unknown as VaultStorage;
40-
mockSyncDownCommand = jest.fn()
41-
auth = {
42-
dataKey,
43-
eccPrivateKey: eccKeyPair.privateKey,
44-
eccPublicKey: eccKeyPair.publicKey,
45-
executeRest: mockSyncDownCommand,
46-
} as unknown as Auth;
47-
syncDownResponseBuilder = new SyncDownResponseBuilder();
48-
})
4957
it('saves the record data when a new record is created by the user', async () => {
5058
const decryptedRecordKey = platform.getRandomBytes(32)
5159
const recordKey = await platform.aesGcmEncrypt(decryptedRecordKey, auth.dataKey!)
@@ -254,5 +262,132 @@ describe('Sync Down', () => {
254262
expect(storage.delete).toHaveBeenCalledWith('record', webSafe64FromBytes(recordUid))
255263
})
256264
})
265+
describe('Directly-Shared Records', () => {
266+
it('saves the record data when a record is direct-shared by other user', async () => {
267+
const decryptedRecordKey = platform.getRandomBytes(32)
268+
const recordKey = await platform.aesGcmEncrypt(decryptedRecordKey, auth.dataKey!)
269+
const recordUid = platform.getRandomBytes(16)
270+
const recordUidStr = webSafe64FromBytes(recordUid)
271+
const decryptedRecordData = {
272+
title: 'test record',
273+
}
274+
const decodedRecordData = platform.stringToBytes(JSON.stringify(decryptedRecordData))
275+
const recordData = await platform.aesGcmEncrypt(decodedRecordData, decryptedRecordKey)
276+
const userFolderRecord: Vault.IUserFolderRecord = {
277+
recordUid,
278+
revision: 1,
279+
}
280+
const recordMetadata: Vault.IRecordMetaData = {
281+
recordUid,
282+
recordKey,
283+
owner: false,
284+
canEdit: true,
285+
canShare: true,
286+
recordKeyType: Records.RecordKeyType.ENCRYPTED_BY_DATA_KEY_GCM,
287+
ownerUsername: anotherUserA.username,
288+
ownerAccountUid: anotherUserA.accountUid,
289+
}
290+
const record: Vault.IRecord = {
291+
recordUid,
292+
version: 3,
293+
data: recordData,
294+
extra: new Uint8Array([]),
295+
}
296+
syncDownResponseBuilder
297+
.addUserFolderRecord(userFolderRecord)
298+
.addRecordMetadata(recordMetadata)
299+
.addRecord(record)
300+
mockSyncDownCommand.mockResolvedValue(syncDownResponseBuilder.build())
301+
await syncDown({
302+
auth,
303+
storage,
304+
})
305+
expect(storage.put).toHaveBeenCalledWith(
306+
expect.objectContaining({
307+
kind: 'metadata',
308+
uid: recordUidStr,
309+
owner: recordMetadata.owner,
310+
ownerUsername: recordMetadata.ownerUsername,
311+
})
312+
)
313+
expect(storage.put).toHaveBeenCalledWith(
314+
expect.objectContaining({
315+
kind: 'record',
316+
uid: recordUidStr,
317+
data: decryptedRecordData,
318+
})
319+
)
320+
expect(storage.addDependencies).toHaveBeenCalledWith({
321+
"": new Set([{
322+
kind: "record",
323+
"parentUid": "",
324+
uid: recordUidStr,
325+
}])
326+
})
327+
})
328+
it('saves the record data when the direct-shared record is updated by another user or the user', async () => {
329+
const decryptedRecordKey = platform.getRandomBytes(32)
330+
const recordKey = await platform.aesGcmEncrypt(decryptedRecordKey, auth.dataKey!)
331+
const recordUid = platform.getRandomBytes(16)
332+
const recordUidStr = webSafe64FromBytes(recordUid)
333+
await platform.unwrapKey(recordKey, recordUidStr, 'data', 'gcm', 'aes')
334+
const decryptedRecordData = {
335+
title: 'test record updated',
336+
}
337+
const decodedRecordData = platform.stringToBytes(JSON.stringify(decryptedRecordData))
338+
const recordData = await platform.aesGcmEncrypt(decodedRecordData, decryptedRecordKey)
339+
const recordMetadata: Vault.IRecordMetaData = {
340+
recordUid,
341+
recordKey,
342+
owner: false,
343+
canEdit: true,
344+
canShare: true,
345+
recordKeyType: Records.RecordKeyType.ENCRYPTED_BY_DATA_KEY_GCM,
346+
ownerUsername: anotherUserA.username,
347+
ownerAccountUid: anotherUserA.accountUid,
348+
}
349+
const record: Vault.IRecord = {
350+
recordUid,
351+
version: 3,
352+
data: recordData,
353+
extra: new Uint8Array([]),
354+
}
355+
syncDownResponseBuilder
356+
.addRecord(record)
357+
.addRecordMetadata(recordMetadata)
358+
mockSyncDownCommand.mockResolvedValue(syncDownResponseBuilder.build())
359+
await syncDown({
360+
auth,
361+
storage,
362+
})
363+
expect(storage.put).toHaveBeenCalledWith(
364+
expect.objectContaining({
365+
kind: 'metadata',
366+
uid: recordUidStr,
367+
owner: recordMetadata.owner,
368+
ownerUsername: recordMetadata.ownerUsername,
369+
})
370+
)
371+
expect(storage.put).toHaveBeenCalledWith(
372+
expect.objectContaining({
373+
kind: 'record',
374+
uid: recordUidStr,
375+
data: decryptedRecordData,
376+
})
377+
)
378+
})
379+
it('deletes the record data when the direct-shared record is unshared by another user or deleted by the user', async () => {
380+
const recordUid = platform.getRandomBytes(16)
381+
syncDownResponseBuilder
382+
.addRemovedRecord(recordUid)
383+
mockSyncDownCommand.mockResolvedValue(syncDownResponseBuilder.build())
384+
await syncDown({
385+
auth,
386+
storage,
387+
})
388+
expect(storage.delete).toHaveBeenCalledWith('record', webSafe64FromBytes(recordUid))
389+
})
390+
it('does nothing when the direct-shared record is deleted by another user', () => {})
391+
})
257392
})
258393

0 commit comments

Comments
 (0)