tests: vault tests 3 (#2373)

This commit is contained in:
Mo
2023-07-27 07:35:38 -05:00
committed by GitHub
parent 1fef36d601
commit 14bae5e895
26 changed files with 350 additions and 283 deletions

View File

@@ -6,6 +6,7 @@ export const VaultTests = {
'vaults/pkc.test.js',
'vaults/contacts.test.js',
'vaults/crypto.test.js',
'vaults/importing.test.js',
'vaults/asymmetric-messages.test.js',
'vaults/keypair-change.test.js',
'vaults/signatures.test.js',
@@ -16,7 +17,7 @@ export const VaultTests = {
'vaults/conflicts.test.js',
'vaults/deletion.test.js',
'vaults/permissions.test.js',
'vaults/key_rotation.test.js',
'vaults/key-rotation.test.js',
'vaults/files.test.js',
],
}

View File

@@ -755,7 +755,7 @@ describe('keys', function () {
currentServerPassword: currentRootKey.serverPassword,
newRootKey,
})
await this.application.encryption.reencryptApplicableItemsAfterUserRootKeyChange()
await this.application.dependencies.get(TYPES.ReencryptTypeAItems).execute()
/** Note: this may result in a deadlock if features_service syncs and results in an error */
await this.application.sync.sync({ awaitAll: true })

View File

@@ -369,6 +369,17 @@ export class AppContext {
})
}
spyOnFunctionResult(object, functionName) {
return new Promise((resolve) => {
sinon.stub(object, functionName).callsFake(async (params) => {
object[functionName].restore()
const result = await object[functionName](params)
resolve(result)
return result
})
})
}
resolveWhenAsymmetricMessageProcessingCompletes() {
return this.resolveWhenAsyncFunctionCompletes(this.asymmetric, 'handleRemoteReceivedAsymmetricMessages')
}

View File

@@ -121,71 +121,4 @@ describe('migrations', () => {
await Factory.safeDeinit(application)
})
describe('2.202.1', () => {
let application
beforeEach(async () => {
application = await Factory.createAppWithRandNamespace()
await application.prepareForLaunch({
receiveChallenge: () => {},
})
await application.launch(true)
})
afterEach(async () => {
await Factory.safeDeinit(application)
})
it('remove components that are available as native features', async function () {
const editor = CreateDecryptedItemFromPayload(
new DecryptedPayload({
uuid: '123',
content_type: ContentType.TYPES.Component,
content: FillItemContent({
package_info: {
identifier: NativeFeatureIdentifier.TYPES.MarkdownProEditor,
},
}),
}),
)
await application.mutator.insertItem(editor)
await application.sync.sync()
expect(application.items.getItems(ContentType.TYPES.Component).length).to.equal(1)
/** Run migration */
const migration = new Migration2_202_1(application.migrations.services)
await migration.handleStage(ApplicationStage.FullSyncCompleted_13)
await application.sync.sync()
expect(application.items.getItems(ContentType.TYPES.Component).length).to.equal(0)
})
it('do not remove components that are available as native features but deprecated', async function () {
const editor = CreateDecryptedItemFromPayload(
new DecryptedPayload({
uuid: '123',
content_type: ContentType.TYPES.Component,
content: FillItemContent({
package_info: {
identifier: NativeFeatureIdentifier.TYPES.DeprecatedBoldEditor,
},
}),
}),
)
await application.mutator.insertItem(editor)
await application.sync.sync()
expect(application.items.getItems(ContentType.TYPES.Component).length).to.equal(1)
/** Run migration */
const migration = new Migration2_202_1(application.migrations.services)
await migration.handleStage(ApplicationStage.FullSyncCompleted_13)
await application.sync.sync()
expect(application.items.getItems(ContentType.TYPES.Component).length).to.equal(1)
})
})
})

View File

@@ -882,8 +882,4 @@ describe('importing', function () {
expect(application.items.referencesForItem(importedTag).length).to.equal(1)
expect(application.items.itemsReferencingItem(importedNote).length).to.equal(1)
})
it('should decrypt backup file which contains a vaulted note without a synced key system root key', async () => {
console.error('TODO: Implement this test')
})
})

View File

@@ -101,7 +101,7 @@ describe('contacts', function () {
await deinitContactContext()
})
it('should be able to refresh a contact using a collaborationID that includes full chain of previouos public keys', async () => {
it('should be able to refresh a contact using a collaborationID that includes full chain of previous public keys', async () => {
console.error('TODO: implement test')
})
})

View File

@@ -35,12 +35,25 @@ describe('shared vault crypto', function () {
expect(recreatedContext.encryption.getSigningKeyPair()).to.not.be.undefined
})
it('changing user password should re-encrypt all key system root keys', async () => {
console.error('TODO: implement')
})
it('changing user password should re-encrypt all key system root keys and contacts with new user root key', async () => {
await Collaboration.createPrivateVault(context)
const spy = context.spyOnFunctionResult(context.application.sync, 'payloadsByPreparingForServer')
await context.changePassword('new_password')
it('changing user password should re-encrypt all trusted contacts', async () => {
console.error('TODO: implement')
const payloads = await spy
const keyPayloads = payloads.filter(
(payload) =>
payload.content_type === ContentType.TYPES.KeySystemRootKey ||
payload.content_type === ContentType.TYPES.TrustedContact,
)
expect(keyPayloads.length).to.equal(2)
for (const payload of payloads) {
const keyParams = context.encryption.getEmbeddedPayloadAuthenticatedData(new EncryptedPayload(payload)).kp
const userKeyParams = context.encryption.getRootKeyParams().content
expect(keyParams).to.eql(userKeyParams)
}
})
})

View File

@@ -0,0 +1,58 @@
import * as Factory from '../lib/factory.js'
import * as Collaboration from '../lib/Collaboration.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe.skip('vault importing', function () {
this.timeout(Factory.TwentySecondTimeout)
let context
afterEach(async function () {
await context.deinit()
localStorage.clear()
})
beforeEach(async function () {
localStorage.clear()
context = await Factory.createAppContextWithRealCrypto()
await context.launch()
await context.register()
})
it('should import vaulted items with synced root key', async () => {
console.error('TODO: implement')
})
it('should import vaulted items with non-present root key', async () => {
const vault = await context.vaults.createUserInputtedPasswordVault({
name: 'test vault',
userInputtedPassword: 'test password',
storagePreference: KeySystemRootKeyStorageMode.Ephemeral,
})
const note = await context.createSyncedNote('foo', 'bar')
await Collaboration.moveItemToVault(context, vault, note)
const backupData = await context.application.createEncryptedBackupFileForAutomatedDesktopBackups()
const otherContext = await Factory.createAppContextWithRealCrypto()
await otherContext.launch()
await otherContext.application.importData(backupData)
const expectedImportedItems = ['vault-items-key', 'note']
const invalidItems = otherContext.items.invalidItems
expect(invalidItems.length).to.equal(expectedImportedItems.length)
const encryptedItem = invalidItems[0]
expect(encryptedItem.key_system_identifier).to.equal(vault.systemIdentifier)
expect(encryptedItem.errorDecrypting).to.be.true
expect(encryptedItem.uuid).to.equal(note.uuid)
await otherContext.deinit()
})
})

View File

@@ -4,7 +4,7 @@ import * as Collaboration from '../lib/Collaboration.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('shared vault key rotation', function () {
describe('vault key rotation', function () {
this.timeout(Factory.TwentySecondTimeout)
let context
@@ -29,17 +29,66 @@ describe('shared vault key rotation', function () {
contactContext.lockSyncing()
const spy = sinon.spy(context.keys, 'queueVaultItemsKeysForReencryption')
const callSpy = sinon.spy(context.keys, 'queueVaultItemsKeysForReencryption')
const syncSpy = context.spyOnFunctionResult(context.application.sync, 'payloadsByPreparingForServer')
const promise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault)
await context.vaults.rotateVaultRootKey(sharedVault)
await promise
await syncSpy
expect(spy.callCount).to.equal(1)
expect(callSpy.callCount).to.equal(1)
const payloads = await syncSpy
const keyPayloads = payloads.filter((payload) => payload.content_type === ContentType.TYPES.KeySystemItemsKey)
expect(keyPayloads.length).to.equal(2)
const vaultRootKey = context.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)
for (const payload of keyPayloads) {
const keyParams = context.encryption.getEmbeddedPayloadAuthenticatedData(new EncryptedPayload(payload)).kp
expect(keyParams).to.eql(vaultRootKey.keyParams)
}
deinitContactContext()
})
it('should update value of local storage mode key', async () => {
const vault = await context.vaults.createUserInputtedPasswordVault({
name: 'test vault',
userInputtedPassword: 'test password',
storagePreference: KeySystemRootKeyStorageMode.Local,
})
const beforeKey = context.keys.getRootKeyFromStorageForVault(vault.systemIdentifier)
await context.vaults.rotateVaultRootKey(vault, 'test password')
const afterKey = context.keys.getRootKeyFromStorageForVault(vault.systemIdentifier)
expect(afterKey.keyParams.creationTimestamp).to.be.greaterThan(beforeKey.keyParams.creationTimestamp)
expect(afterKey.key).to.not.equal(beforeKey.key)
expect(afterKey.itemsKey).to.not.equal(beforeKey.itemsKey)
})
it('should update value of mem storage mode key', async () => {
const vault = await context.vaults.createUserInputtedPasswordVault({
name: 'test vault',
userInputtedPassword: 'test password',
storagePreference: KeySystemRootKeyStorageMode.Ephemeral,
})
const beforeKey = context.keys.getMemCachedRootKey(vault.systemIdentifier)
await context.vaults.rotateVaultRootKey(vault, 'test password')
const afterKey = context.keys.getMemCachedRootKey(vault.systemIdentifier)
expect(afterKey.keyParams.creationTimestamp).to.be.greaterThan(beforeKey.keyParams.creationTimestamp)
expect(afterKey.key).to.not.equal(beforeKey.key)
expect(afterKey.itemsKey).to.not.equal(beforeKey.itemsKey)
})
it("rotating a vault's key should send an asymmetric message to all members", async () => {
const { sharedVault, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)

View File

@@ -104,10 +104,27 @@ describe('shared vaults', function () {
})
it('should convert a vault to a shared vault', async () => {
console.error('TODO')
})
const privateVault = await context.vaults.createRandomizedVault({
name: 'My Private Vault',
})
it('should send metadata change message when changing name or description', async () => {
console.error('TODO')
const note = await context.createSyncedNote('foo', 'bar')
await context.vaults.moveItemToVault(privateVault, note)
const sharedVault = await context.sharedVaults.convertVaultToSharedVault(privateVault)
const { thirdPartyContext, deinitThirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
await Collaboration.acceptAllInvites(thirdPartyContext)
const contextNote = thirdPartyContext.items.findItem(note.uuid)
expect(contextNote).to.not.be.undefined
expect(contextNote.title).to.equal('foo')
expect(contextNote.text).to.equal(note.text)
await deinitThirdPartyContext()
})
})