tests: vault tests (#2366)

This commit is contained in:
Mo
2023-07-25 07:40:28 -05:00
committed by GitHub
parent 80436cd0b9
commit 596e041c42
47 changed files with 479 additions and 289 deletions

View File

@@ -75,6 +75,7 @@ import {
VaultInviteServiceInterface,
UserEventServiceEvent,
VaultServiceEvent,
VaultLockServiceInterface,
} from '@standardnotes/services'
import {
PayloadEmitSource,
@@ -1324,18 +1325,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.dependencies.get<HomeServerServiceInterface | undefined>(TYPES.HomeServerService)
}
public get vaults(): VaultServiceInterface {
return this.dependencies.get<VaultServiceInterface>(TYPES.VaultService)
}
public get contacts(): ContactServiceInterface {
return this.dependencies.get<ContactServiceInterface>(TYPES.ContactService)
}
public get sharedVaults(): SharedVaultServiceInterface {
return this.dependencies.get<SharedVaultServiceInterface>(TYPES.SharedVaultService)
}
public get preferences(): PreferenceServiceInterface {
return this.dependencies.get<PreferenceServiceInterface>(TYPES.PreferencesService)
}
@@ -1352,6 +1341,14 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.dependencies.get<InternalEventBusInterface>(TYPES.InternalEventBus)
}
public get vaults(): VaultServiceInterface {
return this.dependencies.get<VaultServiceInterface>(TYPES.VaultService)
}
public get vaultLocks(): VaultLockServiceInterface {
return this.dependencies.get<VaultLockServiceInterface>(TYPES.VaultLockService)
}
public get vaultUsers(): VaultUserServiceInterface {
return this.dependencies.get<VaultUserServiceInterface>(TYPES.VaultUserService)
}
@@ -1360,6 +1357,14 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.dependencies.get<VaultInviteServiceInterface>(TYPES.VaultInviteService)
}
public get contacts(): ContactServiceInterface {
return this.dependencies.get<ContactServiceInterface>(TYPES.ContactService)
}
public get sharedVaults(): SharedVaultServiceInterface {
return this.dependencies.get<SharedVaultServiceInterface>(TYPES.SharedVaultService)
}
private get migrations(): MigrationService {
return this.dependencies.get<MigrationService>(TYPES.MigrationService)
}

View File

@@ -117,6 +117,7 @@ import {
GetOwnedSharedVaults,
ContactBelongsToVault,
DeleteContact,
VaultLockService,
} from '@standardnotes/services'
import { ItemManager } from '../../Services/Items/ItemManager'
import { PayloadManager } from '../../Services/Payloads/PayloadManager'
@@ -650,6 +651,7 @@ export class Dependencies {
return new VaultUserService(
this.get(TYPES.SessionManager),
this.get(TYPES.VaultService),
this.get(TYPES.VaultLockService),
this.get(TYPES.GetVaultUsers),
this.get(TYPES.RemoveVaultMember),
this.get(TYPES.IsVaultOwner),
@@ -725,13 +727,22 @@ export class Dependencies {
)
})
this.factory.set(TYPES.VaultLockService, () => {
return new VaultLockService(
this.get(TYPES.ItemManager),
this.get(TYPES.EncryptionService),
this.get(TYPES.KeySystemKeyManager),
this.get(TYPES.GetVaults),
this.get(TYPES.InternalEventBus),
)
})
this.factory.set(TYPES.VaultService, () => {
return new VaultService(
this.get(TYPES.SyncService),
this.get(TYPES.ItemManager),
this.get(TYPES.MutatorService),
this.get(TYPES.EncryptionService),
this.get(TYPES.KeySystemKeyManager),
this.get(TYPES.VaultLockService),
this.get(TYPES.AlertService),
this.get(TYPES.GetVault),
this.get(TYPES.GetVaults),

View File

@@ -62,6 +62,7 @@ export const TYPES = {
VaultUserService: Symbol.for('VaultUserService'),
VaultInviteService: Symbol.for('VaultInviteService'),
VaultUserCache: Symbol.for('VaultUserCache'),
VaultLockService: Symbol.for('VaultLockService'),
// Servers
RevisionServer: Symbol.for('RevisionServer'),

View File

@@ -11,6 +11,7 @@ export const VaultTests = {
'vaults/signatures.test.js',
'vaults/shared_vaults.test.js',
'vaults/invites.test.js',
'vaults/locking.test.js',
'vaults/items.test.js',
'vaults/conflicts.test.js',
'vaults/deletion.test.js',

View File

@@ -49,10 +49,6 @@ export class AppContext {
)
}
get vaults() {
return this.application.vaults
}
get sessions() {
return this.application.sessions
}
@@ -97,6 +93,14 @@ export class AppContext {
return this.application.sharedVaults
}
get vaults() {
return this.application.vaults
}
get vaultLocks() {
return this.application.vaultLocks
}
get vaultUsers() {
return this.application.vaultUsers
}

View File

@@ -82,6 +82,27 @@ export const createSharedVaultWithUnacceptedButTrustedInvite = async (
return { sharedVault, contact, contactContext, deinitContactContext, invite }
}
export const createSharedVaultAndInviteContact = async (
createInContext,
inviteContext,
inviteContact,
permissions = SharedVaultPermission.Write,
) => {
const sharedVault = await createSharedVault(createInContext)
await createInContext.vaultInvites.inviteContactToSharedVault(sharedVault, inviteContact, permissions)
const promise = inviteContext.awaitNextSyncSharedVaultFromScratchEvent()
await inviteContext.sync()
await acceptAllInvites(inviteContext)
await promise
return { sharedVault }
}
export const createSharedVaultWithUnacceptedAndUntrustedInvite = async (
context,
permissions = SharedVaultPermission.Write,
@@ -113,7 +134,6 @@ export const inviteNewPartyToSharedVault = async (context, sharedVault, permissi
export const createPrivateVault = async (context) => {
const privateVault = await context.vaults.createRandomizedVault({
name: 'My Private Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
return privateVault

View File

@@ -61,7 +61,7 @@
await loadTests(MainRegistry.VaultTests.files);
}
if (!MainRegistry.VaultTests.enabled.exclusive) {
if (!MainRegistry.VaultTests.enabled || !MainRegistry.VaultTests.enabled.exclusive) {
await loadTests(MainRegistry.BaseTests);
}

View File

@@ -153,6 +153,16 @@ describe('shared vault deletion', function () {
})
it('being removed from a shared vault should delete respective vault listing', async () => {
console.error('TODO: implement test')
const { sharedVault, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
await context.vaultUsers.removeUserFromSharedVault(sharedVault, contactContext.userUuid)
await contactContext.sync()
const vault = contactContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(vault).to.be.undefined
await deinitContactContext()
})
})

View File

@@ -200,10 +200,6 @@ describe('shared vault invites', function () {
await deinitContactContext()
})
it('when inviter keypair changes, recipient should still be able to trust and decrypt previous invite', async () => {
console.error('TODO: implement test')
})
it('should delete all inbound invites after changing user password', async () => {
/** Invites to user are encrypted with old keypair and are no longer decryptable */
const { contactContext, deinitContactContext } =

View File

@@ -117,6 +117,28 @@ describe('shared vault items', function () {
})
it('adding item to vault while belonging to other vault should move the item to new vault', async () => {
console.error('TODO: implement test')
const { note, sharedVault, contactContext, contact, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInviteAndNote(context)
const { sharedVault: otherSharedVault } = await Collaboration.createSharedVaultAndInviteContact(
context,
contactContext,
contact,
)
const updatedNote = await Collaboration.moveItemToVault(context, otherSharedVault, note)
expect(updatedNote.key_system_identifier).to.equal(otherSharedVault.systemIdentifier)
expect(updatedNote.shared_vault_uuid).to.equal(otherSharedVault.sharing.sharedVaultUuid)
await contactContext.sync()
const receivedNote = contactContext.items.findItem(note.uuid)
expect(receivedNote).to.not.be.undefined
expect(receivedNote.title).to.equal(note.title)
expect(receivedNote.key_system_identifier).to.equal(otherSharedVault.systemIdentifier)
expect(receivedNote.shared_vault_uuid).to.equal(otherSharedVault.sharing.sharedVaultUuid)
await deinitContactContext()
})
})

View File

@@ -229,36 +229,4 @@ describe('shared vault key rotation', function () {
await deinitContactContext()
})
it('should throw if attempting to change password of locked vault', async () => {
console.error('TODO: implement')
})
it('should respect storage preference when rotating key system root key', async () => {
console.error('TODO: implement')
})
it('should change storage preference from synced to local', async () => {
console.error('TODO: implement')
})
it('should change storage preference from local to synced', async () => {
console.error('TODO: implement')
})
it('should resync key system items key if it is encrypted with noncurrent key system root key', async () => {
console.error('TODO: implement')
})
it('should change password type from user inputted to randomized', async () => {
console.error('TODO: implement')
})
it('should change password type from randomized to user inputted', async () => {
console.error('TODO: implement')
})
it('should not be able to change storage mode of third party vault', async () => {
console.error('TODO: implement')
})
})

View File

@@ -0,0 +1,108 @@
import * as Factory from '../lib/factory.js'
import * as Collaboration from '../lib/Collaboration.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('vault locking', 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 lock non-persistent vault', async () => {
const vault = await context.vaults.createUserInputtedPasswordVault({
name: 'test vault',
description: 'test vault description',
userInputtedPassword: 'test password',
storagePreference: KeySystemRootKeyStorageMode.Ephemeral,
})
context.vaultLocks.lockNonPersistentVault(vault)
expect(context.vaultLocks.isVaultLocked(vault)).to.be.true
})
it('should not be able to lock user-inputted vault with synced key', async () => {
const vault = await context.vaults.createUserInputtedPasswordVault({
name: 'test vault',
description: 'test vault description',
userInputtedPassword: 'test password',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
expect(() => context.vaultLocks.lockNonPersistentVault(vault)).to.throw(
Error,
'Vault uses synced key storage and cannot be locked',
)
})
it('should not be able to lock randomized vault', async () => {
const vault = await context.vaults.createRandomizedVault({
name: 'test vault',
description: 'test vault description',
})
expect(() => context.vaultLocks.lockNonPersistentVault(vault)).to.throw(
Error,
'Vault uses synced key storage and cannot be locked',
)
})
it('should throw if attempting to change password of locked vault', async () => {
const vault = await context.vaults.createUserInputtedPasswordVault({
name: 'test vault',
description: 'test vault description',
userInputtedPassword: 'test password',
storagePreference: KeySystemRootKeyStorageMode.Ephemeral,
})
context.vaultLocks.lockNonPersistentVault(vault)
await Factory.expectThrowsAsync(
() => context.vaults.changeVaultOptions({ vault }),
'Attempting to change vault options on a locked vault',
)
})
it('should respect storage preference when rotating key system root key', async () => {
console.error('TODO: implement')
})
it('should change storage preference from synced to local', async () => {
console.error('TODO: implement')
})
it('should change storage preference from local to synced', async () => {
console.error('TODO: implement')
})
it('should resync key system items key if it is encrypted with noncurrent key system root key', async () => {
console.error('TODO: implement')
})
it('should change password type from user inputted to randomized', async () => {
console.error('TODO: implement')
})
it('should change password type from randomized to user inputted', async () => {
console.error('TODO: implement')
})
it('should not be able to change storage mode of third party vault', async () => {
console.error('TODO: implement')
})
})

View File

@@ -42,7 +42,6 @@ describe('vaults', function () {
it('should be able to create an offline vault', async () => {
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
expect(vault.systemIdentifier).to.not.be.undefined
@@ -59,7 +58,6 @@ describe('vaults', function () {
await context.application.addPasscode('123')
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
expect(vault.systemIdentifier).to.not.be.undefined
@@ -75,7 +73,6 @@ describe('vaults', function () {
it('should add item to offline vault', async () => {
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
const item = await context.createSyncedNote()
@@ -89,7 +86,6 @@ describe('vaults', function () {
const appIdentifier = context.identifier
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
const note = await context.createSyncedNote('foo', 'bar')
await vaults.moveItemToVault(vault, note)
@@ -110,7 +106,6 @@ describe('vaults', function () {
const appIdentifier = context.identifier
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
const note = await context.createSyncedNote('foo', 'bar')
await vaults.moveItemToVault(vault, note)
@@ -138,7 +133,6 @@ describe('vaults', function () {
const appIdentifier = context.identifier
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
const note = await context.createSyncedNote('foo', 'bar')
await vaults.moveItemToVault(vault, note)
@@ -168,7 +162,6 @@ describe('vaults', function () {
it('should create a vault', async () => {
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
expect(vault).to.not.be.undefined
@@ -184,7 +177,6 @@ describe('vaults', function () {
const note = await context.createSyncedNote('foo', 'bar')
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
await vaults.moveItemToVault(vault, note)
@@ -198,7 +190,6 @@ describe('vaults', function () {
const appIdentifier = context.identifier
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
const note = await context.createSyncedNote('foo', 'bar')
await vaults.moveItemToVault(vault, note)
@@ -219,7 +210,6 @@ describe('vaults', function () {
it('rotating a key system root key should create a new vault items key', async () => {
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
const keySystemItemsKey = context.keys.getKeySystemItemsKeys(vault.systemIdentifier)[0]
@@ -235,7 +225,6 @@ describe('vaults', function () {
it('deleting a vault should delete all its items', async () => {
const vault = await vaults.createRandomizedVault({
name: 'My Vault',
storagePreference: KeySystemRootKeyStorageMode.Synced,
})
const note = await context.createSyncedNote('foo', 'bar')
await vaults.moveItemToVault(vault, note)