diff --git a/packages/services/src/Domain/Application/ApplicationInterface.ts b/packages/services/src/Domain/Application/ApplicationInterface.ts index 62484c4db..38799ac5e 100644 --- a/packages/services/src/Domain/Application/ApplicationInterface.ts +++ b/packages/services/src/Domain/Application/ApplicationInterface.ts @@ -34,7 +34,7 @@ import { StorageValueModes } from '../Storage/StorageTypes' import { DeinitMode } from './DeinitMode' import { DeinitSource } from './DeinitSource' -import { UserClientInterface } from '../User/UserClientInterface' +import { UserServiceInterface } from '../User/UserServiceInterface' import { SessionsClientInterface } from '../Session/SessionsClientInterface' import { HomeServerServiceInterface } from '../HomeServer/HomeServerServiceInterface' import { User } from '@standardnotes/responses' @@ -113,7 +113,7 @@ export interface ApplicationInterface { get preferences(): PreferenceServiceInterface get sessions(): SessionsClientInterface get subscriptions(): SubscriptionManagerInterface - get user(): UserClientInterface + get user(): UserServiceInterface get vaults(): VaultServiceInterface get vaultLocks(): VaultLockServiceInterface get vaultUsers(): VaultUserServiceInterface diff --git a/packages/services/src/Domain/AsymmetricMessage/AsymmetricMessageService.spec.ts b/packages/services/src/Domain/AsymmetricMessage/AsymmetricMessageService.spec.ts index 398c57eca..22e484736 100644 --- a/packages/services/src/Domain/AsymmetricMessage/AsymmetricMessageService.spec.ts +++ b/packages/services/src/Domain/AsymmetricMessage/AsymmetricMessageService.spec.ts @@ -1,3 +1,4 @@ +import { GetKeyPairs } from './../Encryption/UseCase/GetKeyPairs' import { GetVault } from './../Vault/UseCase/GetVault' import { SessionsClientInterface } from './../Session/SessionsClientInterface' import { EncryptionProviderInterface } from './../Encryption/EncryptionProviderInterface' @@ -48,6 +49,7 @@ describe('AsymmetricMessageService', () => { const getOutboundMessagesUseCase = {} as jest.Mocked const getInboundMessagesUseCase = {} as jest.Mocked const getUntrustedPayload = {} as jest.Mocked + const getKeyPairs = {} as jest.Mocked sync = {} as jest.Mocked sync.sync = jest.fn() @@ -73,6 +75,7 @@ describe('AsymmetricMessageService', () => { getOutboundMessagesUseCase, getInboundMessagesUseCase, getUntrustedPayload, + getKeyPairs, eventBus, ) }) diff --git a/packages/services/src/Domain/AsymmetricMessage/AsymmetricMessageService.ts b/packages/services/src/Domain/AsymmetricMessage/AsymmetricMessageService.ts index ede56a369..bb55da5af 100644 --- a/packages/services/src/Domain/AsymmetricMessage/AsymmetricMessageService.ts +++ b/packages/services/src/Domain/AsymmetricMessage/AsymmetricMessageService.ts @@ -1,3 +1,4 @@ +import { GetKeyPairs } from './../Encryption/UseCase/GetKeyPairs' import { SyncServiceInterface } from './../Sync/SyncServiceInterface' import { SessionsClientInterface } from './../Session/SessionsClientInterface' import { MutatorClientInterface } from './../Mutator/MutatorClientInterface' @@ -54,6 +55,7 @@ export class AsymmetricMessageService private _getOutboundMessagesUseCase: GetOutboundMessages, private _getInboundMessagesUseCase: GetInboundMessages, private _getUntrustedPayload: GetUntrustedPayload, + private _getKeyPairs: GetKeyPairs, eventBus: InternalEventBusInterface, ) { super(eventBus) @@ -196,8 +198,13 @@ export class AsymmetricMessageService } getUntrustedMessagePayload(message: AsymmetricMessageServerHash): Result { + const keys = this._getKeyPairs.execute() + if (keys.isFailed()) { + return Result.fail(keys.getError()) + } + const result = this._getUntrustedPayload.execute({ - privateKey: this.encryption.getKeyPair().privateKey, + privateKey: keys.getValue().encryption.privateKey, message, }) @@ -214,8 +221,13 @@ export class AsymmetricMessageService return Result.fail(contact.getError()) } + const keys = this._getKeyPairs.execute() + if (keys.isFailed()) { + return Result.fail(keys.getError()) + } + const result = this._getTrustedPayload.execute({ - privateKey: this.encryption.getKeyPair().privateKey, + privateKey: keys.getValue().encryption.privateKey, sender: contact.getValue(), ownUserUuid: this.sessions.userUuid, message, diff --git a/packages/services/src/Domain/AsymmetricMessage/UseCase/HandleRootKeyChangedMessage.ts b/packages/services/src/Domain/AsymmetricMessage/UseCase/HandleRootKeyChangedMessage.ts index 48b8c5d7e..468fbb8ab 100644 --- a/packages/services/src/Domain/AsymmetricMessage/UseCase/HandleRootKeyChangedMessage.ts +++ b/packages/services/src/Domain/AsymmetricMessage/UseCase/HandleRootKeyChangedMessage.ts @@ -11,14 +11,14 @@ import { import { ContentType } from '@standardnotes/domain-core' import { GetVault } from '../../Vault/UseCase/GetVault' -import { EncryptionProviderInterface } from '../../Encryption/EncryptionProviderInterface' +import { DecryptErroredPayloads } from '../../Encryption/UseCase/DecryptErroredPayloads' export class HandleRootKeyChangedMessage { constructor( private mutator: MutatorClientInterface, private sync: SyncServiceInterface, - private encryption: EncryptionProviderInterface, - private getVault: GetVault, + private _getVault: GetVault, + private _decryptErroredPayloads: DecryptErroredPayloads, ) {} async execute(message: AsymmetricMessageSharedVaultRootKeyChanged): Promise { @@ -30,14 +30,16 @@ export class HandleRootKeyChangedMessage { true, ) - const vault = this.getVault.execute({ keySystemIdentifier: rootKeyContent.systemIdentifier }) + const vault = this._getVault.execute({ + keySystemIdentifier: rootKeyContent.systemIdentifier, + }) if (!vault.isFailed()) { await this.mutator.changeItem(vault.getValue(), (mutator) => { mutator.rootKeyParams = rootKeyContent.keyParams }) } - await this.encryption.decryptErroredPayloads() + await this._decryptErroredPayloads.execute() void this.sync.sync({ sourceDescription: 'Not awaiting due to this event handler running from sync response' }) } diff --git a/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.ts b/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.ts index 7eb80e9f5..b3359f20c 100644 --- a/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.ts +++ b/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.ts @@ -16,13 +16,13 @@ export class ProcessAcceptedVaultInvite { constructor( private mutator: MutatorClientInterface, private sync: SyncServiceInterface, - private createOrEditContact: CreateOrEditContact, + private _createOrEditContact: CreateOrEditContact, ) {} async execute( message: AsymmetricMessageSharedVaultInvite, sharedVaultUuid: string, - senderUuid: string, + ownerUuid: string, ): Promise { const { rootKey: rootKeyContent, trustedContacts, metadata } = message.data @@ -34,7 +34,7 @@ export class ProcessAcceptedVaultInvite { description: metadata.description, sharing: { sharedVaultUuid: sharedVaultUuid, - ownerUserUuid: senderUuid, + ownerUserUuid: ownerUuid, }, } @@ -47,7 +47,7 @@ export class ProcessAcceptedVaultInvite { await this.mutator.createItem(ContentType.TYPES.VaultListing, FillItemContentSpecialized(content), true) for (const contact of trustedContacts) { - await this.createOrEditContact.execute({ + await this._createOrEditContact.execute({ name: contact.name, contactUuid: contact.contactUuid, publicKey: contact.publicKeySet.encryption, diff --git a/packages/services/src/Domain/Contacts/ContactService.ts b/packages/services/src/Domain/Contacts/ContactService.ts index bf21e14f5..961f5b31b 100644 --- a/packages/services/src/Domain/Contacts/ContactService.ts +++ b/packages/services/src/Domain/Contacts/ContactService.ts @@ -8,7 +8,7 @@ import { SyncServiceInterface } from '../Sync/SyncServiceInterface' import { SessionsClientInterface } from '../Session/SessionsClientInterface' import { ContactServiceEvent, ContactServiceInterface } from '../Contacts/ContactServiceInterface' import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface' -import { UserClientInterface } from '../User/UserClientInterface' +import { UserServiceInterface } from '../User/UserServiceInterface' import { CollaborationIDData, Version1CollaborationId } from './CollaborationID' import { ValidateItemSigner } from './UseCase/ValidateItemSigner' import { ItemSignatureValidationResult } from './UseCase/Types/ItemSignatureValidationResult' @@ -26,7 +26,7 @@ export class ContactService extends AbstractService impleme private mutator: MutatorClientInterface, private session: SessionsClientInterface, private crypto: PureCryptoInterface, - private user: UserClientInterface, + private user: UserServiceInterface, private selfContactManager: SelfContactManager, private encryption: EncryptionProviderInterface, private _deleteContact: DeleteContact, diff --git a/packages/services/src/Domain/Contacts/UseCase/DeleteContact.ts b/packages/services/src/Domain/Contacts/UseCase/DeleteContact.ts index 2b4f8a6c5..49303e657 100644 --- a/packages/services/src/Domain/Contacts/UseCase/DeleteContact.ts +++ b/packages/services/src/Domain/Contacts/UseCase/DeleteContact.ts @@ -18,7 +18,7 @@ export class DeleteContact implements UseCaseInterface { throw new Error('Cannot delete self') } - const vaults = this.getOwnedVaults.execute({ userUuid: dto.ownUserUuid }) + const vaults = this.getOwnedVaults.execute() if (vaults.isFailed()) { return Result.fail('Failed to get owned vaults') } diff --git a/packages/services/src/Domain/Encryption/EncryptionProviderInterface.ts b/packages/services/src/Domain/Encryption/EncryptionProviderInterface.ts index befeae1ce..fc9292a1e 100644 --- a/packages/services/src/Domain/Encryption/EncryptionProviderInterface.ts +++ b/packages/services/src/Domain/Encryption/EncryptionProviderInterface.ts @@ -20,7 +20,6 @@ import { KeySystemRootKeyParamsInterface, PortablePublicKeySet, } from '@standardnotes/models' -import { PkcKeyPair } from '@standardnotes/sncrypto-common' export interface EncryptionProviderInterface { initialize(): Promise @@ -72,7 +71,6 @@ export interface EncryptionProviderInterface { } > - decryptErroredPayloads(): Promise deleteWorkspaceSpecificKeyStateFromDevice(): Promise unwrapRootKey(wrappingKey: RootKeyInterface): Promise @@ -110,9 +108,6 @@ export interface EncryptionProviderInterface { rootKeyToken: string, ): KeySystemItemsKeyInterface - getKeyPair(): PkcKeyPair - getSigningKeyPair(): PkcKeyPair - asymmetricSignatureVerifyDetached( encryptedString: AsymmetricallyEncryptedString, ): AsymmetricSignatureVerificationDetachedResult diff --git a/packages/services/src/Domain/Encryption/EncryptionService.ts b/packages/services/src/Domain/Encryption/EncryptionService.ts index 1d46594c3..3afa0cf43 100644 --- a/packages/services/src/Domain/Encryption/EncryptionService.ts +++ b/packages/services/src/Domain/Encryption/EncryptionService.ts @@ -1,3 +1,4 @@ +import { GetKeyPairs } from './UseCase/GetKeyPairs' import { FindDefaultItemsKey } from './UseCase/ItemsKey/FindDefaultItemsKey' import { InternalEventInterface } from './../Internal/InternalEventInterface' import { InternalEventHandlerInterface } from './../Internal/InternalEventHandlerInterface' @@ -43,7 +44,7 @@ import { PortablePublicKeySet, RootKeyParamsInterface, } from '@standardnotes/models' -import { PkcKeyPair, PureCryptoInterface } from '@standardnotes/sncrypto-common' +import { PureCryptoInterface } from '@standardnotes/sncrypto-common' import { extendArray, isNotUndefined, @@ -73,7 +74,6 @@ import { DecryptedParameters } from '@standardnotes/encryption/src/Domain/Types/ import { RootKeyManager } from '../RootKeyManager/RootKeyManager' import { RootKeyManagerEvent } from '../RootKeyManager/RootKeyManagerEvent' import { CreateNewItemsKeyWithRollback } from './UseCase/ItemsKey/CreateNewItemsKeyWithRollback' -import { DecryptErroredTypeAPayloads } from './UseCase/TypeA/DecryptErroredPayloads' import { CreateNewDefaultItemsKey } from './UseCase/ItemsKey/CreateNewDefaultItemsKey' import { DecryptTypeAPayload } from './UseCase/TypeA/DecryptPayload' import { DecryptTypeAPayloadWithKeyLookup } from './UseCase/TypeA/DecryptPayloadWithKeyLookup' @@ -126,12 +126,12 @@ export class EncryptionService private crypto: PureCryptoInterface, private _createNewItemsKeyWithRollback: CreateNewItemsKeyWithRollback, private _findDefaultItemsKey: FindDefaultItemsKey, - private _decryptErroredRootPayloads: DecryptErroredTypeAPayloads, private _rootKeyEncryptPayloadWithKeyLookup: EncryptTypeAPayloadWithKeyLookup, private _rootKeyEncryptPayload: EncryptTypeAPayload, private _rootKeyDecryptPayload: DecryptTypeAPayload, private _rootKeyDecryptPayloadWithKeyLookup: DecryptTypeAPayloadWithKeyLookup, private _createDefaultItemsKey: CreateNewDefaultItemsKey, + private _getKeyPairs: GetKeyPairs, protected override internalEventBus: InternalEventBusInterface, ) { super(internalEventBus) @@ -157,7 +157,6 @@ export class EncryptionService ;(this.crypto as unknown) = undefined ;(this._createNewItemsKeyWithRollback as unknown) = undefined ;(this._findDefaultItemsKey as unknown) = undefined - ;(this._decryptErroredRootPayloads as unknown) = undefined ;(this._rootKeyEncryptPayloadWithKeyLookup as unknown) = undefined ;(this._rootKeyEncryptPayload as unknown) = undefined ;(this._rootKeyDecryptPayload as unknown) = undefined @@ -167,28 +166,6 @@ export class EncryptionService super.deinit() } - /** @throws */ - getKeyPair(): PkcKeyPair { - const rootKey = this.getRootKey() - - if (!rootKey?.encryptionKeyPair) { - throw new Error('Account keypair not found') - } - - return rootKey.encryptionKeyPair - } - - /** @throws */ - getSigningKeyPair(): PkcKeyPair { - const rootKey = this.getRootKey() - - if (!rootKey?.signingKeyPair) { - throw new Error('Account keypair not found') - } - - return rootKey.signingKeyPair - } - hasSigningKeyPair(): boolean { return !!this.getRootKey()?.signingKeyPair } @@ -244,12 +221,6 @@ export class EncryptionService return this._createNewItemsKeyWithRollback.execute() } - public async decryptErroredPayloads(): Promise { - await this._decryptErroredRootPayloads.execute() - - await this.itemsEncryption.decryptErroredItemPayloads() - } - public itemsKeyForEncryptedPayload( payload: EncryptedPayloadInterface, ): ItemsKeyInterface | KeySystemItemsKeyInterface | undefined { @@ -279,7 +250,9 @@ export class EncryptionService usesKeySystemRootKeyWithKeyLookup, } = split - const signingKeyPair = this.hasSigningKeyPair() ? this.getSigningKeyPair() : undefined + const keys = this._getKeyPairs.execute() + + const signingKeyPair = keys.isFailed() ? undefined : keys.getValue().signing if (usesRootKey) { const rootKeyEncrypted = await this._rootKeyEncryptPayload.executeMany( diff --git a/packages/services/src/Domain/Encryption/UseCase/DecryptErroredPayloads.ts b/packages/services/src/Domain/Encryption/UseCase/DecryptErroredPayloads.ts new file mode 100644 index 000000000..b3b879ad7 --- /dev/null +++ b/packages/services/src/Domain/Encryption/UseCase/DecryptErroredPayloads.ts @@ -0,0 +1,18 @@ +import { DecryptErroredTypeAPayloads } from './TypeA/DecryptErroredPayloads' +import { ItemsEncryptionService } from './../../ItemsEncryption/ItemsEncryption' +import { Result, UseCaseInterface } from '@standardnotes/domain-core' + +export class DecryptErroredPayloads implements UseCaseInterface { + constructor( + private itemsEncryption: ItemsEncryptionService, + private _decryptErroredRootPayloads: DecryptErroredTypeAPayloads, + ) {} + + async execute(): Promise> { + await this._decryptErroredRootPayloads.execute() + + await this.itemsEncryption.decryptErroredItemPayloads() + + return Result.ok() + } +} diff --git a/packages/services/src/Domain/Encryption/UseCase/GetKeyPairs.ts b/packages/services/src/Domain/Encryption/UseCase/GetKeyPairs.ts new file mode 100644 index 000000000..693d18f76 --- /dev/null +++ b/packages/services/src/Domain/Encryption/UseCase/GetKeyPairs.ts @@ -0,0 +1,25 @@ +import { Result, SyncUseCaseInterface } from '@standardnotes/domain-core' +import { PkcKeyPair } from '@standardnotes/sncrypto-common' +import { RootKeyManager } from '../../RootKeyManager/RootKeyManager' + +type UsecaseResult = { + encryption: PkcKeyPair + signing: PkcKeyPair +} + +export class GetKeyPairs implements SyncUseCaseInterface { + constructor(private rootKeyManager: RootKeyManager) {} + + execute(): Result { + const rootKey = this.rootKeyManager.getRootKey() + + if (!rootKey?.encryptionKeyPair || !rootKey?.signingKeyPair) { + return Result.fail('Account keypair not found') + } + + return Result.ok({ + encryption: rootKey.encryptionKeyPair, + signing: rootKey.signingKeyPair, + }) + } +} diff --git a/packages/services/src/Domain/SharedVaults/SharedVaultService.spec.ts b/packages/services/src/Domain/SharedVaults/SharedVaultService.spec.ts index ea847f8f3..1d02300d0 100644 --- a/packages/services/src/Domain/SharedVaults/SharedVaultService.spec.ts +++ b/packages/services/src/Domain/SharedVaults/SharedVaultService.spec.ts @@ -1,15 +1,11 @@ import { DiscardItemsLocally } from './../UseCase/DiscardItemsLocally' import { InternalEventBusInterface } from './../Internal/InternalEventBusInterface' import { GetOwnedSharedVaults } from './UseCase/GetOwnedSharedVaults' -import { IsVaultOwner } from './../VaultUser/UseCase/IsVaultOwner' -import { EncryptionProviderInterface } from './../Encryption/EncryptionProviderInterface' import { DeleteSharedVault } from './UseCase/DeleteSharedVault' import { ConvertToSharedVault } from './UseCase/ConvertToSharedVault' import { ShareContactWithVault } from './UseCase/ShareContactWithVault' import { DeleteThirdPartyVault } from './UseCase/DeleteExternalSharedVault' import { FindContact } from './../Contacts/UseCase/FindContact' -import { SendVaultDataChangedMessage } from './UseCase/SendVaultDataChangedMessage' -import { NotifyVaultUsersOfKeyRotation } from './UseCase/NotifyVaultUsersOfKeyRotation' import { HandleKeyPairChange } from './../Contacts/UseCase/HandleKeyPairChange' import { CreateSharedVault } from './UseCase/CreateSharedVault' import { GetVault } from './../Vault/UseCase/GetVault' @@ -29,20 +25,16 @@ describe('SharedVaultService', () => { const items = {} as jest.Mocked items.addObserver = jest.fn() - const encryption = {} as jest.Mocked const session = {} as jest.Mocked const getVault = {} as jest.Mocked const getOwnedVaults = {} as jest.Mocked const createSharedVaultUseCase = {} as jest.Mocked const handleKeyPairChange = {} as jest.Mocked - const notifyVaultUsersOfKeyRotation = {} as jest.Mocked - const sendVaultDataChangeMessage = {} as jest.Mocked const findContact = {} as jest.Mocked const deleteThirdPartyVault = {} as jest.Mocked const shareContactWithVault = {} as jest.Mocked const convertToSharedVault = {} as jest.Mocked const deleteSharedVaultUseCase = {} as jest.Mocked - const isVaultAdmin = {} as jest.Mocked const discardItemsLocally = {} as jest.Mocked const eventBus = {} as jest.Mocked @@ -50,20 +42,16 @@ describe('SharedVaultService', () => { service = new SharedVaultService( items, - encryption, session, getVault, getOwnedVaults, createSharedVaultUseCase, handleKeyPairChange, - notifyVaultUsersOfKeyRotation, - sendVaultDataChangeMessage, findContact, deleteThirdPartyVault, shareContactWithVault, convertToSharedVault, deleteSharedVaultUseCase, - isVaultAdmin, discardItemsLocally, eventBus, ) diff --git a/packages/services/src/Domain/SharedVaults/SharedVaultService.ts b/packages/services/src/Domain/SharedVaults/SharedVaultService.ts index 035f53026..80ef5e968 100644 --- a/packages/services/src/Domain/SharedVaults/SharedVaultService.ts +++ b/packages/services/src/Domain/SharedVaults/SharedVaultService.ts @@ -22,18 +22,13 @@ import { InternalEventInterface } from '../Internal/InternalEventInterface' import { NotificationServiceEvent, NotificationServiceEventPayload } from '../UserEvent/NotificationServiceEvent' import { DeleteThirdPartyVault } from './UseCase/DeleteExternalSharedVault' import { DeleteSharedVault } from './UseCase/DeleteSharedVault' -import { VaultServiceEvent, VaultServiceEventPayload } from '../Vault/VaultServiceEvent' import { ShareContactWithVault } from './UseCase/ShareContactWithVault' -import { NotifyVaultUsersOfKeyRotation } from './UseCase/NotifyVaultUsersOfKeyRotation' import { CreateSharedVault } from './UseCase/CreateSharedVault' -import { SendVaultDataChangedMessage } from './UseCase/SendVaultDataChangedMessage' import { ConvertToSharedVault } from './UseCase/ConvertToSharedVault' import { GetVault } from '../Vault/UseCase/GetVault' import { ContentType, NotificationType, Uuid } from '@standardnotes/domain-core' import { HandleKeyPairChange } from '../Contacts/UseCase/HandleKeyPairChange' import { FindContact } from '../Contacts/UseCase/FindContact' -import { EncryptionProviderInterface } from '../Encryption/EncryptionProviderInterface' -import { IsVaultOwner } from '../VaultUser/UseCase/IsVaultOwner' import { GetOwnedSharedVaults } from './UseCase/GetOwnedSharedVaults' export class SharedVaultService @@ -42,20 +37,16 @@ export class SharedVaultService { constructor( private items: ItemManagerInterface, - private encryption: EncryptionProviderInterface, private session: SessionsClientInterface, private _getVault: GetVault, private _getOwnedSharedVaults: GetOwnedSharedVaults, private _createSharedVault: CreateSharedVault, private _handleKeyPairChange: HandleKeyPairChange, - private _notifyVaultUsersOfKeyRotation: NotifyVaultUsersOfKeyRotation, - private _sendVaultDataChangeMessage: SendVaultDataChangedMessage, private _findContact: FindContact, private _deleteThirdPartyVault: DeleteThirdPartyVault, private _shareContactWithVault: ShareContactWithVault, private _convertToSharedVault: ConvertToSharedVault, private _deleteSharedVault: DeleteSharedVault, - private _isVaultAdmin: IsVaultOwner, private _discardItemsLocally: DiscardItemsLocally, eventBus: InternalEventBusInterface, ) { @@ -68,32 +59,20 @@ export class SharedVaultService } }), ) - - this.eventDisposers.push( - items.addObserver(ContentType.TYPES.VaultListing, ({ changed, source }) => { - if (source === PayloadEmitSource.LocalChanged && changed.length > 0) { - void this.handleVaultListingsChange(changed) - } - }), - ) } override deinit(): void { super.deinit() ;(this.items as unknown) = undefined - ;(this.encryption as unknown) = undefined ;(this.session as unknown) = undefined ;(this._getVault as unknown) = undefined ;(this._createSharedVault as unknown) = undefined ;(this._handleKeyPairChange as unknown) = undefined - ;(this._notifyVaultUsersOfKeyRotation as unknown) = undefined - ;(this._sendVaultDataChangeMessage as unknown) = undefined ;(this._findContact as unknown) = undefined ;(this._deleteThirdPartyVault as unknown) = undefined ;(this._shareContactWithVault as unknown) = undefined ;(this._convertToSharedVault as unknown) = undefined ;(this._deleteSharedVault as unknown) = undefined - ;(this._isVaultAdmin as unknown) = undefined } async handleEvent(event: InternalEventInterface): Promise { @@ -109,11 +88,6 @@ export class SharedVaultService case NotificationServiceEvent.NotificationReceived: await this.handleUserEvent(event.payload as NotificationServiceEventPayload) break - case VaultServiceEvent.VaultRootKeyRotated: { - const payload = event.payload as VaultServiceEventPayload[VaultServiceEvent.VaultRootKeyRotated] - await this.handleVaultRootKeyRotatedEvent(payload.vault) - break - } case SyncEvent.ReceivedRemoteSharedVaults: void this.notifyEventSync(SharedVaultServiceEvent.SharedVaultStatusChanged) break @@ -141,33 +115,6 @@ export class SharedVaultService } } - private isCurrentUserVaultOwner(sharedVault: SharedVaultListingInterface): boolean { - if (!sharedVault.sharing.ownerUserUuid) { - throw new Error(`Shared vault ${sharedVault.sharing.sharedVaultUuid} does not have an owner user uuid`) - } - - return sharedVault.sharing.ownerUserUuid === this.session.userUuid - } - - private async handleVaultRootKeyRotatedEvent(vault: VaultListingInterface): Promise { - if (!vault.isSharedVaultListing()) { - return - } - - if (!this.isCurrentUserVaultOwner(vault)) { - return - } - - await this._notifyVaultUsersOfKeyRotation.execute({ - sharedVault: vault, - senderUuid: this.session.getSureUser().uuid, - keys: { - encryption: this.encryption.getKeyPair(), - signing: this.encryption.getSigningKeyPair(), - }, - }) - } - async createSharedVault(dto: { name: string description?: string @@ -198,23 +145,6 @@ export class SharedVaultService } } - private async handleVaultListingsChange(vaults: VaultListingInterface[]): Promise { - for (const vault of vaults) { - if (!vault.isSharedVaultListing()) { - continue - } - - await this._sendVaultDataChangeMessage.execute({ - vault, - senderUuid: this.session.getSureUser().uuid, - keys: { - encryption: this.encryption.getKeyPair(), - signing: this.encryption.getSigningKeyPair(), - }, - }) - } - } - public async deleteSharedVault(sharedVault: SharedVaultListingInterface): Promise { return this._deleteSharedVault.execute({ sharedVault }) } @@ -224,17 +154,12 @@ export class SharedVaultService throw new Error('Cannot share self contact') } - const ownedVaults = this._getOwnedSharedVaults.execute({ userUuid: this.session.userUuid }).getValue() + const ownedVaults = this._getOwnedSharedVaults.execute().getValue() for (const vault of ownedVaults) { await this._shareContactWithVault.execute({ - keys: { - encryption: this.encryption.getKeyPair(), - signing: this.encryption.getSigningKeyPair(), - }, sharedVault: vault, contactToShare: contact, - senderUserUuid: this.session.getSureUser().uuid, }) } } diff --git a/packages/services/src/Domain/SharedVaults/UseCase/GetOwnedSharedVaults.ts b/packages/services/src/Domain/SharedVaults/UseCase/GetOwnedSharedVaults.ts index 79384d01f..7f77c6d02 100644 --- a/packages/services/src/Domain/SharedVaults/UseCase/GetOwnedSharedVaults.ts +++ b/packages/services/src/Domain/SharedVaults/UseCase/GetOwnedSharedVaults.ts @@ -5,18 +5,17 @@ import { GetSharedVaults } from './GetSharedVaults' export class GetOwnedSharedVaults implements SyncUseCaseInterface { constructor( - private getSharedVaults: GetSharedVaults, - private isVaultOwnwer: IsVaultOwner, + private _getSharedVaults: GetSharedVaults, + private _isVaultOwnwer: IsVaultOwner, ) {} - execute(dto: { userUuid: string }): Result { - const sharedVaults = this.getSharedVaults.execute().getValue() + execute(): Result { + const sharedVaults = this._getSharedVaults.execute().getValue() const ownedVaults = sharedVaults.filter((vault) => { - return this.isVaultOwnwer + return this._isVaultOwnwer .execute({ sharedVault: vault, - userUuid: dto.userUuid, }) .getValue() }) diff --git a/packages/services/src/Domain/SharedVaults/UseCase/NotifyVaultUsersOfKeyRotation.ts b/packages/services/src/Domain/SharedVaults/UseCase/NotifyVaultUsersOfKeyRotation.ts index 488cd13bb..6c716dfa5 100644 --- a/packages/services/src/Domain/SharedVaults/UseCase/NotifyVaultUsersOfKeyRotation.ts +++ b/packages/services/src/Domain/SharedVaults/UseCase/NotifyVaultUsersOfKeyRotation.ts @@ -2,30 +2,26 @@ import { SharedVaultInvitesServerInterface } from '@standardnotes/api' import { AsymmetricMessageSharedVaultInvite, SharedVaultListingInterface } from '@standardnotes/models' import { SharedVaultInviteServerHash, isErrorResponse } from '@standardnotes/responses' import { SendVaultKeyChangedMessage } from './SendVaultKeyChangedMessage' -import { PkcKeyPair } from '@standardnotes/sncrypto-common' import { Result, UseCaseInterface } from '@standardnotes/domain-core' import { InviteToVault } from '../../VaultInvite/UseCase/InviteToVault' import { GetVaultContacts } from '../../VaultUser/UseCase/GetVaultContacts' import { DecryptOwnMessage } from '../../Encryption/UseCase/Asymmetric/DecryptOwnMessage' import { FindContact } from '../../Contacts/UseCase/FindContact' +import { GetKeyPairs } from '../../Encryption/UseCase/GetKeyPairs' type Params = { - keys: { - encryption: PkcKeyPair - signing: PkcKeyPair - } sharedVault: SharedVaultListingInterface - senderUuid: string } export class NotifyVaultUsersOfKeyRotation implements UseCaseInterface { constructor( - private findContact: FindContact, - private sendKeyChangedMessage: SendVaultKeyChangedMessage, - private inviteToVault: InviteToVault, - private inviteServer: SharedVaultInvitesServerInterface, - private getVaultContacts: GetVaultContacts, - private decryptOwnMessage: DecryptOwnMessage, + private _findContact: FindContact, + private _sendKeyChangedMessage: SendVaultKeyChangedMessage, + private _inviteToVault: InviteToVault, + private _inviteServer: SharedVaultInvitesServerInterface, + private _getVaultContacts: GetVaultContacts, + private _decryptOwnMessage: DecryptOwnMessage, + private _getKeyPairs: GetKeyPairs, ) {} async execute(params: Params): Promise> { @@ -44,20 +40,25 @@ export class NotifyVaultUsersOfKeyRotation implements UseCaseInterface { await this.deleteAllInvites(params.sharedVault.sharing.sharedVaultUuid) - const contacts = await this.getVaultContacts.execute({ + const contacts = await this._getVaultContacts.execute({ sharedVaultUuid: params.sharedVault.sharing.sharedVaultUuid, readFromCache: false, }) + const keys = this._getKeyPairs.execute() + if (keys.isFailed()) { + return Result.fail('Cannot send metadata changed message; keys not found') + } + for (const invite of existingInvites.getValue()) { - const recipient = this.findContact.execute({ userUuid: invite.user_uuid }) + const recipient = this._findContact.execute({ userUuid: invite.user_uuid }) if (recipient.isFailed()) { continue } - const decryptedPreviousInvite = this.decryptOwnMessage.execute({ + const decryptedPreviousInvite = this._decryptOwnMessage.execute({ message: invite.encrypted_message, - privateKey: params.keys.encryption.privateKey, + privateKey: keys.getValue().encryption.privateKey, recipientPublicKey: recipient.getValue().publicKeySet.encryption, }) @@ -65,13 +66,11 @@ export class NotifyVaultUsersOfKeyRotation implements UseCaseInterface { return Result.fail(decryptedPreviousInvite.getError()) } - await this.inviteToVault.execute({ - keys: params.keys, + await this._inviteToVault.execute({ sharedVault: params.sharedVault, sharedVaultContacts: !contacts.isFailed() ? contacts.getValue() : [], recipient: recipient.getValue(), permission: invite.permission, - senderUuid: params.senderUuid, }) } @@ -79,11 +78,9 @@ export class NotifyVaultUsersOfKeyRotation implements UseCaseInterface { } private async performSendKeyChangeMessage(params: Params): Promise> { - const result = await this.sendKeyChangedMessage.execute({ + const result = await this._sendKeyChangedMessage.execute({ keySystemIdentifier: params.sharedVault.systemIdentifier, sharedVaultUuid: params.sharedVault.sharing.sharedVaultUuid, - senderUuid: params.senderUuid, - keys: params.keys, }) if (result.isFailed()) { @@ -94,7 +91,7 @@ export class NotifyVaultUsersOfKeyRotation implements UseCaseInterface { } private async deleteAllInvites(sharedVaultUuid: string): Promise> { - const response = await this.inviteServer.deleteAllSharedVaultInvites({ + const response = await this._inviteServer.deleteAllSharedVaultInvites({ sharedVaultUuid: sharedVaultUuid, }) @@ -106,7 +103,7 @@ export class NotifyVaultUsersOfKeyRotation implements UseCaseInterface { } private async getExistingInvites(sharedVaultUuid: string): Promise> { - const response = await this.inviteServer.getOutboundUserInvites() + const response = await this._inviteServer.getOutboundUserInvites() if (isErrorResponse(response)) { return Result.fail(`Failed to get outbound user invites ${JSON.stringify(response)}`) diff --git a/packages/services/src/Domain/SharedVaults/UseCase/SendVaultDataChangedMessage.ts b/packages/services/src/Domain/SharedVaults/UseCase/SendVaultDataChangedMessage.ts index 7b07c826e..bfd6b6b59 100644 --- a/packages/services/src/Domain/SharedVaults/UseCase/SendVaultDataChangedMessage.ts +++ b/packages/services/src/Domain/SharedVaults/UseCase/SendVaultDataChangedMessage.ts @@ -1,3 +1,5 @@ +import { UserServiceInterface } from './../../User/UserServiceInterface' +import { IsVaultOwner } from './../../VaultUser/UseCase/IsVaultOwner' import { AsymmetricMessagePayloadType, AsymmetricMessageSharedVaultMetadataChanged, @@ -12,24 +14,26 @@ import { EncryptMessage } from '../../Encryption/UseCase/Asymmetric/EncryptMessa import { Result, UseCaseInterface } from '@standardnotes/domain-core' import { GetReplaceabilityIdentifier } from '../../AsymmetricMessage/UseCase/GetReplaceabilityIdentifier' import { FindContact } from '../../Contacts/UseCase/FindContact' +import { GetKeyPairs } from '../../Encryption/UseCase/GetKeyPairs' export class SendVaultDataChangedMessage implements UseCaseInterface { constructor( - private encryptMessage: EncryptMessage, - private findContact: FindContact, - private getVaultUsers: GetVaultUsers, - private sendMessage: SendMessage, + private users: UserServiceInterface, + private _encryptMessage: EncryptMessage, + private _findContact: FindContact, + private _getVaultUsers: GetVaultUsers, + private _sendMessage: SendMessage, + private _isVaultOwner: IsVaultOwner, + private _getKeyPairs: GetKeyPairs, ) {} - async execute(params: { - vault: SharedVaultListingInterface - senderUuid: string - keys: { - encryption: PkcKeyPair - signing: PkcKeyPair + async execute(params: { vault: SharedVaultListingInterface }): Promise> { + const isOwner = this._isVaultOwner.execute({ sharedVault: params.vault }).getValue() + if (!isOwner) { + return Result.ok() } - }): Promise> { - const users = await this.getVaultUsers.execute({ + + const users = await this._getVaultUsers.execute({ sharedVaultUuid: params.vault.sharing.sharedVaultUuid, readFromCache: false, }) @@ -37,20 +41,25 @@ export class SendVaultDataChangedMessage implements UseCaseInterface { return Result.fail('Cannot send metadata changed message; users not found') } + const keys = this._getKeyPairs.execute() + if (keys.isFailed()) { + return Result.fail('Cannot send metadata changed message; keys not found') + } + const errors: string[] = [] for (const user of users.getValue()) { - if (user.user_uuid === params.senderUuid) { + if (user.user_uuid === this.users.sureUser.uuid) { continue } - const trustedContact = this.findContact.execute({ userUuid: user.user_uuid }) + const trustedContact = this._findContact.execute({ userUuid: user.user_uuid }) if (trustedContact.isFailed()) { continue } const sendMessageResult = await this.sendToContact({ vault: params.vault, - keys: params.keys, + keys: keys.getValue(), contact: trustedContact.getValue(), }) @@ -84,7 +93,7 @@ export class SendVaultDataChangedMessage implements UseCaseInterface { }, } - const encryptedMessage = this.encryptMessage.execute({ + const encryptedMessage = this._encryptMessage.execute({ message: message, keys: params.keys, recipientPublicKey: params.contact.publicKeySet.encryption, @@ -100,7 +109,7 @@ export class SendVaultDataChangedMessage implements UseCaseInterface { params.vault.systemIdentifier, ) - const sendMessageResult = await this.sendMessage.execute({ + const sendMessageResult = await this._sendMessage.execute({ recipientUuid: params.contact.contactUuid, encryptedMessage: encryptedMessage.getValue(), replaceabilityIdentifier, diff --git a/packages/services/src/Domain/SharedVaults/UseCase/SendVaultKeyChangedMessage.ts b/packages/services/src/Domain/SharedVaults/UseCase/SendVaultKeyChangedMessage.ts index 9a2d183d4..c0330ffe8 100644 --- a/packages/services/src/Domain/SharedVaults/UseCase/SendVaultKeyChangedMessage.ts +++ b/packages/services/src/Domain/SharedVaults/UseCase/SendVaultKeyChangedMessage.ts @@ -1,3 +1,4 @@ +import { UserServiceInterface } from './../../User/UserServiceInterface' import { AsymmetricMessagePayloadType, AsymmetricMessageSharedVaultRootKeyChanged, @@ -13,38 +14,38 @@ import { Result, UseCaseInterface } from '@standardnotes/domain-core' import { GetReplaceabilityIdentifier } from '../../AsymmetricMessage/UseCase/GetReplaceabilityIdentifier' import { FindContact } from '../../Contacts/UseCase/FindContact' import { KeySystemKeyManagerInterface } from '../../KeySystem/KeySystemKeyManagerInterface' +import { GetKeyPairs } from '../../Encryption/UseCase/GetKeyPairs' export class SendVaultKeyChangedMessage implements UseCaseInterface { constructor( - private encryptMessage: EncryptMessage, + private users: UserServiceInterface, private keyManager: KeySystemKeyManagerInterface, - private findContact: FindContact, - private sendMessage: SendMessage, - private getVaultUsers: GetVaultUsers, + private _encryptMessage: EncryptMessage, + private _findContact: FindContact, + private _sendMessage: SendMessage, + private _getVaultUsers: GetVaultUsers, + private _getKeyPairs: GetKeyPairs, ) {} - async execute(params: { - keySystemIdentifier: KeySystemIdentifier - sharedVaultUuid: string - senderUuid: string - keys: { - encryption: PkcKeyPair - signing: PkcKeyPair - } - }): Promise> { - const users = await this.getVaultUsers.execute({ sharedVaultUuid: params.sharedVaultUuid, readFromCache: false }) + async execute(params: { keySystemIdentifier: KeySystemIdentifier; sharedVaultUuid: string }): Promise> { + const users = await this._getVaultUsers.execute({ sharedVaultUuid: params.sharedVaultUuid, readFromCache: false }) if (users.isFailed()) { return Result.fail('Cannot send root key changed message; users not found') } + const keys = this._getKeyPairs.execute() + if (keys.isFailed()) { + return Result.fail('Cannot send root key changed message; keys not found') + } + const errors: string[] = [] for (const user of users.getValue()) { - if (user.user_uuid === params.senderUuid) { + if (user.user_uuid === this.users.sureUser.uuid) { continue } - const trustedContact = this.findContact.execute({ userUuid: user.user_uuid }) + const trustedContact = this._findContact.execute({ userUuid: user.user_uuid }) if (trustedContact.isFailed()) { continue } @@ -52,7 +53,7 @@ export class SendVaultKeyChangedMessage implements UseCaseInterface { const result = await this.sendToContact({ keySystemIdentifier: params.keySystemIdentifier, sharedVaultUuid: params.sharedVaultUuid, - keys: params.keys, + keys: keys.getValue(), contact: trustedContact.getValue(), }) @@ -87,7 +88,7 @@ export class SendVaultKeyChangedMessage implements UseCaseInterface { data: { recipientUuid: params.contact.contactUuid, rootKey: keySystemRootKey.content }, } - const encryptedMessage = this.encryptMessage.execute({ + const encryptedMessage = this._encryptMessage.execute({ message: message, keys: params.keys, recipientPublicKey: params.contact.publicKeySet.encryption, @@ -103,7 +104,7 @@ export class SendVaultKeyChangedMessage implements UseCaseInterface { params.keySystemIdentifier, ) - const sendMessageResult = await this.sendMessage.execute({ + const sendMessageResult = await this._sendMessage.execute({ recipientUuid: params.contact.contactUuid, encryptedMessage: encryptedMessage.getValue(), replaceabilityIdentifier, diff --git a/packages/services/src/Domain/SharedVaults/UseCase/ShareContactWithVault.ts b/packages/services/src/Domain/SharedVaults/UseCase/ShareContactWithVault.ts index cee580b35..0180dc8e9 100644 --- a/packages/services/src/Domain/SharedVaults/UseCase/ShareContactWithVault.ts +++ b/packages/services/src/Domain/SharedVaults/UseCase/ShareContactWithVault.ts @@ -1,37 +1,35 @@ +import { UserServiceInterface } from './../../User/UserServiceInterface' import { TrustedContactInterface, SharedVaultListingInterface, AsymmetricMessagePayloadType, } from '@standardnotes/models' -import { PkcKeyPair } from '@standardnotes/sncrypto-common' import { SendMessage } from '../../AsymmetricMessage/UseCase/SendMessage' import { EncryptMessage } from '../../Encryption/UseCase/Asymmetric/EncryptMessage' import { Result, UseCaseInterface } from '@standardnotes/domain-core' import { FindContact } from '../../Contacts/UseCase/FindContact' import { GetVaultUsers } from '../../VaultUser/UseCase/GetVaultUsers' +import { GetKeyPairs } from '../../Encryption/UseCase/GetKeyPairs' export class ShareContactWithVault implements UseCaseInterface { constructor( - private findContact: FindContact, - private encryptMessage: EncryptMessage, - private sendMessage: SendMessage, - private getVaultUsers: GetVaultUsers, + private users: UserServiceInterface, + private _findContact: FindContact, + private _encryptMessage: EncryptMessage, + private _sendMessage: SendMessage, + private _getVaultUsers: GetVaultUsers, + private _getKeyPairs: GetKeyPairs, ) {} async execute(params: { - keys: { - encryption: PkcKeyPair - signing: PkcKeyPair - } - senderUserUuid: string sharedVault: SharedVaultListingInterface contactToShare: TrustedContactInterface }): Promise> { - if (params.sharedVault.sharing.ownerUserUuid !== params.senderUserUuid) { + if (params.sharedVault.sharing.ownerUserUuid !== this.users.sureUser.uuid) { return Result.fail('Cannot share contact; user is not the owner of the shared vault') } - const users = await this.getVaultUsers.execute({ + const users = await this._getVaultUsers.execute({ sharedVaultUuid: params.sharedVault.sharing.sharedVaultUuid, readFromCache: false, }) @@ -44,8 +42,13 @@ export class ShareContactWithVault implements UseCaseInterface { return Result.ok() } + const keys = this._getKeyPairs.execute() + if (keys.isFailed()) { + return Result.fail('Cannot share contact; keys not found') + } + for (const vaultUser of users.getValue()) { - if (vaultUser.user_uuid === params.senderUserUuid) { + if (vaultUser.user_uuid === this.users.sureUser.uuid) { continue } @@ -53,12 +56,12 @@ export class ShareContactWithVault implements UseCaseInterface { continue } - const vaultUserAsContact = this.findContact.execute({ userUuid: vaultUser.user_uuid }) + const vaultUserAsContact = this._findContact.execute({ userUuid: vaultUser.user_uuid }) if (vaultUserAsContact.isFailed()) { continue } - const encryptedMessage = this.encryptMessage.execute({ + const encryptedMessage = this._encryptMessage.execute({ message: { type: AsymmetricMessagePayloadType.ContactShare, data: { @@ -66,7 +69,7 @@ export class ShareContactWithVault implements UseCaseInterface { trustedContact: params.contactToShare.content, }, }, - keys: params.keys, + keys: keys.getValue(), recipientPublicKey: vaultUserAsContact.getValue().publicKeySet.encryption, }) @@ -74,7 +77,7 @@ export class ShareContactWithVault implements UseCaseInterface { continue } - await this.sendMessage.execute({ + await this._sendMessage.execute({ recipientUuid: vaultUserAsContact.getValue().contactUuid, encryptedMessage: encryptedMessage.getValue(), replaceabilityIdentifier: undefined, diff --git a/packages/services/src/Domain/User/UserService.spec.ts b/packages/services/src/Domain/User/UserService.spec.ts index 735e4e413..aaebaebbc 100644 --- a/packages/services/src/Domain/User/UserService.spec.ts +++ b/packages/services/src/Domain/User/UserService.spec.ts @@ -1,3 +1,4 @@ +import { DecryptErroredPayloads } from './../Encryption/UseCase/DecryptErroredPayloads' import { ReencryptTypeAItems } from './../Encryption/UseCase/TypeA/ReencryptTypeAItems' import { EncryptionProviderInterface } from './../Encryption/EncryptionProviderInterface' import { UserApiServiceInterface } from '@standardnotes/api' @@ -27,6 +28,7 @@ describe('UserService', () => { let protectionService: ProtectionsClientInterface let userApiService: UserApiServiceInterface let reencryptTypeAItems: ReencryptTypeAItems + let decryptErroredPayloads: DecryptErroredPayloads let internalEventBus: InternalEventBusInterface const createService = () => @@ -41,6 +43,7 @@ describe('UserService', () => { protectionService, userApiService, reencryptTypeAItems, + decryptErroredPayloads, internalEventBus, ) diff --git a/packages/services/src/Domain/User/UserService.ts b/packages/services/src/Domain/User/UserService.ts index f78710e5f..0151fda94 100644 --- a/packages/services/src/Domain/User/UserService.ts +++ b/packages/services/src/Domain/User/UserService.ts @@ -25,7 +25,7 @@ import { } from '../Challenge' import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface' import { AbstractService } from '../Service/AbstractService' -import { UserClientInterface } from './UserClientInterface' +import { UserServiceInterface } from './UserServiceInterface' import { DeinitSource } from '../Application/DeinitSource' import { StoragePersistencePolicies } from '../Storage/StorageTypes' import { SessionsClientInterface } from '../Session/SessionsClientInterface' @@ -38,10 +38,11 @@ import { SignedInOrRegisteredEventPayload } from './SignedInOrRegisteredEventPay import { CredentialsChangeFunctionResponse } from './CredentialsChangeFunctionResponse' import { EncryptionProviderInterface } from '../Encryption/EncryptionProviderInterface' import { ReencryptTypeAItems } from '../Encryption/UseCase/TypeA/ReencryptTypeAItems' +import { DecryptErroredPayloads } from '../Encryption/UseCase/DecryptErroredPayloads' export class UserService extends AbstractService - implements UserClientInterface, InternalEventHandlerInterface + implements UserServiceInterface, InternalEventHandlerInterface { private signingIn = false private registering = false @@ -60,6 +61,7 @@ export class UserService private protections: ProtectionsClientInterface, private userApi: UserApiServiceInterface, private _reencryptTypeAItems: ReencryptTypeAItems, + private _decryptErroredPayloads: DecryptErroredPayloads, protected override internalEventBus: InternalEventBusInterface, ) { super(internalEventBus) @@ -77,6 +79,7 @@ export class UserService ;(this.protections as unknown) = undefined ;(this.userApi as unknown) = undefined ;(this._reencryptTypeAItems as unknown) = undefined + ;(this._decryptErroredPayloads as unknown) = undefined } async handleEvent(event: InternalEventInterface): Promise { @@ -104,18 +107,26 @@ export class UserService }) .then(() => { if (!payload.awaitSync) { - void this.encryption.decryptErroredPayloads() + void this._decryptErroredPayloads.execute() } }) if (payload.awaitSync) { await syncPromise - await this.encryption.decryptErroredPayloads() + await this._decryptErroredPayloads.execute() } } } + get user(): User | undefined { + return this.sessions.getUser() + } + + get sureUser(): User { + return this.sessions.getSureUser() + } + getUserUuid(): string { return this.sessions.userUuid } diff --git a/packages/services/src/Domain/User/UserClientInterface.ts b/packages/services/src/Domain/User/UserServiceInterface.ts similarity index 89% rename from packages/services/src/Domain/User/UserClientInterface.ts rename to packages/services/src/Domain/User/UserServiceInterface.ts index fef88b566..c7d78b93e 100644 --- a/packages/services/src/Domain/User/UserClientInterface.ts +++ b/packages/services/src/Domain/User/UserServiceInterface.ts @@ -2,13 +2,15 @@ import { Base64String } from '@standardnotes/sncrypto-common' import { KeyParamsOrigination, UserRequestType } from '@standardnotes/common' import { DeinitSource } from '../Application/DeinitSource' import { UserRegistrationResponseBody } from '@standardnotes/api' -import { HttpResponse, SignInResponse } from '@standardnotes/responses' +import { HttpResponse, SignInResponse, User } from '@standardnotes/responses' import { AbstractService } from '../Service/AbstractService' import { AccountEventData } from './AccountEventData' import { AccountEvent } from './AccountEvent' import { CredentialsChangeFunctionResponse } from './CredentialsChangeFunctionResponse' -export interface UserClientInterface extends AbstractService { +export interface UserServiceInterface extends AbstractService { + get user(): User | undefined + get sureUser(): User getUserUuid(): string isSignedIn(): boolean diff --git a/packages/services/src/Domain/Vault/UseCase/ChangeVaultKeyOptions.ts b/packages/services/src/Domain/Vault/UseCase/ChangeVaultKeyOptions.ts index 60af590ca..d3552cae0 100644 --- a/packages/services/src/Domain/Vault/UseCase/ChangeVaultKeyOptions.ts +++ b/packages/services/src/Domain/Vault/UseCase/ChangeVaultKeyOptions.ts @@ -1,207 +1,66 @@ -import { MutatorClientInterface, SyncServiceInterface } from '@standardnotes/services' -import { - KeySystemPasswordType, - KeySystemRootKeyStorageMode, - VaultListingInterface, - VaultListingMutator, -} from '@standardnotes/models' +import { RotateVaultKey } from './RotateVaultKey' +import { SyncServiceInterface } from '@standardnotes/services' +import { KeySystemPasswordType, KeySystemRootKeyStorageMode } from '@standardnotes/models' import { ChangeVaultKeyOptionsDTO } from './ChangeVaultKeyOptionsDTO' -import { GetVault } from './GetVault' -import { EncryptionProviderInterface } from '../../Encryption/EncryptionProviderInterface' -import { KeySystemKeyManagerInterface } from '../../KeySystem/KeySystemKeyManagerInterface' import { Result, UseCaseInterface } from '@standardnotes/domain-core' +import { ChangeVaultStorageMode } from './ChangeVaultStorageMode' export class ChangeVaultKeyOptions implements UseCaseInterface { constructor( - private mutator: MutatorClientInterface, private sync: SyncServiceInterface, - private encryption: EncryptionProviderInterface, - private keys: KeySystemKeyManagerInterface, - private getVault: GetVault, + private _rotateVaultKey: RotateVaultKey, + private _changeVaultStorageMode: ChangeVaultStorageMode, ) {} async execute(dto: ChangeVaultKeyOptionsDTO): Promise> { - if (dto.newPasswordType) { - const result = await this.handleNewPasswordType(dto) - if (result.isFailed()) { - return result + let newStorageMode = dto.newStorageMode + let vault = dto.vault + + if (dto.newPasswordOptions) { + if ( + dto.newPasswordOptions.passwordType === KeySystemPasswordType.Randomized && + dto.newStorageMode && + dto.newStorageMode !== KeySystemRootKeyStorageMode.Synced + ) { + return Result.fail('Cannot change storage mode to non-synced for randomized vault') } - } - if (dto.newStorageMode) { - const result = await this.handleNewStorageMode(dto) - if (result.isFailed()) { - return result + if ( + dto.newPasswordOptions.passwordType === KeySystemPasswordType.UserInputted && + !dto.newPasswordOptions.userInputtedPassword + ) { + return Result.fail('User inputted password required') } - } - await this.sync.sync() - - return Result.ok() - } - - private async handleNewPasswordType(dto: ChangeVaultKeyOptionsDTO): Promise> { - if (!dto.newPasswordType) { - return Result.ok() - } - - if (dto.vault.keyPasswordType === dto.newPasswordType.passwordType) { - return Result.fail('Vault password type is already set to this type') - } - - if (dto.newPasswordType.passwordType === KeySystemPasswordType.UserInputted) { - if (!dto.newPasswordType.userInputtedPassword) { - return Result.fail('User inputted password is required') - } - const useStorageMode = dto.newStorageMode ?? dto.vault.keyStorageMode - const result = await this.changePasswordTypeToUserInputted( - dto.vault, - dto.newPasswordType.userInputtedPassword, - useStorageMode, - ) - if (result.isFailed()) { - return result - } - } else if (dto.newPasswordType.passwordType === KeySystemPasswordType.Randomized) { - const result = await this.changePasswordTypeToRandomized(dto.vault) - if (result.isFailed()) { - return result - } - } - - return Result.ok() - } - - private async handleNewStorageMode(dto: ChangeVaultKeyOptionsDTO): Promise> { - if (!dto.newStorageMode) { - return Result.ok() - } - - const result = this.getVault.execute({ keySystemIdentifier: dto.vault.systemIdentifier }) - if (result.isFailed()) { - return Result.fail('Vault not found') - } - - const latestVault = result.getValue() - - if (latestVault.rootKeyParams.passwordType !== KeySystemPasswordType.UserInputted) { - return Result.fail('Vault uses randomized password and cannot change its storage preference') - } - - if (dto.newStorageMode === latestVault.keyStorageMode) { - return Result.fail('Vault already uses this storage preference') - } - - if ( - dto.newStorageMode === KeySystemRootKeyStorageMode.Local || - dto.newStorageMode === KeySystemRootKeyStorageMode.Ephemeral - ) { - const result = await this.changeStorageModeToLocalOrEphemeral(latestVault, dto.newStorageMode) - if (result.isFailed()) { - return result - } - } else if (dto.newStorageMode === KeySystemRootKeyStorageMode.Synced) { - const result = await this.changeStorageModeToSynced(latestVault) - if (result.isFailed()) { - return result - } - } - - return Result.ok() - } - - private async changePasswordTypeToUserInputted( - vault: VaultListingInterface, - userInputtedPassword: string, - storageMode: KeySystemRootKeyStorageMode, - ): Promise> { - const newRootKey = this.encryption.createUserInputtedKeySystemRootKey({ - systemIdentifier: vault.systemIdentifier, - userInputtedPassword: userInputtedPassword, - }) - - if (storageMode === KeySystemRootKeyStorageMode.Synced) { - await this.mutator.insertItem(newRootKey, true) - } else { - this.keys.cacheKey(newRootKey, storageMode) - } - - await this.mutator.changeItem(vault, (mutator) => { - mutator.rootKeyParams = newRootKey.keyParams - }) - - await this.keys.queueVaultItemsKeysForReencryption(vault.systemIdentifier) - - return Result.ok() - } - - private async changePasswordTypeToRandomized(vault: VaultListingInterface): Promise> { - if (vault.keyStorageMode !== KeySystemRootKeyStorageMode.Synced) { - this.keys.removeKeyFromCache(vault.systemIdentifier) - - await this.mutator.changeItem(vault, (mutator) => { - mutator.keyStorageMode = KeySystemRootKeyStorageMode.Synced + const result = await this._rotateVaultKey.execute({ + vault: dto.vault, + userInputtedPassword: + dto.newPasswordOptions.passwordType === KeySystemPasswordType.UserInputted + ? dto.newPasswordOptions.userInputtedPassword + : undefined, }) - } - - const newRootKey = this.encryption.createRandomizedKeySystemRootKey({ - systemIdentifier: vault.systemIdentifier, - }) - - await this.mutator.changeItem(vault, (mutator) => { - mutator.rootKeyParams = newRootKey.keyParams - }) - - await this.mutator.insertItem(newRootKey, true) - - await this.keys.queueVaultItemsKeysForReencryption(vault.systemIdentifier) - - return Result.ok() - } - - private async changeStorageModeToLocalOrEphemeral( - vault: VaultListingInterface, - newStorageMode: KeySystemRootKeyStorageMode, - ): Promise> { - const primaryKey = this.keys.getPrimaryKeySystemRootKey(vault.systemIdentifier) - if (!primaryKey) { - return Result.fail('No primary key found') - } - - if (newStorageMode === KeySystemRootKeyStorageMode.Ephemeral) { - this.keys.removeKeyFromCache(vault.systemIdentifier) - } - - this.keys.cacheKey(primaryKey, newStorageMode) - await this.keys.deleteAllSyncedKeySystemRootKeys(vault.systemIdentifier) - - await this.mutator.changeItem(vault, (mutator) => { - mutator.keyStorageMode = newStorageMode - }) - - await this.sync.sync() - - return Result.ok() - } - - private async changeStorageModeToSynced(vault: VaultListingInterface): Promise> { - const allRootKeys = this.keys.getAllKeySystemRootKeysForVault(vault.systemIdentifier) - const syncedRootKeys = this.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier) - - this.keys.removeKeyFromCache(vault.systemIdentifier) - - for (const key of allRootKeys) { - const existingSyncedKey = syncedRootKeys.find((syncedKey) => syncedKey.token === key.token) - if (existingSyncedKey) { - continue + if (result.isFailed()) { + return result } - await this.mutator.insertItem(key) + vault = result.getValue() + + if (dto.newPasswordOptions.passwordType === KeySystemPasswordType.Randomized) { + newStorageMode = KeySystemRootKeyStorageMode.Synced + } } - await this.mutator.changeItem(vault, (mutator) => { - mutator.keyStorageMode = KeySystemRootKeyStorageMode.Synced - }) + if (newStorageMode && newStorageMode !== vault.keyStorageMode) { + const result = await this._changeVaultStorageMode.execute({ + vault: vault, + newStorageMode: newStorageMode, + }) + if (result.isFailed()) { + return result + } + } + + await this.sync.sync() return Result.ok() } diff --git a/packages/services/src/Domain/Vault/UseCase/ChangeVaultKeyOptionsDTO.ts b/packages/services/src/Domain/Vault/UseCase/ChangeVaultKeyOptionsDTO.ts index c521b2865..608d24026 100644 --- a/packages/services/src/Domain/Vault/UseCase/ChangeVaultKeyOptionsDTO.ts +++ b/packages/services/src/Domain/Vault/UseCase/ChangeVaultKeyOptionsDTO.ts @@ -2,7 +2,7 @@ import { KeySystemPasswordType, KeySystemRootKeyStorageMode, VaultListingInterfa export type ChangeVaultKeyOptionsDTO = { vault: VaultListingInterface - newPasswordType: + newPasswordOptions: | { passwordType: KeySystemPasswordType.Randomized } | { passwordType: KeySystemPasswordType.UserInputted; userInputtedPassword: string } | undefined diff --git a/packages/services/src/Domain/Vault/UseCase/ChangeVaultStorageMode.ts b/packages/services/src/Domain/Vault/UseCase/ChangeVaultStorageMode.ts new file mode 100644 index 000000000..3af59e073 --- /dev/null +++ b/packages/services/src/Domain/Vault/UseCase/ChangeVaultStorageMode.ts @@ -0,0 +1,107 @@ +import { MutatorClientInterface, SyncServiceInterface } from '@standardnotes/services' +import { + KeySystemPasswordType, + KeySystemRootKeyStorageMode, + VaultListingInterface, + VaultListingMutator, +} from '@standardnotes/models' +import { GetVault } from './GetVault' +import { KeySystemKeyManagerInterface } from '../../KeySystem/KeySystemKeyManagerInterface' +import { Result, UseCaseInterface } from '@standardnotes/domain-core' + +export class ChangeVaultStorageMode implements UseCaseInterface { + constructor( + private mutator: MutatorClientInterface, + private sync: SyncServiceInterface, + private keys: KeySystemKeyManagerInterface, + private _getVault: GetVault, + ) {} + + async execute(dto: { + vault: VaultListingInterface + newStorageMode: KeySystemRootKeyStorageMode + }): Promise> { + const result = this._getVault.execute({ keySystemIdentifier: dto.vault.systemIdentifier }) + if (result.isFailed()) { + return Result.fail('Vault not found') + } + + const vault = result.getValue() + if ( + vault.keyPasswordType === KeySystemPasswordType.Randomized && + dto.newStorageMode !== KeySystemRootKeyStorageMode.Synced + ) { + return Result.fail('Cannot change storage mode to non-synced for randomized vault') + } + + const latestVault = result.getValue() + + if (dto.newStorageMode === latestVault.keyStorageMode) { + return Result.fail('Vault already uses this storage preference') + } + + if ( + dto.newStorageMode === KeySystemRootKeyStorageMode.Local || + dto.newStorageMode === KeySystemRootKeyStorageMode.Ephemeral + ) { + const result = await this.changeStorageModeToLocalOrEphemeral(latestVault, dto.newStorageMode) + if (result.isFailed()) { + return result + } + } else if (dto.newStorageMode === KeySystemRootKeyStorageMode.Synced) { + const result = await this.changeStorageModeToSynced(latestVault) + if (result.isFailed()) { + return result + } + } + + return Result.ok() + } + + private async changeStorageModeToLocalOrEphemeral( + vault: VaultListingInterface, + newStorageMode: KeySystemRootKeyStorageMode, + ): Promise> { + const primaryKey = this.keys.getPrimaryKeySystemRootKey(vault.systemIdentifier) + if (!primaryKey) { + return Result.fail('No primary key found') + } + + if (newStorageMode === KeySystemRootKeyStorageMode.Ephemeral) { + this.keys.removeKeyFromCache(vault.systemIdentifier) + } + + this.keys.cacheKey(primaryKey, newStorageMode) + await this.keys.deleteAllSyncedKeySystemRootKeys(vault.systemIdentifier) + + const updatedVault = await this.mutator.changeItem(vault, (mutator) => { + mutator.keyStorageMode = newStorageMode + }) + + await this.sync.sync() + + return Result.ok(updatedVault) + } + + private async changeStorageModeToSynced(vault: VaultListingInterface): Promise> { + const allRootKeys = this.keys.getAllKeySystemRootKeysForVault(vault.systemIdentifier) + const syncedRootKeys = this.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier) + + this.keys.removeKeyFromCache(vault.systemIdentifier) + + for (const key of allRootKeys) { + const existingSyncedKey = syncedRootKeys.find((syncedKey) => syncedKey.token === key.token) + if (existingSyncedKey) { + continue + } + + await this.mutator.insertItem(key) + } + + const updatedVault = await this.mutator.changeItem(vault, (mutator) => { + mutator.keyStorageMode = KeySystemRootKeyStorageMode.Synced + }) + + return Result.ok(updatedVault) + } +} diff --git a/packages/services/src/Domain/Vault/UseCase/RotateVaultKey.ts b/packages/services/src/Domain/Vault/UseCase/RotateVaultKey.ts index dc3e28dd3..bf339817f 100644 --- a/packages/services/src/Domain/Vault/UseCase/RotateVaultKey.ts +++ b/packages/services/src/Domain/Vault/UseCase/RotateVaultKey.ts @@ -1,9 +1,9 @@ +import { IsVaultOwner } from './../../VaultUser/UseCase/IsVaultOwner' +import { NotifyVaultUsersOfKeyRotation } from './../../SharedVaults/UseCase/NotifyVaultUsersOfKeyRotation' import { UuidGenerator, assert } from '@standardnotes/utils' -import { ClientDisplayableError, isClientDisplayableError } from '@standardnotes/responses' import { KeySystemIdentifier, KeySystemRootKeyInterface, - KeySystemPasswordType, KeySystemRootKeyStorageMode, VaultListingInterface, VaultListingMutator, @@ -11,19 +11,47 @@ import { import { MutatorClientInterface } from '../../Mutator/MutatorClientInterface' import { EncryptionProviderInterface } from '../../Encryption/EncryptionProviderInterface' import { KeySystemKeyManagerInterface } from '../../KeySystem/KeySystemKeyManagerInterface' +import { Result, UseCaseInterface } from '@standardnotes/domain-core' -export class RotateVaultKey { +export class RotateVaultKey implements UseCaseInterface { constructor( private mutator: MutatorClientInterface, private encryption: EncryptionProviderInterface, private keys: KeySystemKeyManagerInterface, + private _notifyVaultUsersOfKeyRotation: NotifyVaultUsersOfKeyRotation, + private _isVaultOwner: IsVaultOwner, ) {} async execute(params: { vault: VaultListingInterface - sharedVaultUuid: string | undefined userInputtedPassword: string | undefined - }): Promise { + }): Promise> { + const { newRootKey, updatedVault } = await this.updateRootKeyparams(params) + + await this.createNewKeySystemItemsKey({ + keySystemIdentifier: updatedVault.systemIdentifier, + sharedVaultUuid: updatedVault.isSharedVaultListing() ? updatedVault.sharing.sharedVaultUuid : undefined, + rootKeyToken: newRootKey.token, + }) + + await this.keys.queueVaultItemsKeysForReencryption(updatedVault.systemIdentifier) + + const shareResult = await this.shareNewKeyWithMembers({ + vault: updatedVault, + newRootKey, + }) + + if (shareResult.isFailed()) { + return Result.fail(shareResult.getError()) + } + + return Result.ok(updatedVault) + } + + private async updateRootKeyparams(params: { + vault: VaultListingInterface + userInputtedPassword: string | undefined + }): Promise<{ newRootKey: KeySystemRootKeyInterface; updatedVault: VaultListingInterface }> { const currentRootKey = this.keys.getPrimaryKeySystemRootKey(params.vault.systemIdentifier) if (!currentRootKey) { throw new Error('Cannot rotate key system root key; key system root key not found') @@ -31,16 +59,12 @@ export class RotateVaultKey { let newRootKey: KeySystemRootKeyInterface | undefined - if (currentRootKey.keyParams.passwordType === KeySystemPasswordType.UserInputted) { - if (!params.userInputtedPassword) { - throw new Error('Cannot rotate key system root key; user inputted password required') - } - + if (params.userInputtedPassword) { newRootKey = this.encryption.createUserInputtedKeySystemRootKey({ systemIdentifier: params.vault.systemIdentifier, userInputtedPassword: params.userInputtedPassword, }) - } else if (currentRootKey.keyParams.passwordType === KeySystemPasswordType.Randomized) { + } else { newRootKey = this.encryption.createRandomizedKeySystemRootKey({ systemIdentifier: params.vault.systemIdentifier, }) @@ -50,39 +74,28 @@ export class RotateVaultKey { throw new Error('Cannot rotate key system root key; new root key not created') } - if (params.vault.keyStorageMode === KeySystemRootKeyStorageMode.Synced) { + if (!params.userInputtedPassword || params.vault.keyStorageMode === KeySystemRootKeyStorageMode.Synced) { await this.mutator.insertItem(newRootKey, true) } else { this.keys.cacheKey(newRootKey, params.vault.keyStorageMode) } - await this.mutator.changeItem(params.vault, (mutator) => { - assert(newRootKey) - mutator.rootKeyParams = newRootKey.keyParams - }) + const updatedVault = await this.mutator.changeItem( + params.vault, + (mutator) => { + assert(newRootKey) + mutator.rootKeyParams = newRootKey.keyParams + }, + ) - const errors: ClientDisplayableError[] = [] - - const updateKeySystemItemsKeyResult = await this.createNewKeySystemItemsKey({ - keySystemIdentifier: params.vault.systemIdentifier, - sharedVaultUuid: params.sharedVaultUuid, - rootKeyToken: newRootKey.token, - }) - - if (isClientDisplayableError(updateKeySystemItemsKeyResult)) { - errors.push(updateKeySystemItemsKeyResult) - } - - await this.keys.queueVaultItemsKeysForReencryption(params.vault.systemIdentifier) - - return errors + return { newRootKey, updatedVault } } private async createNewKeySystemItemsKey(params: { keySystemIdentifier: KeySystemIdentifier sharedVaultUuid: string | undefined rootKeyToken: string - }): Promise { + }): Promise { const newItemsKeyUuid = UuidGenerator.GenerateUuid() const newItemsKey = this.encryption.createKeySystemItemsKey( newItemsKeyUuid, @@ -92,4 +105,25 @@ export class RotateVaultKey { ) await this.mutator.insertItem(newItemsKey) } + + private async shareNewKeyWithMembers(params: { + vault: VaultListingInterface + newRootKey: KeySystemRootKeyInterface + }): Promise> { + if (!params.vault.isSharedVaultListing()) { + return Result.ok() + } + + const isOwner = this._isVaultOwner.execute({ sharedVault: params.vault }).getValue() + + if (!isOwner) { + return Result.ok() + } + + const result = await this._notifyVaultUsersOfKeyRotation.execute({ + sharedVault: params.vault, + }) + + return result + } } diff --git a/packages/services/src/Domain/Vault/VaultService.ts b/packages/services/src/Domain/Vault/VaultService.ts index 0d797c721..41af05ec8 100644 --- a/packages/services/src/Domain/Vault/VaultService.ts +++ b/packages/services/src/Domain/Vault/VaultService.ts @@ -1,3 +1,4 @@ +import { SendVaultDataChangedMessage } from './../SharedVaults/UseCase/SendVaultDataChangedMessage' import { isClientDisplayableError } from '@standardnotes/responses' import { DecryptedItemInterface, @@ -46,6 +47,7 @@ export class VaultService private _removeItemFromVault: RemoveItemFromVault, private _deleteVault: DeleteVault, private _rotateVaultKey: RotateVaultKey, + private _sendVaultDataChangeMessage: SendVaultDataChangedMessage, eventBus: InternalEventBusInterface, ) { super(eventBus) @@ -192,6 +194,12 @@ export class VaultService await this.sync.sync() + if (updatedVault.isSharedVaultListing()) { + await this._sendVaultDataChangeMessage.execute({ + vault: updatedVault, + }) + } + return updatedVault } @@ -202,12 +210,9 @@ export class VaultService await this._rotateVaultKey.execute({ vault, - sharedVaultUuid: vault.isSharedVaultListing() ? vault.sharing.sharedVaultUuid : undefined, userInputtedPassword: vaultPassword, }) - await this.notifyEventSync(VaultServiceEvent.VaultRootKeyRotated, { vault }) - await this.sync.sync() } @@ -228,17 +233,13 @@ export class VaultService return this.getVault({ keySystemIdentifier: latestItem.key_system_identifier }) } - async changeVaultOptions(dto: ChangeVaultKeyOptionsDTO): Promise> { + async changeVaultKeyOptions(dto: ChangeVaultKeyOptionsDTO): Promise> { if (this.vaultLocks.isVaultLocked(dto.vault)) { throw new Error('Attempting to change vault options on a locked vault') } const result = await this._changeVaultKeyOptions.execute(dto) - if (dto.newPasswordType) { - await this.notifyEventSync(VaultServiceEvent.VaultRootKeyRotated, { vault: dto.vault }) - } - return result } } diff --git a/packages/services/src/Domain/Vault/VaultServiceEvent.ts b/packages/services/src/Domain/Vault/VaultServiceEvent.ts index cd3ef6224..d3d77e4ab 100644 --- a/packages/services/src/Domain/Vault/VaultServiceEvent.ts +++ b/packages/services/src/Domain/Vault/VaultServiceEvent.ts @@ -1,11 +1,3 @@ -import { VaultListingInterface } from '@standardnotes/models' +export enum VaultServiceEvent {} -export enum VaultServiceEvent { - VaultRootKeyRotated = 'VaultRootKeyRotated', -} - -export type VaultServiceEventPayload = { - [VaultServiceEvent.VaultRootKeyRotated]: { - vault: VaultListingInterface - } -} +export type VaultServiceEventPayload = Record diff --git a/packages/services/src/Domain/Vault/VaultServiceInterface.ts b/packages/services/src/Domain/Vault/VaultServiceInterface.ts index bd9c9f5e8..184bbb5ed 100644 --- a/packages/services/src/Domain/Vault/VaultServiceInterface.ts +++ b/packages/services/src/Domain/Vault/VaultServiceInterface.ts @@ -36,5 +36,5 @@ export interface VaultServiceInterface params: { name: string; description: string }, ): Promise rotateVaultRootKey(vault: VaultListingInterface, vaultPassword?: string): Promise - changeVaultOptions(dto: ChangeVaultKeyOptionsDTO): Promise> + changeVaultKeyOptions(dto: ChangeVaultKeyOptionsDTO): Promise> } diff --git a/packages/services/src/Domain/VaultInvite/UseCase/InviteToVault.ts b/packages/services/src/Domain/VaultInvite/UseCase/InviteToVault.ts index 16da4ba5f..9d74d7dd7 100644 --- a/packages/services/src/Domain/VaultInvite/UseCase/InviteToVault.ts +++ b/packages/services/src/Domain/VaultInvite/UseCase/InviteToVault.ts @@ -11,27 +11,35 @@ import { EncryptMessage } from '../../Encryption/UseCase/Asymmetric/EncryptMessa import { Result, SharedVaultUserPermission, UseCaseInterface } from '@standardnotes/domain-core' import { ShareContactWithVault } from '../../SharedVaults/UseCase/ShareContactWithVault' import { KeySystemKeyManagerInterface } from '../../KeySystem/KeySystemKeyManagerInterface' +import { GetKeyPairs } from '../../Encryption/UseCase/GetKeyPairs' export class InviteToVault implements UseCaseInterface { constructor( private keyManager: KeySystemKeyManagerInterface, - private encryptMessage: EncryptMessage, - private sendInvite: SendVaultInvite, - private shareContact: ShareContactWithVault, + private _encryptMessage: EncryptMessage, + private _sendInvite: SendVaultInvite, + private _shareContact: ShareContactWithVault, + private _getKeyPairs: GetKeyPairs, ) {} async execute(params: { - keys: { - encryption: PkcKeyPair - signing: PkcKeyPair - } - senderUuid: string sharedVault: SharedVaultListingInterface sharedVaultContacts: TrustedContactInterface[] recipient: TrustedContactInterface permission: string }): Promise> { - const createInviteResult = await this.inviteContact(params) + const keys = this._getKeyPairs.execute() + if (keys.isFailed()) { + return Result.fail('Cannot invite contact; keys not found') + } + + const createInviteResult = await this.inviteContact({ + keys: keys.getValue(), + sharedVault: params.sharedVault, + sharedVaultContacts: params.sharedVaultContacts, + recipient: params.recipient, + permission: params.permission, + }) if (createInviteResult.isFailed()) { return createInviteResult @@ -39,8 +47,7 @@ export class InviteToVault implements UseCaseInterface> { - const result = await this.shareContact.execute({ - keys: params.keys, - senderUserUuid: params.senderUuid, + const result = await this._shareContact.execute({ sharedVault: params.sharedVault, contactToShare: params.contact, }) @@ -108,7 +112,7 @@ export class InviteToVault implements UseCaseInterface @@ -45,7 +46,6 @@ export class VaultInviteService private session: SessionsClientInterface, private vaultUsers: VaultUserServiceInterface, private sync: SyncServiceInterface, - private encryption: EncryptionProviderInterface, private invitesServer: SharedVaultInvitesServer, private _getAllContacts: GetAllContacts, private _getVault: GetVault, @@ -55,6 +55,8 @@ export class VaultInviteService private _getUntrustedPayload: GetUntrustedPayload, private _findContact: FindContact, private _acceptVaultInvite: AcceptVaultInvite, + private _getKeyPairs: GetKeyPairs, + private _decryptErroredPayloads: DecryptErroredPayloads, eventBus: InternalEventBusInterface, ) { super(eventBus) @@ -75,7 +77,6 @@ export class VaultInviteService ;(this.session as unknown) = undefined ;(this.vaultUsers as unknown) = undefined ;(this.sync as unknown) = undefined - ;(this.encryption as unknown) = undefined ;(this.invitesServer as unknown) = undefined ;(this._getAllContacts as unknown) = undefined ;(this._getVault as unknown) = undefined @@ -85,6 +86,8 @@ export class VaultInviteService ;(this._getUntrustedPayload as unknown) = undefined ;(this._findContact as unknown) = undefined ;(this._acceptVaultInvite as unknown) = undefined + ;(this._getKeyPairs as unknown) = undefined + ;(this._decryptErroredPayloads as unknown) = undefined this.pendingInvites = {} } @@ -142,7 +145,7 @@ export class VaultInviteService void this.sync.sync() - await this.encryption.decryptErroredPayloads() + await this._decryptErroredPayloads.execute() await this.sync.syncSharedVaultsFromScratch([pendingInvite.invite.shared_vault_uuid]) } @@ -181,11 +184,6 @@ export class VaultInviteService const contacts = contactsResult.getValue() const result = await this._inviteToVault.execute({ - keys: { - encryption: this.encryption.getKeyPair(), - signing: this.encryption.getSigningKeyPair(), - }, - senderUuid: this.session.getSureUser().uuid, sharedVault, recipient: contact, sharedVaultContacts: contacts, @@ -233,6 +231,11 @@ export class VaultInviteService return } + const keys = this._getKeyPairs.execute() + if (keys.isFailed()) { + return + } + for (const invite of invites) { delete this.pendingInvites[invite.uuid] @@ -240,7 +243,7 @@ export class VaultInviteService if (!sender.isFailed()) { const trustedMessage = this._getTrustedPayload.execute({ message: invite, - privateKey: this.encryption.getKeyPair().privateKey, + privateKey: keys.getValue().encryption.privateKey, ownUserUuid: this.session.userUuid, sender: sender.getValue(), }) @@ -258,7 +261,7 @@ export class VaultInviteService const untrustedMessage = this._getUntrustedPayload.execute({ message: invite, - privateKey: this.encryption.getKeyPair().privateKey, + privateKey: keys.getValue().encryption.privateKey, }) if (!untrustedMessage.isFailed()) { diff --git a/packages/services/src/Domain/VaultLock/VaultLockService.ts b/packages/services/src/Domain/VaultLock/VaultLockService.ts index 38b902dd5..d1e3371f6 100644 --- a/packages/services/src/Domain/VaultLock/VaultLockService.ts +++ b/packages/services/src/Domain/VaultLock/VaultLockService.ts @@ -8,6 +8,7 @@ import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface import { ContentType } from '@standardnotes/domain-core' import { EncryptionProviderInterface } from '../Encryption/EncryptionProviderInterface' import { KeySystemKeyManagerInterface } from '../KeySystem/KeySystemKeyManagerInterface' +import { DecryptErroredPayloads } from '../Encryption/UseCase/DecryptErroredPayloads' export class VaultLockService extends AbstractService @@ -20,6 +21,7 @@ export class VaultLockService private encryption: EncryptionProviderInterface, private keys: KeySystemKeyManagerInterface, private _getVaults: GetVaults, + private _decryptErroredPayloads: DecryptErroredPayloads, eventBus: InternalEventBusInterface, ) { super(eventBus) @@ -37,6 +39,7 @@ export class VaultLockService ;(this.encryption as unknown) = undefined ;(this.keys as unknown) = undefined ;(this._getVaults as unknown) = undefined + ;(this._decryptErroredPayloads as unknown) = undefined this.lockMap.clear() } @@ -86,7 +89,7 @@ export class VaultLockService this.keys.cacheKey(derivedRootKey, vault.keyStorageMode) - await this.encryption.decryptErroredPayloads() + await this._decryptErroredPayloads.execute() if (this.computeVaultLockState(vault) === 'locked') { this.keys.removeKeyFromCache(vault.systemIdentifier) diff --git a/packages/services/src/Domain/VaultUser/UseCase/GetVaultContacts.ts b/packages/services/src/Domain/VaultUser/UseCase/GetVaultContacts.ts index 95f15fe59..4c0f664e7 100644 --- a/packages/services/src/Domain/VaultUser/UseCase/GetVaultContacts.ts +++ b/packages/services/src/Domain/VaultUser/UseCase/GetVaultContacts.ts @@ -6,12 +6,12 @@ import { Result, UseCaseInterface } from '@standardnotes/domain-core' export class GetVaultContacts implements UseCaseInterface { constructor( - private findContact: FindContact, - private getVaultUsers: GetVaultUsers, + private _findContact: FindContact, + private _getVaultUsers: GetVaultUsers, ) {} async execute(dto: { sharedVaultUuid: string; readFromCache: boolean }): Promise> { - const users = await this.getVaultUsers.execute({ + const users = await this._getVaultUsers.execute({ sharedVaultUuid: dto.sharedVaultUuid, readFromCache: dto.readFromCache, }) @@ -21,7 +21,7 @@ export class GetVaultContacts implements UseCaseInterface this.findContact.execute({ userUuid: user.user_uuid })) + .map((user) => this._findContact.execute({ userUuid: user.user_uuid })) .map((result) => (result.isFailed() ? undefined : result.getValue())) .filter(isNotUndefined) diff --git a/packages/services/src/Domain/VaultUser/UseCase/IsVaultOwner.ts b/packages/services/src/Domain/VaultUser/UseCase/IsVaultOwner.ts index 44f85bfa6..77e615f2a 100644 --- a/packages/services/src/Domain/VaultUser/UseCase/IsVaultOwner.ts +++ b/packages/services/src/Domain/VaultUser/UseCase/IsVaultOwner.ts @@ -1,12 +1,17 @@ +import { UserServiceInterface } from './../../User/UserServiceInterface' import { Result, SyncUseCaseInterface } from '@standardnotes/domain-core' import { SharedVaultListingInterface } from '@standardnotes/models' export class IsVaultOwner implements SyncUseCaseInterface { - execute(dto: { sharedVault: SharedVaultListingInterface; userUuid: string }): Result { + constructor(private users: UserServiceInterface) {} + + execute(dto: { sharedVault: SharedVaultListingInterface }): Result { if (!dto.sharedVault.sharing.ownerUserUuid) { throw new Error(`Shared vault ${dto.sharedVault.sharing.sharedVaultUuid} does not have an owner user uuid`) } - return Result.ok(dto.sharedVault.sharing.ownerUserUuid === dto.userUuid) + const user = this.users.sureUser + + return Result.ok(dto.sharedVault.sharing.ownerUserUuid === user.uuid) } } diff --git a/packages/services/src/Domain/VaultUser/UseCase/LeaveSharedVault.ts b/packages/services/src/Domain/VaultUser/UseCase/LeaveSharedVault.ts index deeaaf539..28627a135 100644 --- a/packages/services/src/Domain/VaultUser/UseCase/LeaveSharedVault.ts +++ b/packages/services/src/Domain/VaultUser/UseCase/LeaveSharedVault.ts @@ -1,3 +1,4 @@ +import { UserServiceInterface } from './../../User/UserServiceInterface' import { ClientDisplayableError, isErrorResponse } from '@standardnotes/responses' import { SharedVaultUsersServerInterface } from '@standardnotes/api' import { DeleteThirdPartyVault } from '../../SharedVaults/UseCase/DeleteExternalSharedVault' @@ -6,15 +7,13 @@ import { SharedVaultListingInterface } from '@standardnotes/models' export class LeaveVault { constructor( + private users: UserServiceInterface, private vaultUserServer: SharedVaultUsersServerInterface, private items: ItemManagerInterface, - private deleteThirdPartyVault: DeleteThirdPartyVault, + private _deleteThirdPartyVault: DeleteThirdPartyVault, ) {} - async execute(params: { - sharedVault: SharedVaultListingInterface - userUuid: string - }): Promise { + async execute(params: { sharedVault: SharedVaultListingInterface }): Promise { const latestVaultListing = this.items.findItem(params.sharedVault.uuid) if (!latestVaultListing) { throw new Error(`LeaveVaultUseCase: Could not find vault ${params.sharedVault.uuid}`) @@ -22,13 +21,13 @@ export class LeaveVault { const response = await this.vaultUserServer.deleteSharedVaultUser({ sharedVaultUuid: latestVaultListing.sharing.sharedVaultUuid, - userUuid: params.userUuid, + userUuid: this.users.sureUser.uuid, }) if (isErrorResponse(response)) { return ClientDisplayableError.FromString(`Failed to leave vault ${JSON.stringify(response)}`) } - await this.deleteThirdPartyVault.execute(latestVaultListing) + await this._deleteThirdPartyVault.execute(latestVaultListing) } } diff --git a/packages/services/src/Domain/VaultUser/VaultUserService.ts b/packages/services/src/Domain/VaultUser/VaultUserService.ts index d94f0847b..993e93e47 100644 --- a/packages/services/src/Domain/VaultUser/VaultUserService.ts +++ b/packages/services/src/Domain/VaultUser/VaultUserService.ts @@ -4,7 +4,6 @@ import { GetVault } from '../Vault/UseCase/GetVault' import { InternalEventBusInterface } from './../Internal/InternalEventBusInterface' import { RemoveVaultMember } from './UseCase/RemoveSharedVaultMember' import { VaultServiceInterface } from '../Vault/VaultServiceInterface' -import { SessionsClientInterface } from './../Session/SessionsClientInterface' import { GetVaultUsers } from './UseCase/GetVaultUsers' import { SharedVaultListingInterface } from '@standardnotes/models' import { VaultUserServiceInterface } from './VaultUserServiceInterface' @@ -16,7 +15,6 @@ import { IsVaultOwner } from './UseCase/IsVaultOwner' export class VaultUserService extends AbstractService implements VaultUserServiceInterface { constructor( - private session: SessionsClientInterface, private vaults: VaultServiceInterface, private vaultLocks: VaultLockServiceInterface, private _getVaultUsers: GetVaultUsers, @@ -31,7 +29,6 @@ export class VaultUserService extends AbstractService imp override deinit(): void { super.deinit() - ;(this.session as unknown) = undefined ;(this.vaults as unknown) = undefined ;(this._getVaultUsers as unknown) = undefined ;(this._removeVaultMember as unknown) = undefined @@ -58,7 +55,6 @@ export class VaultUserService extends AbstractService imp return this._isVaultOwner .execute({ sharedVault, - userUuid: this.session.userUuid, }) .getValue() } @@ -101,7 +97,6 @@ export class VaultUserService extends AbstractService imp async leaveSharedVault(sharedVault: SharedVaultListingInterface): Promise { const result = await this._leaveVault.execute({ sharedVault: sharedVault, - userUuid: this.session.getSureUser().uuid, }) if (isClientDisplayableError(result)) { diff --git a/packages/services/src/Domain/index.ts b/packages/services/src/Domain/index.ts index eae24607a..d18610473 100644 --- a/packages/services/src/Domain/index.ts +++ b/packages/services/src/Domain/index.ts @@ -21,7 +21,6 @@ export * from './AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite' export * from './AsymmetricMessage/UseCase/ResendAllMessages' export * from './AsymmetricMessage/UseCase/ResendMessage' export * from './AsymmetricMessage/UseCase/SendMessage' -export * from './Contacts/UseCase/SendOwnContactChangeMessage' export * from './Auth/AuthClientInterface' export * from './Auth/AuthManager' export * from './Authenticator/AuthenticatorClientInterface' @@ -42,6 +41,7 @@ export * from './Contacts/UseCase/FindContact' export * from './Contacts/UseCase/GetAllContacts' export * from './Contacts/UseCase/HandleKeyPairChange' export * from './Contacts/UseCase/ReplaceContactData' +export * from './Contacts/UseCase/SendOwnContactChangeMessage' export * from './Contacts/UseCase/Types/ItemSignatureValidationResult' export * from './Contacts/UseCase/ValidateItemSigner' export * from './Device/DatabaseItemMetadata' @@ -67,6 +67,8 @@ export * from './Encryption/UseCase/Asymmetric/DecryptOwnMessage' export * from './Encryption/UseCase/Asymmetric/EncryptMessage' export * from './Encryption/UseCase/Asymmetric/GetMessageAdditionalData' export * from './Encryption/UseCase/DecryptBackupFile' +export * from './Encryption/UseCase/DecryptErroredPayloads' +export * from './Encryption/UseCase/GetKeyPairs' export * from './Encryption/UseCase/ItemsKey/CreateNewDefaultItemsKey' export * from './Encryption/UseCase/ItemsKey/CreateNewItemsKeyWithRollback' export * from './Encryption/UseCase/ItemsKey/FindDefaultItemsKey' @@ -174,23 +176,14 @@ export * from './User/AccountEventData' export * from './User/CredentialsChangeFunctionResponse' export * from './User/SignedInOrRegisteredEventPayload' export * from './User/SignedOutEventPayload' -export * from './User/UserClientInterface' -export * from './User/UserClientInterface' +export * from './User/UserServiceInterface' +export * from './User/UserServiceInterface' export * from './User/UserService' export * from './UserEvent/NotificationService' export * from './UserEvent/NotificationServiceEvent' -export * from './VaultInvite/InviteRecord' -export * from './VaultInvite/UseCase/AcceptVaultInvite' -export * from './VaultInvite/UseCase/InviteToVault' -export * from './VaultInvite/UseCase/ReuploadAllInvites' -export * from './VaultInvite/UseCase/ReuploadInvite' -export * from './VaultInvite/UseCase/ReuploadVaultInvites' -export * from './VaultInvite/UseCase/SendVaultInvite' -export * from './VaultInvite/VaultInviteService' -export * from './VaultInvite/VaultInviteServiceEvent' -export * from './VaultInvite/VaultInviteServiceInterface' -export * from './Vault/UseCase/ChangeVaultKeyOptionsDTO' +export * from './Vault/UseCase/ChangeVaultStorageMode' export * from './Vault/UseCase/ChangeVaultKeyOptions' +export * from './Vault/UseCase/ChangeVaultKeyOptionsDTO' export * from './Vault/UseCase/CreateVault' export * from './Vault/UseCase/DeleteVault' export * from './Vault/UseCase/GetVault' @@ -201,6 +194,16 @@ export * from './Vault/UseCase/RotateVaultKey' export * from './Vault/VaultService' export * from './Vault/VaultServiceEvent' export * from './Vault/VaultServiceInterface' +export * from './VaultInvite/InviteRecord' +export * from './VaultInvite/UseCase/AcceptVaultInvite' +export * from './VaultInvite/UseCase/InviteToVault' +export * from './VaultInvite/UseCase/ReuploadAllInvites' +export * from './VaultInvite/UseCase/ReuploadInvite' +export * from './VaultInvite/UseCase/ReuploadVaultInvites' +export * from './VaultInvite/UseCase/SendVaultInvite' +export * from './VaultInvite/VaultInviteService' +export * from './VaultInvite/VaultInviteServiceEvent' +export * from './VaultInvite/VaultInviteServiceInterface' export * from './VaultLock/VaultLockService' export * from './VaultLock/VaultLockServiceEvent' export * from './VaultLock/VaultLockServiceInterface' diff --git a/packages/snjs/lib/Application/Application.ts b/packages/snjs/lib/Application/Application.ts index 1fd93868e..9ddb17ed1 100644 --- a/packages/snjs/lib/Application/Application.ts +++ b/packages/snjs/lib/Application/Application.ts @@ -4,8 +4,8 @@ import { WebSocketsService } from './../Services/Api/WebsocketsService' import { MigrationService } from './../Services/Migration/MigrationService' import { LegacyApiService } from './../Services/Api/ApiService' import { FeaturesService } from '@Lib/Services/Features/FeaturesService' -import { SNPreferencesService } from './../Services/Preferences/PreferencesService' -import { SNProtectionService } from './../Services/Protection/ProtectionService' +import { PreferencesService } from './../Services/Preferences/PreferencesService' +import { ProtectionService } from './../Services/Protection/ProtectionService' import { SessionManager } from './../Services/Session/SessionManager' import { HttpService, HttpServiceInterface, UserRegistrationResponseBody } from '@standardnotes/api' import { ApplicationIdentifier, compareVersions, ProtocolVersion, KeyParamsOrigination } from '@standardnotes/common' @@ -32,7 +32,7 @@ import { FeaturesClientInterface, ItemManagerInterface, SyncServiceInterface, - UserClientInterface, + UserServiceInterface, MutatorClientInterface, StatusServiceInterface, AlertService, @@ -74,7 +74,6 @@ import { VaultUserServiceInterface, VaultInviteServiceInterface, NotificationServiceEvent, - VaultServiceEvent, VaultLockServiceInterface, } from '@standardnotes/services' import { @@ -297,7 +296,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli const uninstall = syncService.addEventObserver(syncEventCallback) this.serviceObservers.push(uninstall) - const protectionService = this.dependencies.get(TYPES.ProtectionService) + const protectionService = this.dependencies.get(TYPES.ProtectionService) this.serviceObservers.push( protectionService.addEventObserver((event) => { if (event === ProtectionEvent.UnprotectedSessionBegan) { @@ -329,7 +328,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli }), ) - const preferencesService = this.dependencies.get(TYPES.PreferencesService) + const preferencesService = this.dependencies.get(TYPES.PreferencesService) this.serviceObservers.push( preferencesService.addEventObserver(() => { void this.notifyEvent(ApplicationEvent.PreferencesChanged) @@ -1141,7 +1140,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli this.dependencies.get(TYPES.SharedVaultService), NotificationServiceEvent.NotificationReceived, ) - this.events.addEventHandler(this.dependencies.get(TYPES.SharedVaultService), VaultServiceEvent.VaultRootKeyRotated) this.events.addEventHandler(this.dependencies.get(TYPES.SharedVaultService), SyncEvent.ReceivedRemoteSharedVaults) this.events.addEventHandler( @@ -1267,8 +1265,8 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli return this.dependencies.get(TYPES.SyncService) } - public get user(): UserClientInterface { - return this.dependencies.get(TYPES.UserService) + public get user(): UserServiceInterface { + return this.dependencies.get(TYPES.UserService) } public get settings(): SettingsService { diff --git a/packages/snjs/lib/Application/Dependencies/Dependencies.ts b/packages/snjs/lib/Application/Dependencies/Dependencies.ts index 65ecce4b0..ca9789ed0 100644 --- a/packages/snjs/lib/Application/Dependencies/Dependencies.ts +++ b/packages/snjs/lib/Application/Dependencies/Dependencies.ts @@ -15,10 +15,10 @@ import { SNMfaService } from '../../Services/Mfa/MfaService' import { SNComponentManager } from '../../Services/ComponentManager/ComponentManager' import { FeaturesService } from '@Lib/Services/Features/FeaturesService' import { SettingsService } from '../../Services/Settings/SNSettingsService' -import { SNPreferencesService } from '../../Services/Preferences/PreferencesService' +import { PreferencesService } from '../../Services/Preferences/PreferencesService' import { SingletonManager } from '../../Services/Singleton/SingletonManager' import { KeyRecoveryService } from '../../Services/KeyRecovery/KeyRecoveryService' -import { SNProtectionService } from '../../Services/Protection/ProtectionService' +import { ProtectionService } from '../../Services/Protection/ProtectionService' import { SyncService } from '../../Services/Sync/SyncService' import { HistoryManager } from '../../Services/History/HistoryManager' import { SessionManager } from '../../Services/Session/SessionManager' @@ -120,6 +120,12 @@ import { VaultLockService, RemoveItemsFromMemory, ReencryptTypeAItems, + DecryptErroredPayloads, + GetKeyPairs, + DeviceInterface, + AlertService, + DesktopDeviceInterface, + ChangeVaultStorageMode, } from '@standardnotes/services' import { ItemManager } from '../../Services/Items/ItemManager' import { PayloadManager } from '../../Services/Payloads/PayloadManager' @@ -150,6 +156,8 @@ import { TYPES } from './Types' import { isDeinitable } from './isDeinitable' import { Logger, isNotUndefined } from '@standardnotes/utils' import { EncryptionOperators } from '@standardnotes/encryption' +import { AsymmetricMessagePayload, AsymmetricMessageSharedVaultInvite } from '@standardnotes/models' +import { PureCryptoInterface } from '@standardnotes/sncrypto-common' export class Dependencies { private factory = new Map unknown>() @@ -204,380 +212,431 @@ export class Dependencies { } private registerUseCaseMakers() { + this.factory.set(TYPES.DecryptErroredPayloads, () => { + return new DecryptErroredPayloads( + this.get(TYPES.ItemsEncryptionService), + this.get(TYPES.DecryptErroredTypeAPayloads), + ) + }) + + this.factory.set(TYPES.GetKeyPairs, () => { + return new GetKeyPairs(this.get(TYPES.RootKeyManager)) + }) + this.factory.set(TYPES.ReencryptTypeAItems, () => { - return new ReencryptTypeAItems(this.get(TYPES.ItemManager), this.get(TYPES.MutatorService)) + return new ReencryptTypeAItems( + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + ) }) this.factory.set(TYPES.ImportDataUseCase, () => { return new ImportDataUseCase( - this.get(TYPES.ItemManager), - this.get(TYPES.SyncService), - this.get(TYPES.ProtectionService), - this.get(TYPES.EncryptionService), - this.get(TYPES.PayloadManager), - this.get(TYPES.ChallengeService), - this.get(TYPES.HistoryManager), - this.get(TYPES.DecryptBackupFile), + this.get(TYPES.ItemManager), + this.get(TYPES.SyncService), + this.get(TYPES.ProtectionService), + this.get(TYPES.EncryptionService), + this.get(TYPES.PayloadManager), + this.get(TYPES.ChallengeService), + this.get(TYPES.HistoryManager), + this.get(TYPES.DecryptBackupFile), ) }) this.factory.set(TYPES.IsVaultOwner, () => { - return new IsVaultOwner() + return new IsVaultOwner(this.get(TYPES.UserService)) }) this.factory.set(TYPES.DecryptBackupFile, () => { - return new DecryptBackupFile(this.get(TYPES.EncryptionService), this.get(TYPES.Logger)) + return new DecryptBackupFile(this.get(TYPES.EncryptionService), this.get(TYPES.Logger)) }) this.factory.set(TYPES.DiscardItemsLocally, () => { - return new DiscardItemsLocally(this.get(TYPES.ItemManager), this.get(TYPES.DiskStorageService)) + return new DiscardItemsLocally( + this.get(TYPES.ItemManager), + this.get(TYPES.DiskStorageService), + ) }) this.factory.set(TYPES.RemoveItemsFromMemory, () => { return new RemoveItemsFromMemory( - this.get(TYPES.DiskStorageService), - this.get(TYPES.ItemManager), - this.get(TYPES.PayloadManager), + this.get(TYPES.DiskStorageService), + this.get(TYPES.ItemManager), + this.get(TYPES.PayloadManager), ) }) this.factory.set(TYPES.FindContact, () => { - return new FindContact(this.get(TYPES.ItemManager)) + return new FindContact(this.get(TYPES.ItemManager)) }) this.factory.set(TYPES.DeleteContact, () => { return new DeleteContact( - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.GetOwnedSharedVaults), - this.get(TYPES.ContactBelongsToVault), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.GetOwnedSharedVaults), + this.get(TYPES.ContactBelongsToVault), ) }) this.factory.set(TYPES.EditContact, () => { - return new EditContact(this.get(TYPES.MutatorService)) + return new EditContact(this.get(TYPES.MutatorService)) }) this.factory.set(TYPES.GetAllContacts, () => { - return new GetAllContacts(this.get(TYPES.ItemManager)) + return new GetAllContacts(this.get(TYPES.ItemManager)) }) this.factory.set(TYPES.ValidateItemSigner, () => { - return new ValidateItemSigner(this.get(TYPES.FindContact)) + return new ValidateItemSigner(this.get(TYPES.FindContact)) }) this.factory.set(TYPES.CreateOrEditContact, () => { return new CreateOrEditContact( - this.get(TYPES.MutatorService), - this.get(TYPES.FindContact), - this.get(TYPES.EditContact), + this.get(TYPES.MutatorService), + this.get(TYPES.FindContact), + this.get(TYPES.EditContact), ) }) this.factory.set(TYPES.GetVault, () => { - return new GetVault(this.get(TYPES.ItemManager)) + return new GetVault(this.get(TYPES.ItemManager)) }) this.factory.set(TYPES.GetVaults, () => { - return new GetVaults(this.get(TYPES.ItemManager)) + return new GetVaults(this.get(TYPES.ItemManager)) }) this.factory.set(TYPES.GetSharedVaults, () => { - return new GetSharedVaults(this.get(TYPES.GetVaults)) + return new GetSharedVaults(this.get(TYPES.GetVaults)) }) this.factory.set(TYPES.GetOwnedSharedVaults, () => { - return new GetOwnedSharedVaults(this.get(TYPES.GetSharedVaults), this.get(TYPES.IsVaultOwner)) + return new GetOwnedSharedVaults( + this.get(TYPES.GetSharedVaults), + this.get(TYPES.IsVaultOwner), + ) }) this.factory.set(TYPES.ContactBelongsToVault, () => { - return new ContactBelongsToVault(this.get(TYPES.GetVaultUsers)) + return new ContactBelongsToVault(this.get(TYPES.GetVaultUsers)) + }) + + this.factory.set(TYPES.ChangeVaultStorageMode, () => { + return new ChangeVaultStorageMode( + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.GetVault), + ) }) this.factory.set(TYPES.ChangeVaultKeyOptions, () => { return new ChangeVaultKeyOptions( - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.EncryptionService), - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.GetVault), + this.get(TYPES.SyncService), + this.get(TYPES.RotateVaultKey), + this.get(TYPES.ChangeVaultStorageMode), ) }) this.factory.set(TYPES.MoveItemsToVault, () => { return new MoveItemsToVault( - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.FileService), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.FileService), ) }) this.factory.set(TYPES.CreateVault, () => { return new CreateVault( - this.get(TYPES.MutatorService), - this.get(TYPES.EncryptionService), - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.SyncService), + this.get(TYPES.MutatorService), + this.get(TYPES.EncryptionService), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.SyncService), ) }) this.factory.set(TYPES.RemoveItemFromVault, () => { return new RemoveItemFromVault( - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.FileService), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.FileService), ) }) this.factory.set(TYPES.DeleteVault, () => { return new DeleteVault( - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.KeySystemKeyManager), ) }) this.factory.set(TYPES.RotateVaultKey, () => { return new RotateVaultKey( - this.get(TYPES.MutatorService), - this.get(TYPES.EncryptionService), - this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.MutatorService), + this.get(TYPES.EncryptionService), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.NotifyVaultUsersOfKeyRotation), + this.get(TYPES.IsVaultOwner), ) }) this.factory.set(TYPES.ReuploadInvite, () => { return new ReuploadInvite( - this.get(TYPES.DecryptOwnMessage), - this.get(TYPES.SendVaultInvite), - this.get(TYPES.EncryptMessage), + this.get>(TYPES.DecryptOwnMessage), + this.get(TYPES.SendVaultInvite), + this.get(TYPES.EncryptMessage), ) }) this.factory.set(TYPES.ReuploadAllInvites, () => { return new ReuploadAllInvites( - this.get(TYPES.ReuploadInvite), - this.get(TYPES.FindContact), - this.get(TYPES.SharedVaultInvitesServer), + this.get(TYPES.ReuploadInvite), + this.get(TYPES.FindContact), + this.get(TYPES.SharedVaultInvitesServer), ) }) this.factory.set(TYPES.ResendAllMessages, () => { return new ResendAllMessages( - this.get(TYPES.ResendMessage), - this.get(TYPES.DecryptOwnMessage), - this.get(TYPES.AsymmetricMessageServer), - this.get(TYPES.FindContact), + this.get(TYPES.ResendMessage), + this.get>(TYPES.DecryptOwnMessage), + this.get(TYPES.AsymmetricMessageServer), + this.get(TYPES.FindContact), ) }) this.factory.set(TYPES.CreateSharedVault, () => { return new CreateSharedVault( - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.SharedVaultServer), - this.get(TYPES.CreateVault), - this.get(TYPES.MoveItemsToVault), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.SharedVaultServer), + this.get(TYPES.CreateVault), + this.get(TYPES.MoveItemsToVault), ) }) this.factory.set(TYPES.HandleKeyPairChange, () => { return new HandleKeyPairChange( - this.get(TYPES.SelfContactManager), - this.get(TYPES.SharedVaultInvitesServer), - this.get(TYPES.AsymmetricMessageServer), - this.get(TYPES.ReuploadAllInvites), - this.get(TYPES.ResendAllMessages), - this.get(TYPES.GetAllContacts), - this.get(TYPES.SendOwnContactChangeMessage), - this.get(TYPES.CreateOrEditContact), - this.get(TYPES.Logger), + this.get(TYPES.SelfContactManager), + this.get(TYPES.SharedVaultInvitesServer), + this.get(TYPES.AsymmetricMessageServer), + this.get(TYPES.ReuploadAllInvites), + this.get(TYPES.ResendAllMessages), + this.get(TYPES.GetAllContacts), + this.get(TYPES.SendOwnContactChangeMessage), + this.get(TYPES.CreateOrEditContact), + this.get(TYPES.Logger), ) }) this.factory.set(TYPES.NotifyVaultUsersOfKeyRotation, () => { return new NotifyVaultUsersOfKeyRotation( - this.get(TYPES.FindContact), - this.get(TYPES.SendVaultKeyChangedMessage), - this.get(TYPES.InviteToVault), - this.get(TYPES.SharedVaultInvitesServer), - this.get(TYPES.GetVaultContacts), - this.get(TYPES.DecryptOwnMessage), + this.get(TYPES.FindContact), + this.get(TYPES.SendVaultKeyChangedMessage), + this.get(TYPES.InviteToVault), + this.get(TYPES.SharedVaultInvitesServer), + this.get(TYPES.GetVaultContacts), + this.get>(TYPES.DecryptOwnMessage), + this.get(TYPES.GetKeyPairs), ) }) this.factory.set(TYPES.SendVaultKeyChangedMessage, () => { return new SendVaultKeyChangedMessage( - this.get(TYPES.EncryptMessage), - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.FindContact), - this.get(TYPES.SendMessage), - this.get(TYPES.GetVaultUsers), + this.get(TYPES.UserService), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.EncryptMessage), + this.get(TYPES.FindContact), + this.get(TYPES.SendMessage), + this.get(TYPES.GetVaultUsers), + this.get(TYPES.GetKeyPairs), ) }) this.factory.set(TYPES.SendVaultDataChangedMessage, () => { return new SendVaultDataChangedMessage( - this.get(TYPES.EncryptMessage), - this.get(TYPES.FindContact), - this.get(TYPES.GetVaultUsers), - this.get(TYPES.SendMessage), + this.get(TYPES.UserService), + this.get(TYPES.EncryptMessage), + this.get(TYPES.FindContact), + this.get(TYPES.GetVaultUsers), + this.get(TYPES.SendMessage), + this.get(TYPES.IsVaultOwner), + this.get(TYPES.GetKeyPairs), ) }) this.factory.set(TYPES.ReplaceContactData, () => { return new ReplaceContactData( - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.FindContact), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.FindContact), ) }) this.factory.set(TYPES.GetTrustedPayload, () => { - return new GetTrustedPayload(this.get(TYPES.DecryptMessage)) + return new GetTrustedPayload(this.get(TYPES.DecryptMessage)) }) this.factory.set(TYPES.GetUntrustedPayload, () => { - return new GetUntrustedPayload(this.get(TYPES.DecryptMessage)) + return new GetUntrustedPayload(this.get(TYPES.DecryptMessage)) }) this.factory.set(TYPES.GetVaultContacts, () => { - return new GetVaultContacts(this.get(TYPES.FindContact), this.get(TYPES.GetVaultUsers)) + return new GetVaultContacts( + this.get(TYPES.FindContact), + this.get(TYPES.GetVaultUsers), + ) }) this.factory.set(TYPES.AcceptVaultInvite, () => { - return new AcceptVaultInvite(this.get(TYPES.SharedVaultInvitesServer), this.get(TYPES.ProcessAcceptedVaultInvite)) + return new AcceptVaultInvite( + this.get(TYPES.SharedVaultInvitesServer), + this.get(TYPES.ProcessAcceptedVaultInvite), + ) }) this.factory.set(TYPES.InviteToVault, () => { return new InviteToVault( - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.EncryptMessage), - this.get(TYPES.SendVaultInvite), - this.get(TYPES.ShareContactWithVault), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.EncryptMessage), + this.get(TYPES.SendVaultInvite), + this.get(TYPES.ShareContactWithVault), + this.get(TYPES.GetKeyPairs), ) }) this.factory.set(TYPES.SendVaultInvite, () => { - return new SendVaultInvite(this.get(TYPES.SharedVaultInvitesServer)) + return new SendVaultInvite(this.get(TYPES.SharedVaultInvitesServer)) }) this.factory.set(TYPES.DeleteThirdPartyVault, () => { return new DeleteThirdPartyVault( - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.SyncService), - this.get(TYPES.DiscardItemsLocally), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.SyncService), + this.get(TYPES.DiscardItemsLocally), ) }) this.factory.set(TYPES.LeaveVault, () => { return new LeaveVault( - this.get(TYPES.SharedVaultUsersServer), - this.get(TYPES.ItemManager), - this.get(TYPES.DeleteThirdPartyVault), + this.get(TYPES.UserService), + this.get(TYPES.SharedVaultUsersServer), + this.get(TYPES.ItemManager), + this.get(TYPES.DeleteThirdPartyVault), ) }) this.factory.set(TYPES.ShareContactWithVault, () => { return new ShareContactWithVault( - this.get(TYPES.FindContact), - this.get(TYPES.EncryptMessage), - this.get(TYPES.SendMessage), - this.get(TYPES.GetVaultUsers), + this.get(TYPES.UserService), + this.get(TYPES.FindContact), + this.get(TYPES.EncryptMessage), + this.get(TYPES.SendMessage), + this.get(TYPES.GetVaultUsers), + this.get(TYPES.GetKeyPairs), ) }) this.factory.set(TYPES.ConvertToSharedVault, () => { return new ConvertToSharedVault( - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.SharedVaultServer), - this.get(TYPES.MoveItemsToVault), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.SharedVaultServer), + this.get(TYPES.MoveItemsToVault), ) }) this.factory.set(TYPES.DeleteSharedVault, () => { return new DeleteSharedVault( - this.get(TYPES.SharedVaultServer), - this.get(TYPES.SyncService), - this.get(TYPES.DeleteVault), + this.get(TYPES.SharedVaultServer), + this.get(TYPES.SyncService), + this.get(TYPES.DeleteVault), ) }) this.factory.set(TYPES.RemoveVaultMember, () => { - return new RemoveVaultMember(this.get(TYPES.SharedVaultUsersServer)) + return new RemoveVaultMember(this.get(TYPES.SharedVaultUsersServer)) }) this.factory.set(TYPES.GetVaultUsers, () => { - return new GetVaultUsers(this.get(TYPES.SharedVaultUsersServer), this.get(TYPES.VaultUserCache)) + return new GetVaultUsers( + this.get(TYPES.SharedVaultUsersServer), + this.get(TYPES.VaultUserCache), + ) }) this.factory.set(TYPES.DecryptOwnMessage, () => { - return new DecryptOwnMessage(this.get(TYPES.EncryptionOperators)) + return new DecryptOwnMessage(this.get(TYPES.EncryptionOperators)) }) this.factory.set(TYPES.EncryptMessage, () => { - return new EncryptMessage(this.get(TYPES.EncryptionOperators)) + return new EncryptMessage(this.get(TYPES.EncryptionOperators)) }) this.factory.set(TYPES.DecryptMessage, () => { - return new DecryptMessage(this.get(TYPES.EncryptionOperators)) + return new DecryptMessage(this.get(TYPES.EncryptionOperators)) }) this.factory.set(TYPES.ResendMessage, () => { - return new ResendMessage(this.get(TYPES.SendMessage), this.get(TYPES.EncryptMessage)) + return new ResendMessage(this.get(TYPES.SendMessage), this.get(TYPES.EncryptMessage)) }) this.factory.set(TYPES.SendMessage, () => { - return new SendMessage(this.get(TYPES.AsymmetricMessageServer)) + return new SendMessage(this.get(TYPES.AsymmetricMessageServer)) }) this.factory.set(TYPES.ProcessAcceptedVaultInvite, () => { return new ProcessAcceptedVaultInvite( - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.CreateOrEditContact), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.CreateOrEditContact), ) }) this.factory.set(TYPES.HandleRootKeyChangedMessage, () => { return new HandleRootKeyChangedMessage( - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.EncryptionService), - this.get(TYPES.GetVault), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.GetVault), + this.get(TYPES.DecryptErroredPayloads), ) }) this.factory.set(TYPES.SendOwnContactChangeMessage, () => { - return new SendOwnContactChangeMessage(this.get(TYPES.EncryptMessage), this.get(TYPES.SendMessage)) + return new SendOwnContactChangeMessage( + this.get(TYPES.EncryptMessage), + this.get(TYPES.SendMessage), + ) }) this.factory.set(TYPES.GetOutboundMessages, () => { - return new GetOutboundMessages(this.get(TYPES.AsymmetricMessageServer)) + return new GetOutboundMessages(this.get(TYPES.AsymmetricMessageServer)) }) this.factory.set(TYPES.GetInboundMessages, () => { - return new GetInboundMessages(this.get(TYPES.AsymmetricMessageServer)) + return new GetInboundMessages(this.get(TYPES.AsymmetricMessageServer)) }) this.factory.set(TYPES.CreateNewDefaultItemsKey, () => { return new CreateNewDefaultItemsKey( - this.get(TYPES.MutatorService), - this.get(TYPES.ItemManager), - this.get(TYPES.EncryptionOperators), - this.get(TYPES.RootKeyManager), + this.get(TYPES.MutatorService), + this.get(TYPES.ItemManager), + this.get(TYPES.EncryptionOperators), + this.get(TYPES.RootKeyManager), ) }) this.factory.set(TYPES.CreateNewItemsKeyWithRollback, () => { return new CreateNewItemsKeyWithRollback( - this.get(TYPES.MutatorService), - this.get(TYPES.ItemManager), - this.get(TYPES.CreateNewDefaultItemsKey), - this.get(TYPES.DiscardItemsLocally), - this.get(TYPES.FindDefaultItemsKey), + this.get(TYPES.MutatorService), + this.get(TYPES.ItemManager), + this.get(TYPES.CreateNewDefaultItemsKey), + this.get(TYPES.DiscardItemsLocally), + this.get(TYPES.FindDefaultItemsKey), ) }) @@ -587,34 +646,34 @@ export class Dependencies { this.factory.set(TYPES.DecryptErroredTypeAPayloads, () => { return new DecryptErroredTypeAPayloads( - this.get(TYPES.PayloadManager), - this.get(TYPES.EncryptionOperators), - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.RootKeyManager), + this.get(TYPES.PayloadManager), + this.get(TYPES.EncryptionOperators), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.RootKeyManager), ) }) this.factory.set(TYPES.DecryptTypeAPayload, () => { - return new DecryptTypeAPayload(this.get(TYPES.EncryptionOperators)) + return new DecryptTypeAPayload(this.get(TYPES.EncryptionOperators)) }) this.factory.set(TYPES.DecryptTypeAPayloadWithKeyLookup, () => { return new DecryptTypeAPayloadWithKeyLookup( - this.get(TYPES.EncryptionOperators), - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.RootKeyManager), + this.get(TYPES.EncryptionOperators), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.RootKeyManager), ) }) this.factory.set(TYPES.EncryptTypeAPayload, () => { - return new EncryptTypeAPayload(this.get(TYPES.EncryptionOperators)) + return new EncryptTypeAPayload(this.get(TYPES.EncryptionOperators)) }) this.factory.set(TYPES.EncryptTypeAPayloadWithKeyLookup, () => { return new EncryptTypeAPayloadWithKeyLookup( - this.get(TYPES.EncryptionOperators), - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.RootKeyManager), + this.get(TYPES.EncryptionOperators), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.RootKeyManager), ) }) } @@ -625,63 +684,62 @@ export class Dependencies { }) this.factory.set(TYPES.UserServer, () => { - return new UserServer(this.get(TYPES.HttpService)) + return new UserServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.RootKeyManager, () => { return new RootKeyManager( - this.get(TYPES.DeviceInterface), - this.get(TYPES.DiskStorageService), - this.get(TYPES.EncryptionOperators), + this.get(TYPES.DeviceInterface), + this.get(TYPES.DiskStorageService), + this.get(TYPES.EncryptionOperators), this.options.identifier, - this.get(TYPES.ReencryptTypeAItems), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ReencryptTypeAItems), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.ItemsEncryptionService, () => { return new ItemsEncryptionService( - this.get(TYPES.ItemManager), - this.get(TYPES.PayloadManager), - this.get(TYPES.DiskStorageService), - this.get(TYPES.EncryptionOperators), - this.get(TYPES.KeySystemKeyManager), - this.get(TYPES.FindDefaultItemsKey), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.PayloadManager), + this.get(TYPES.DiskStorageService), + this.get(TYPES.EncryptionOperators), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.FindDefaultItemsKey), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.EncryptionOperators, () => { - return new EncryptionOperators(this.get(TYPES.Crypto)) + return new EncryptionOperators(this.get(TYPES.Crypto)) }) this.factory.set(TYPES.SharedVaultInvitesServer, () => { - return new SharedVaultInvitesServer(this.get(TYPES.HttpService)) + return new SharedVaultInvitesServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.SharedVaultServer, () => { - return new SharedVaultServer(this.get(TYPES.HttpService)) + return new SharedVaultServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.AsymmetricMessageServer, () => { - return new AsymmetricMessageServer(this.get(TYPES.HttpService)) + return new AsymmetricMessageServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.SharedVaultUsersServer, () => { - return new SharedVaultUsersServer(this.get(TYPES.HttpService)) + return new SharedVaultUsersServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.VaultUserService, () => { 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), - this.get(TYPES.GetVault), - this.get(TYPES.LeaveVault), - this.get(TYPES.InternalEventBus), + this.get(TYPES.VaultService), + this.get(TYPES.VaultLockService), + this.get(TYPES.GetVaultUsers), + this.get(TYPES.RemoveVaultMember), + this.get(TYPES.IsVaultOwner), + this.get(TYPES.GetVault), + this.get(TYPES.LeaveVault), + this.get(TYPES.InternalEventBus), ) }) @@ -691,521 +749,541 @@ export class Dependencies { this.factory.set(TYPES.VaultInviteService, () => { return new VaultInviteService( - this.get(TYPES.ItemManager), - this.get(TYPES.SessionManager), - this.get(TYPES.VaultUserService), - this.get(TYPES.SyncService), - this.get(TYPES.EncryptionService), - this.get(TYPES.SharedVaultInvitesServer), - this.get(TYPES.GetAllContacts), - this.get(TYPES.GetVault), - this.get(TYPES.GetVaultContacts), - this.get(TYPES.InviteToVault), - this.get(TYPES.GetTrustedPayload), - this.get(TYPES.GetUntrustedPayload), - this.get(TYPES.FindContact), - this.get(TYPES.AcceptVaultInvite), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.SessionManager), + this.get(TYPES.VaultUserService), + this.get(TYPES.SyncService), + this.get(TYPES.SharedVaultInvitesServer), + this.get(TYPES.GetAllContacts), + this.get(TYPES.GetVault), + this.get(TYPES.GetVaultContacts), + this.get(TYPES.InviteToVault), + this.get(TYPES.GetTrustedPayload), + this.get(TYPES.GetUntrustedPayload), + this.get(TYPES.FindContact), + this.get(TYPES.AcceptVaultInvite), + this.get(TYPES.GetKeyPairs), + this.get(TYPES.DecryptErroredPayloads), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.AsymmetricMessageService, () => { return new AsymmetricMessageService( - this.get(TYPES.EncryptionService), - this.get(TYPES.MutatorService), - this.get(TYPES.SessionManager), - this.get(TYPES.SyncService), - this.get(TYPES.AsymmetricMessageServer), - this.get(TYPES.CreateOrEditContact), - this.get(TYPES.FindContact), - this.get(TYPES.ReplaceContactData), - this.get(TYPES.GetTrustedPayload), - this.get(TYPES.GetVault), - this.get(TYPES.HandleRootKeyChangedMessage), - this.get(TYPES.GetOutboundMessages), - this.get(TYPES.GetInboundMessages), - this.get(TYPES.GetUntrustedPayload), - this.get(TYPES.InternalEventBus), + this.get(TYPES.EncryptionService), + this.get(TYPES.MutatorService), + this.get(TYPES.SessionManager), + this.get(TYPES.SyncService), + this.get(TYPES.AsymmetricMessageServer), + this.get(TYPES.CreateOrEditContact), + this.get(TYPES.FindContact), + this.get(TYPES.ReplaceContactData), + this.get(TYPES.GetTrustedPayload), + this.get(TYPES.GetVault), + this.get(TYPES.HandleRootKeyChangedMessage), + this.get(TYPES.GetOutboundMessages), + this.get(TYPES.GetInboundMessages), + this.get(TYPES.GetUntrustedPayload), + this.get(TYPES.GetKeyPairs), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.SharedVaultService, () => { return new SharedVaultService( - this.get(TYPES.ItemManager), - this.get(TYPES.EncryptionService), - this.get(TYPES.SessionManager), - this.get(TYPES.GetVault), - this.get(TYPES.GetOwnedSharedVaults), - this.get(TYPES.CreateSharedVault), - this.get(TYPES.HandleKeyPairChange), - this.get(TYPES.NotifyVaultUsersOfKeyRotation), - this.get(TYPES.SendVaultDataChangedMessage), - this.get(TYPES.FindContact), - this.get(TYPES.DeleteThirdPartyVault), - this.get(TYPES.ShareContactWithVault), - this.get(TYPES.ConvertToSharedVault), - this.get(TYPES.DeleteSharedVault), - this.get(TYPES.IsVaultOwner), - this.get(TYPES.DiscardItemsLocally), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.SessionManager), + this.get(TYPES.GetVault), + this.get(TYPES.GetOwnedSharedVaults), + this.get(TYPES.CreateSharedVault), + this.get(TYPES.HandleKeyPairChange), + this.get(TYPES.FindContact), + this.get(TYPES.DeleteThirdPartyVault), + this.get(TYPES.ShareContactWithVault), + this.get(TYPES.ConvertToSharedVault), + this.get(TYPES.DeleteSharedVault), + this.get(TYPES.DiscardItemsLocally), + this.get(TYPES.InternalEventBus), ) }) 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.get(TYPES.ItemManager), + this.get(TYPES.EncryptionService), + this.get(TYPES.KeySystemKeyManager), + this.get(TYPES.GetVaults), + this.get(TYPES.DecryptErroredPayloads), + 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.VaultLockService), - this.get(TYPES.AlertService), - this.get(TYPES.GetVault), - this.get(TYPES.GetVaults), - this.get(TYPES.ChangeVaultKeyOptions), - this.get(TYPES.MoveItemsToVault), - this.get(TYPES.CreateVault), - this.get(TYPES.RemoveItemFromVault), - this.get(TYPES.DeleteVault), - this.get(TYPES.RotateVaultKey), - this.get(TYPES.InternalEventBus), + this.get(TYPES.SyncService), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.VaultLockService), + this.get(TYPES.AlertService), + this.get(TYPES.GetVault), + this.get(TYPES.GetVaults), + this.get(TYPES.ChangeVaultKeyOptions), + this.get(TYPES.MoveItemsToVault), + this.get(TYPES.CreateVault), + this.get(TYPES.RemoveItemFromVault), + this.get(TYPES.DeleteVault), + this.get(TYPES.RotateVaultKey), + this.get(TYPES.SendVaultDataChangedMessage), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.SelfContactManager, () => { return new SelfContactManager( - this.get(TYPES.SyncService), - this.get(TYPES.ItemManager), - this.get(TYPES.SessionManager), - this.get(TYPES.SingletonManager), + this.get(TYPES.SyncService), + this.get(TYPES.ItemManager), + this.get(TYPES.SessionManager), + this.get(TYPES.SingletonManager), ) }) this.factory.set(TYPES.ContactService, () => { return new ContactService( - this.get(TYPES.SyncService), - this.get(TYPES.MutatorService), - this.get(TYPES.SessionManager), - this.get(TYPES.Crypto), - this.get(TYPES.UserService), - this.get(TYPES.SelfContactManager), - this.get(TYPES.EncryptionService), - this.get(TYPES.DeleteContact), - this.get(TYPES.FindContact), - this.get(TYPES.GetAllContacts), - this.get(TYPES.CreateOrEditContact), - this.get(TYPES.EditContact), - this.get(TYPES.ValidateItemSigner), - this.get(TYPES.InternalEventBus), + this.get(TYPES.SyncService), + this.get(TYPES.MutatorService), + this.get(TYPES.SessionManager), + this.get(TYPES.Crypto), + this.get(TYPES.UserService), + this.get(TYPES.SelfContactManager), + this.get(TYPES.EncryptionService), + this.get(TYPES.DeleteContact), + this.get(TYPES.FindContact), + this.get(TYPES.GetAllContacts), + this.get(TYPES.CreateOrEditContact), + this.get(TYPES.EditContact), + this.get(TYPES.ValidateItemSigner), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.SignInWithRecoveryCodes, () => { return new SignInWithRecoveryCodes( - this.get(TYPES.AuthManager), - this.get(TYPES.EncryptionService), - this.get(TYPES.InMemoryStore), - this.get(TYPES.Crypto), - this.get(TYPES.SessionManager), - this.get(TYPES.InternalEventBus), + this.get(TYPES.AuthManager), + this.get(TYPES.EncryptionService), + this.get(TYPES.InMemoryStore), + this.get(TYPES.Crypto), + this.get(TYPES.SessionManager), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.GetRecoveryCodes, () => { - return new GetRecoveryCodes(this.get(TYPES.AuthManager), this.get(TYPES.SettingsService)) + return new GetRecoveryCodes( + this.get(TYPES.AuthManager), + this.get(TYPES.SettingsService), + ) }) this.factory.set(TYPES.AddAuthenticator, () => { return new AddAuthenticator( - this.get(TYPES.AuthenticatorManager), + this.get(TYPES.AuthenticatorManager), this.options.u2fAuthenticatorRegistrationPromptFunction, ) }) this.factory.set(TYPES.ListAuthenticators, () => { - return new ListAuthenticators(this.get(TYPES.AuthenticatorManager)) + return new ListAuthenticators(this.get(TYPES.AuthenticatorManager)) }) this.factory.set(TYPES.DeleteAuthenticator, () => { - return new DeleteAuthenticator(this.get(TYPES.AuthenticatorManager)) + return new DeleteAuthenticator(this.get(TYPES.AuthenticatorManager)) }) this.factory.set(TYPES.GetAuthenticatorAuthenticationOptions, () => { - return new GetAuthenticatorAuthenticationOptions(this.get(TYPES.AuthenticatorManager)) + return new GetAuthenticatorAuthenticationOptions(this.get(TYPES.AuthenticatorManager)) }) this.factory.set(TYPES.GetAuthenticatorAuthenticationResponse, () => { return new GetAuthenticatorAuthenticationResponse( - this.get(TYPES.GetAuthenticatorAuthenticationOptions), + this.get(TYPES.GetAuthenticatorAuthenticationOptions), this.options.u2fAuthenticatorVerificationPromptFunction, ) }) this.factory.set(TYPES.ListRevisions, () => { - return new ListRevisions(this.get(TYPES.RevisionManager)) + return new ListRevisions(this.get(TYPES.RevisionManager)) }) this.factory.set(TYPES.GetRevision, () => { - return new GetRevision(this.get(TYPES.RevisionManager), this.get(TYPES.EncryptionService)) + return new GetRevision( + this.get(TYPES.RevisionManager), + this.get(TYPES.EncryptionService), + ) }) this.factory.set(TYPES.DeleteRevision, () => { - return new DeleteRevision(this.get(TYPES.RevisionManager)) + return new DeleteRevision(this.get(TYPES.RevisionManager)) }) this.factory.set(TYPES.RevisionServer, () => { - return new RevisionServer(this.get(TYPES.HttpService)) + return new RevisionServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.RevisionApiService, () => { - return new RevisionApiService(this.get(TYPES.RevisionServer)) + return new RevisionApiService(this.get(TYPES.RevisionServer)) }) this.factory.set(TYPES.RevisionManager, () => { - return new RevisionManager(this.get(TYPES.RevisionApiService), this.get(TYPES.InternalEventBus)) + return new RevisionManager( + this.get(TYPES.RevisionApiService), + this.get(TYPES.InternalEventBus), + ) }) this.factory.set(TYPES.AuthServer, () => { - return new AuthServer(this.get(TYPES.HttpService)) + return new AuthServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.AuthApiService, () => { - return new AuthApiService(this.get(TYPES.AuthServer)) + return new AuthApiService(this.get(TYPES.AuthServer)) }) this.factory.set(TYPES.AuthManager, () => { - return new AuthManager(this.get(TYPES.AuthApiService), this.get(TYPES.InternalEventBus)) + return new AuthManager( + this.get(TYPES.AuthApiService), + this.get(TYPES.InternalEventBus), + ) }) this.factory.set(TYPES.AuthenticatorServer, () => { - return new AuthenticatorServer(this.get(TYPES.HttpService)) + return new AuthenticatorServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.AuthenticatorApiService, () => { - return new AuthenticatorApiService(this.get(TYPES.AuthenticatorServer)) + return new AuthenticatorApiService(this.get(TYPES.AuthenticatorServer)) }) this.factory.set(TYPES.AuthenticatorManager, () => { return new AuthenticatorManager( - this.get(TYPES.AuthenticatorApiService), - this.get(TYPES.PreferencesService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.AuthenticatorApiService), + this.get(TYPES.PreferencesService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.ActionsService, () => { return new ActionsService( - this.get(TYPES.ItemManager), - this.get(TYPES.AlertService), - this.get(TYPES.DeviceInterface), - this.get(TYPES.DeprecatedHttpService), - this.get(TYPES.EncryptionService), - this.get(TYPES.ChallengeService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.AlertService), + this.get(TYPES.DeviceInterface), + this.get(TYPES.DeprecatedHttpService), + this.get(TYPES.EncryptionService), + this.get(TYPES.ChallengeService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.ListedService, () => { return new ListedService( - this.get(TYPES.LegacyApiService), - this.get(TYPES.ItemManager), - this.get(TYPES.SettingsService), - this.get(TYPES.DeprecatedHttpService), - this.get(TYPES.ProtectionService), - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.LegacyApiService), + this.get(TYPES.ItemManager), + this.get(TYPES.SettingsService), + this.get(TYPES.DeprecatedHttpService), + this.get(TYPES.ProtectionService), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.IntegrityService, () => { return new IntegrityService( - this.get(TYPES.LegacyApiService), - this.get(TYPES.LegacyApiService), - this.get(TYPES.PayloadManager), - this.get(TYPES.Logger), - this.get(TYPES.InternalEventBus), + this.get(TYPES.LegacyApiService), + this.get(TYPES.LegacyApiService), + this.get(TYPES.PayloadManager), + this.get(TYPES.Logger), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.FileService, () => { return new FileService( - this.get(TYPES.LegacyApiService), - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.EncryptionService), - this.get(TYPES.ChallengeService), - this.get(TYPES.HttpService), - this.get(TYPES.AlertService), - this.get(TYPES.Crypto), - this.get(TYPES.InternalEventBus), - this.get(TYPES.Logger), - this.get(TYPES.FilesBackupService), + this.get(TYPES.LegacyApiService), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.EncryptionService), + this.get(TYPES.ChallengeService), + this.get(TYPES.HttpService), + this.get(TYPES.AlertService), + this.get(TYPES.Crypto), + this.get(TYPES.InternalEventBus), + this.get(TYPES.Logger), + this.get(TYPES.FilesBackupService), ) }) this.factory.set(TYPES.MigrationService, () => { return new MigrationService({ - encryptionService: this.get(TYPES.EncryptionService), - deviceInterface: this.get(TYPES.DeviceInterface), - storageService: this.get(TYPES.DiskStorageService), - sessionManager: this.get(TYPES.SessionManager), - challengeService: this.get(TYPES.ChallengeService), - itemManager: this.get(TYPES.ItemManager), - mutator: this.get(TYPES.MutatorService), - singletonManager: this.get(TYPES.SingletonManager), - featuresService: this.get(TYPES.FeaturesService), + encryptionService: this.get(TYPES.EncryptionService), + deviceInterface: this.get(TYPES.DeviceInterface), + storageService: this.get(TYPES.DiskStorageService), + sessionManager: this.get(TYPES.SessionManager), + challengeService: this.get(TYPES.ChallengeService), + itemManager: this.get(TYPES.ItemManager), + mutator: this.get(TYPES.MutatorService), + singletonManager: this.get(TYPES.SingletonManager), + featuresService: this.get(TYPES.FeaturesService), environment: this.options.environment, platform: this.options.platform, identifier: this.options.identifier, - internalEventBus: this.get(TYPES.InternalEventBus), - legacySessionStorageMapper: this.get(TYPES.LegacySessionStorageMapper), - backups: this.get(TYPES.FilesBackupService), - preferences: this.get(TYPES.PreferencesService), + internalEventBus: this.get(TYPES.InternalEventBus), + legacySessionStorageMapper: this.get(TYPES.LegacySessionStorageMapper), + backups: this.get(TYPES.FilesBackupService), + preferences: this.get(TYPES.PreferencesService), }) }) this.factory.set(TYPES.HomeServerService, () => { - if (!isDesktopDevice(this.get(TYPES.DeviceInterface))) { + if (!isDesktopDevice(this.get(TYPES.DeviceInterface))) { return undefined } - return new HomeServerService(this.get(TYPES.DeviceInterface), this.get(TYPES.InternalEventBus)) + return new HomeServerService( + this.get(TYPES.DeviceInterface), + this.get(TYPES.InternalEventBus), + ) }) this.factory.set(TYPES.FilesBackupService, () => { - if (!isDesktopDevice(this.get(TYPES.DeviceInterface))) { + if (!isDesktopDevice(this.get(TYPES.DeviceInterface))) { return undefined } return new FilesBackupService( - this.get(TYPES.ItemManager), - this.get(TYPES.LegacyApiService), - this.get(TYPES.EncryptionService), - this.get(TYPES.DeviceInterface), - this.get(TYPES.StatusService), - this.get(TYPES.Crypto), - this.get(TYPES.DiskStorageService), - this.get(TYPES.SessionManager), - this.get(TYPES.PayloadManager), - this.get(TYPES.HistoryManager), - this.get(TYPES.DeviceInterface), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.LegacyApiService), + this.get(TYPES.EncryptionService), + this.get(TYPES.DeviceInterface), + this.get(TYPES.StatusService), + this.get(TYPES.Crypto), + this.get(TYPES.DiskStorageService), + this.get(TYPES.SessionManager), + this.get(TYPES.PayloadManager), + this.get(TYPES.HistoryManager), + this.get(TYPES.DeviceInterface), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.StatusService, () => { - return new StatusService(this.get(TYPES.InternalEventBus)) + return new StatusService(this.get(TYPES.InternalEventBus)) }) this.factory.set(TYPES.MfaService, () => { return new SNMfaService( - this.get(TYPES.SettingsService), - this.get(TYPES.Crypto), - this.get(TYPES.FeaturesService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.SettingsService), + this.get(TYPES.Crypto), + this.get(TYPES.FeaturesService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.ComponentManager, () => { return new SNComponentManager( - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.FeaturesService), - this.get(TYPES.PreferencesService), - this.get(TYPES.AlertService), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.FeaturesService), + this.get(TYPES.PreferencesService), + this.get(TYPES.AlertService), this.options.environment, this.options.platform, - this.get(TYPES.DeviceInterface), - this.get(TYPES.Logger), - this.get(TYPES.InternalEventBus), + this.get(TYPES.DeviceInterface), + this.get(TYPES.Logger), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.FeaturesService, () => { return new FeaturesService( - this.get(TYPES.DiskStorageService), - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.SubscriptionManager), - this.get(TYPES.LegacyApiService), - this.get(TYPES.WebSocketsService), - this.get(TYPES.SettingsService), - this.get(TYPES.UserService), - this.get(TYPES.SyncService), - this.get(TYPES.AlertService), - this.get(TYPES.SessionManager), - this.get(TYPES.Crypto), - this.get(TYPES.Logger), - this.get(TYPES.InternalEventBus), + this.get(TYPES.DiskStorageService), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.SubscriptionManager), + this.get(TYPES.LegacyApiService), + this.get(TYPES.WebSocketsService), + this.get(TYPES.SettingsService), + this.get(TYPES.UserService), + this.get(TYPES.SyncService), + this.get(TYPES.AlertService), + this.get(TYPES.SessionManager), + this.get(TYPES.Crypto), + this.get(TYPES.Logger), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.SettingsService, () => { return new SettingsService( - this.get(TYPES.SessionManager), - this.get(TYPES.LegacyApiService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.SessionManager), + this.get(TYPES.LegacyApiService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.PreferencesService, () => { - return new SNPreferencesService( - this.get(TYPES.SingletonManager), - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.SyncService), - this.get(TYPES.InternalEventBus), + return new PreferencesService( + this.get(TYPES.SingletonManager), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.SyncService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.SingletonManager, () => { return new SingletonManager( - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.PayloadManager), - this.get(TYPES.SyncService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.PayloadManager), + this.get(TYPES.SyncService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.KeyRecoveryService, () => { return new KeyRecoveryService( - this.get(TYPES.ItemManager), - this.get(TYPES.PayloadManager), - this.get(TYPES.LegacyApiService), - this.get(TYPES.EncryptionService), - this.get(TYPES.ChallengeService), - this.get(TYPES.AlertService), - this.get(TYPES.DiskStorageService), - this.get(TYPES.SyncService), - this.get(TYPES.UserService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.PayloadManager), + this.get(TYPES.LegacyApiService), + this.get(TYPES.EncryptionService), + this.get(TYPES.ChallengeService), + this.get(TYPES.AlertService), + this.get(TYPES.DiskStorageService), + this.get(TYPES.SyncService), + this.get(TYPES.UserService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.UserService, () => { return new UserService( - this.get(TYPES.SessionManager), - this.get(TYPES.SyncService), - this.get(TYPES.DiskStorageService), - this.get(TYPES.ItemManager), - this.get(TYPES.EncryptionService), - this.get(TYPES.AlertService), - this.get(TYPES.ChallengeService), - this.get(TYPES.ProtectionService), - this.get(TYPES.UserApiService), - this.get(TYPES.ReencryptTypeAItems), - this.get(TYPES.InternalEventBus), + this.get(TYPES.SessionManager), + this.get(TYPES.SyncService), + this.get(TYPES.DiskStorageService), + this.get(TYPES.ItemManager), + this.get(TYPES.EncryptionService), + this.get(TYPES.AlertService), + this.get(TYPES.ChallengeService), + this.get(TYPES.ProtectionService), + this.get(TYPES.UserApiService), + this.get(TYPES.ReencryptTypeAItems), + this.get(TYPES.DecryptErroredPayloads), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.ProtectionService, () => { - return new SNProtectionService( - this.get(TYPES.EncryptionService), - this.get(TYPES.MutatorService), - this.get(TYPES.ChallengeService), - this.get(TYPES.DiskStorageService), - this.get(TYPES.InternalEventBus), + return new ProtectionService( + this.get(TYPES.EncryptionService), + this.get(TYPES.MutatorService), + this.get(TYPES.ChallengeService), + this.get(TYPES.DiskStorageService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.SyncService, () => { return new SyncService( - this.get(TYPES.ItemManager), - this.get(TYPES.SessionManager), - this.get(TYPES.EncryptionService), - this.get(TYPES.DiskStorageService), - this.get(TYPES.PayloadManager), - this.get(TYPES.LegacyApiService), - this.get(TYPES.HistoryManager), - this.get(TYPES.DeviceInterface), + this.get(TYPES.ItemManager), + this.get(TYPES.SessionManager), + this.get(TYPES.EncryptionService), + this.get(TYPES.DiskStorageService), + this.get(TYPES.PayloadManager), + this.get(TYPES.LegacyApiService), + this.get(TYPES.HistoryManager), + this.get(TYPES.DeviceInterface), this.options.identifier, { loadBatchSize: this.options.loadBatchSize, sleepBetweenBatches: this.options.sleepBetweenBatches, }, - this.get(TYPES.Logger), - this.get(TYPES.InternalEventBus), + this.get(TYPES.Logger), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.HistoryManager, () => { return new HistoryManager( - this.get(TYPES.ItemManager), - this.get(TYPES.DiskStorageService), - this.get(TYPES.DeviceInterface), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.DiskStorageService), + this.get(TYPES.DeviceInterface), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.SubscriptionManager, () => { return new SubscriptionManager( - this.get(TYPES.SubscriptionApiService), - this.get(TYPES.SessionManager), - this.get(TYPES.DiskStorageService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.SubscriptionApiService), + this.get(TYPES.SessionManager), + this.get(TYPES.DiskStorageService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.SessionManager, () => { return new SessionManager( - this.get(TYPES.DiskStorageService), - this.get(TYPES.LegacyApiService), - this.get(TYPES.UserApiService), - this.get(TYPES.AlertService), - this.get(TYPES.EncryptionService), - this.get(TYPES.Crypto), - this.get(TYPES.ChallengeService), - this.get(TYPES.WebSocketsService), - this.get(TYPES.HttpService), - this.get(TYPES.SessionStorageMapper), - this.get(TYPES.LegacySessionStorageMapper), + this.get(TYPES.DiskStorageService), + this.get(TYPES.LegacyApiService), + this.get(TYPES.UserApiService), + this.get(TYPES.AlertService), + this.get(TYPES.EncryptionService), + this.get(TYPES.Crypto), + this.get(TYPES.ChallengeService), + this.get(TYPES.WebSocketsService), + this.get(TYPES.HttpService), + this.get(TYPES.SessionStorageMapper), + this.get(TYPES.LegacySessionStorageMapper), this.options.identifier, - this.get(TYPES.InternalEventBus), + this.get(TYPES.GetKeyPairs), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.WebSocketsService, () => { return new WebSocketsService( - this.get(TYPES.DiskStorageService), + this.get(TYPES.DiskStorageService), this.options.webSocketUrl, - this.get(TYPES.WebSocketApiService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.WebSocketApiService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.WebSocketApiService, () => { - return new WebSocketApiService(this.get(TYPES.WebSocketServer)) + return new WebSocketApiService(this.get(TYPES.WebSocketServer)) }) this.factory.set(TYPES.WebSocketServer, () => { - return new WebSocketServer(this.get(TYPES.HttpService)) + return new WebSocketServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.SubscriptionApiService, () => { - return new SubscriptionApiService(this.get(TYPES.SubscriptionServer)) + return new SubscriptionApiService(this.get(TYPES.SubscriptionServer)) }) this.factory.set(TYPES.UserApiService, () => { - return new UserApiService(this.get(TYPES.UserServer), this.get(TYPES.UserRequestServer)) + return new UserApiService( + this.get(TYPES.UserServer), + this.get(TYPES.UserRequestServer), + ) }) this.factory.set(TYPES.SubscriptionServer, () => { - return new SubscriptionServer(this.get(TYPES.HttpService)) + return new SubscriptionServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.UserRequestServer, () => { - return new UserRequestServer(this.get(TYPES.HttpService)) + return new UserRequestServer(this.get(TYPES.HttpService)) }) this.factory.set(TYPES.InternalEventBus, () => { @@ -1213,32 +1291,35 @@ export class Dependencies { }) this.factory.set(TYPES.PayloadManager, () => { - return new PayloadManager(this.get(TYPES.Logger), this.get(TYPES.InternalEventBus)) + return new PayloadManager(this.get(TYPES.Logger), this.get(TYPES.InternalEventBus)) }) this.factory.set(TYPES.ItemManager, () => { - return new ItemManager(this.get(TYPES.PayloadManager), this.get(TYPES.InternalEventBus)) + return new ItemManager( + this.get(TYPES.PayloadManager), + this.get(TYPES.InternalEventBus), + ) }) this.factory.set(TYPES.MutatorService, () => { return new MutatorService( - this.get(TYPES.ItemManager), - this.get(TYPES.PayloadManager), - this.get(TYPES.AlertService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.PayloadManager), + this.get(TYPES.AlertService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.DiskStorageService, () => { return new DiskStorageService( - this.get(TYPES.DeviceInterface), + this.get(TYPES.DeviceInterface), this.options.identifier, - this.get(TYPES.InternalEventBus), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.NotificationService, () => { - return new NotificationService(this.get(TYPES.InternalEventBus)) + return new NotificationService(this.get(TYPES.InternalEventBus)) }) this.factory.set(TYPES.InMemoryStore, () => { @@ -1247,40 +1328,40 @@ export class Dependencies { this.factory.set(TYPES.KeySystemKeyManager, () => { return new KeySystemKeyManager( - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.DiskStorageService), - this.get(TYPES.RemoveItemsFromMemory), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.DiskStorageService), + this.get(TYPES.RemoveItemsFromMemory), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.ChallengeService, () => { return new ChallengeService( - this.get(TYPES.DiskStorageService), - this.get(TYPES.EncryptionService), - this.get(TYPES.InternalEventBus), + this.get(TYPES.DiskStorageService), + this.get(TYPES.EncryptionService), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.EncryptionService, () => { return new EncryptionService( - this.get(TYPES.ItemManager), - this.get(TYPES.MutatorService), - this.get(TYPES.PayloadManager), - this.get(TYPES.EncryptionOperators), - this.get(TYPES.ItemsEncryptionService), - this.get(TYPES.RootKeyManager), - this.get(TYPES.Crypto), - this.get(TYPES.CreateNewItemsKeyWithRollback), - this.get(TYPES.FindDefaultItemsKey), - this.get(TYPES.DecryptErroredTypeAPayloads), - this.get(TYPES.EncryptTypeAPayloadWithKeyLookup), - this.get(TYPES.EncryptTypeAPayload), - this.get(TYPES.DecryptTypeAPayload), - this.get(TYPES.DecryptTypeAPayloadWithKeyLookup), - this.get(TYPES.CreateNewDefaultItemsKey), - this.get(TYPES.InternalEventBus), + this.get(TYPES.ItemManager), + this.get(TYPES.MutatorService), + this.get(TYPES.PayloadManager), + this.get(TYPES.EncryptionOperators), + this.get(TYPES.ItemsEncryptionService), + this.get(TYPES.RootKeyManager), + this.get(TYPES.Crypto), + this.get(TYPES.CreateNewItemsKeyWithRollback), + this.get(TYPES.FindDefaultItemsKey), + this.get(TYPES.EncryptTypeAPayloadWithKeyLookup), + this.get(TYPES.EncryptTypeAPayload), + this.get(TYPES.DecryptTypeAPayload), + this.get(TYPES.DecryptTypeAPayloadWithKeyLookup), + this.get(TYPES.CreateNewDefaultItemsKey), + this.get(TYPES.GetKeyPairs), + this.get(TYPES.InternalEventBus), ) }) @@ -1288,24 +1369,29 @@ export class Dependencies { return new DeprecatedHttpService( this.options.environment, this.options.appVersion, - this.get(TYPES.InternalEventBus), + this.get(TYPES.InternalEventBus), ) }) this.factory.set(TYPES.HttpService, () => { - return new HttpService(this.options.environment, this.options.appVersion, SnjsVersion, this.get(TYPES.Logger)) + return new HttpService( + this.options.environment, + this.options.appVersion, + SnjsVersion, + this.get(TYPES.Logger), + ) }) this.factory.set(TYPES.LegacyApiService, () => { return new LegacyApiService( - this.get(TYPES.HttpService), - this.get(TYPES.DiskStorageService), + this.get(TYPES.HttpService), + this.get(TYPES.DiskStorageService), this.options.defaultHost, - this.get(TYPES.InMemoryStore), - this.get(TYPES.Crypto), - this.get(TYPES.SessionStorageMapper), - this.get(TYPES.LegacySessionStorageMapper), - this.get(TYPES.InternalEventBus), + this.get(TYPES.InMemoryStore), + this.get(TYPES.Crypto), + this.get(TYPES.SessionStorageMapper), + this.get(TYPES.LegacySessionStorageMapper), + this.get(TYPES.InternalEventBus), ) }) diff --git a/packages/snjs/lib/Application/Dependencies/Types.ts b/packages/snjs/lib/Application/Dependencies/Types.ts index fd8b8e950..073a12c82 100644 --- a/packages/snjs/lib/Application/Dependencies/Types.ts +++ b/packages/snjs/lib/Application/Dependencies/Types.ts @@ -153,6 +153,9 @@ export const TYPES = { IsVaultOwner: Symbol.for('IsVaultOwner'), RemoveItemsFromMemory: Symbol.for('RemoveItemsFromMemory'), ReencryptTypeAItems: Symbol.for('ReencryptTypeAItems'), + DecryptErroredPayloads: Symbol.for('DecryptErroredPayloads'), + GetKeyPairs: Symbol.for('GetKeyPairs'), + ChangeVaultStorageMode: Symbol.for('ChangeVaultStorageMode'), // Mappers SessionStorageMapper: Symbol.for('SessionStorageMapper'), diff --git a/packages/snjs/lib/Services/ComponentManager/ComponentManager.spec.ts b/packages/snjs/lib/Services/ComponentManager/ComponentManager.spec.ts index 22eba0b60..aa0be52d8 100644 --- a/packages/snjs/lib/Services/ComponentManager/ComponentManager.spec.ts +++ b/packages/snjs/lib/Services/ComponentManager/ComponentManager.spec.ts @@ -1,4 +1,4 @@ -import { SNPreferencesService } from '../Preferences/PreferencesService' +import { PreferencesService } from '../Preferences/PreferencesService' import { GenericItem, Environment, Platform } from '@standardnotes/models' import { InternalEventBusInterface, @@ -68,7 +68,7 @@ describe('featuresService', () => { features = {} as jest.Mocked - prefs = {} as jest.Mocked + prefs = {} as jest.Mocked prefs.addEventObserver = jest.fn() alerts = {} as jest.Mocked diff --git a/packages/snjs/lib/Services/Features/FeaturesService.spec.ts b/packages/snjs/lib/Services/Features/FeaturesService.spec.ts index e597e0d17..1cb4d0bcf 100644 --- a/packages/snjs/lib/Services/Features/FeaturesService.spec.ts +++ b/packages/snjs/lib/Services/Features/FeaturesService.spec.ts @@ -20,7 +20,7 @@ import { StorageServiceInterface, SubscriptionManagerInterface, SyncServiceInterface, - UserClientInterface, + UserServiceInterface, UserService, } from '@standardnotes/services' import { LegacyApiService, SessionManager } from '../Api' @@ -37,7 +37,7 @@ describe('FeaturesService', () => { let apiService: LegacyApiServiceInterface let webSocketsService: WebSocketsService let settingsService: SettingsClientInterface - let userService: UserClientInterface + let userService: UserServiceInterface let syncService: SyncServiceInterface let alertService: AlertService let sessionManager: SessionsClientInterface diff --git a/packages/snjs/lib/Services/Features/FeaturesService.ts b/packages/snjs/lib/Services/Features/FeaturesService.ts index 2cd1d1781..f9dd16c67 100644 --- a/packages/snjs/lib/Services/Features/FeaturesService.ts +++ b/packages/snjs/lib/Services/Features/FeaturesService.ts @@ -43,7 +43,7 @@ import { ItemManagerInterface, SyncServiceInterface, SessionsClientInterface, - UserClientInterface, + UserServiceInterface, SubscriptionManagerInterface, AccountEvent, SubscriptionManagerEvent, @@ -76,7 +76,7 @@ export class FeaturesService private api: LegacyApiServiceInterface, sockets: WebSocketsService, private settings: SettingsClientInterface, - private user: UserClientInterface, + private user: UserServiceInterface, private sync: SyncServiceInterface, private alerts: AlertService, private sessions: SessionsClientInterface, diff --git a/packages/snjs/lib/Services/Listed/ListedService.ts b/packages/snjs/lib/Services/Listed/ListedService.ts index bbc998874..892a3d6c8 100644 --- a/packages/snjs/lib/Services/Listed/ListedService.ts +++ b/packages/snjs/lib/Services/Listed/ListedService.ts @@ -14,7 +14,7 @@ import { MutatorClientInterface, SyncServiceInterface, } from '@standardnotes/services' -import { SNProtectionService } from '../Protection' +import { ProtectionService } from '../Protection' import { ContentType } from '@standardnotes/domain-core' export class ListedService extends AbstractService implements ListedClientInterface { @@ -23,7 +23,7 @@ export class ListedService extends AbstractService implements ListedClientInterf private itemManager: ItemManager, private settingsService: SettingsService, private httpSerivce: DeprecatedHttpService, - private protectionService: SNProtectionService, + private protectionService: ProtectionService, private mutator: MutatorClientInterface, private sync: SyncServiceInterface, protected override internalEventBus: InternalEventBusInterface, diff --git a/packages/snjs/lib/Services/Mutator/MutatorService.spec.ts b/packages/snjs/lib/Services/Mutator/MutatorService.spec.ts index 79f7b3950..9c446d2af 100644 --- a/packages/snjs/lib/Services/Mutator/MutatorService.spec.ts +++ b/packages/snjs/lib/Services/Mutator/MutatorService.spec.ts @@ -56,6 +56,14 @@ describe('mutator service', () => { return mutatorService.insertItem(note) } + describe('insertItem', () => { + it('should throw if attempting to insert already inserted item', async () => { + const note = await insertNote('hello') + + expect(mutatorService.insertItem(note)).rejects.toThrow() + }) + }) + describe('note modifications', () => { it('pinning should not update timestamps', async () => { const note = await insertNote('hello') diff --git a/packages/snjs/lib/Services/Mutator/MutatorService.ts b/packages/snjs/lib/Services/Mutator/MutatorService.ts index af79eb9dc..decb35352 100644 --- a/packages/snjs/lib/Services/Mutator/MutatorService.ts +++ b/packages/snjs/lib/Services/Mutator/MutatorService.ts @@ -358,6 +358,11 @@ export class MutatorService extends AbstractService implements MutatorClientInte } public async insertItem(item: DecryptedItemInterface, setDirty = true): Promise { + const existingItem = this.itemManager.findItem(item.uuid) + if (existingItem) { + throw Error('Attempting to insert item that already exists') + } + if (setDirty) { const mutator = CreateDecryptedMutatorForItem(item, MutationType.UpdateUserTimestamps) const dirtiedPayload = mutator.getResult() diff --git a/packages/snjs/lib/Services/Preferences/PreferencesService.ts b/packages/snjs/lib/Services/Preferences/PreferencesService.ts index ea5b811d4..f86c6929b 100644 --- a/packages/snjs/lib/Services/Preferences/PreferencesService.ts +++ b/packages/snjs/lib/Services/Preferences/PreferencesService.ts @@ -17,7 +17,7 @@ import { } from '@standardnotes/services' import { ContentType } from '@standardnotes/domain-core' -export class SNPreferencesService +export class PreferencesService extends AbstractService implements PreferenceServiceInterface, InternalEventHandlerInterface { diff --git a/packages/snjs/lib/Services/Protection/ProtectionService.spec.ts b/packages/snjs/lib/Services/Protection/ProtectionService.spec.ts index 5f9357672..b6dc879b9 100644 --- a/packages/snjs/lib/Services/Protection/ProtectionService.spec.ts +++ b/packages/snjs/lib/Services/Protection/ProtectionService.spec.ts @@ -1,6 +1,6 @@ import { ChallengeService } from '../Challenge' import { DiskStorageService } from '../Storage/DiskStorageService' -import { SNProtectionService } from './ProtectionService' +import { ProtectionService } from './ProtectionService' import { InternalEventBus, InternalEventBusInterface, @@ -28,10 +28,10 @@ describe('protectionService', () => { let challengeService: ChallengeService let storageService: DiskStorageService let internalEventBus: InternalEventBusInterface - let protectionService: SNProtectionService + let protectionService: ProtectionService const createService = () => { - return new SNProtectionService(encryptionService, mutator, challengeService, storageService, internalEventBus) + return new ProtectionService(encryptionService, mutator, challengeService, storageService, internalEventBus) } const createFile = (name: string, isProtected?: boolean) => { diff --git a/packages/snjs/lib/Services/Protection/ProtectionService.ts b/packages/snjs/lib/Services/Protection/ProtectionService.ts index 8c5dca8ab..167fc7a7b 100644 --- a/packages/snjs/lib/Services/Protection/ProtectionService.ts +++ b/packages/snjs/lib/Services/Protection/ProtectionService.ts @@ -74,7 +74,7 @@ export const ProtectionSessionDurations = [ * like viewing a protected note, as well as managing how long that * authentication should be valid for. */ -export class SNProtectionService +export class ProtectionService extends AbstractService implements ProtectionsClientInterface, InternalEventHandlerInterface { diff --git a/packages/snjs/lib/Services/Session/SessionManager.ts b/packages/snjs/lib/Services/Session/SessionManager.ts index 652a51ab2..51bd8e692 100644 --- a/packages/snjs/lib/Services/Session/SessionManager.ts +++ b/packages/snjs/lib/Services/Session/SessionManager.ts @@ -32,8 +32,9 @@ import { ApplicationEvent, ApplicationStageChangedEventPayload, ApplicationStage, + GetKeyPairs, } from '@standardnotes/services' -import { Base64String, PkcKeyPair, PureCryptoInterface } from '@standardnotes/sncrypto-common' +import { Base64String, PureCryptoInterface } from '@standardnotes/sncrypto-common' import { SessionBody, ErrorTag, @@ -103,6 +104,7 @@ export class SessionManager private sessionStorageMapper: MapperInterface>, private legacySessionStorageMapper: MapperInterface>, private workspaceIdentifier: string, + private _getKeyPairs: GetKeyPairs, protected override internalEventBus: InternalEventBusInterface, ) { super(internalEventBus) @@ -215,11 +217,15 @@ export class SessionManager } public getPublicKey(): string { - return this.encryptionService.getKeyPair().publicKey + const keys = this._getKeyPairs.execute() + + return keys.getValue().encryption.publicKey } public getSigningPublicKey(): string { - return this.encryptionService.getSigningKeyPair().publicKey + const keys = this._getKeyPairs.execute() + + return keys.getValue().signing.publicKey } public get userUuid(): string { @@ -625,15 +631,7 @@ export class SessionManager newEmail: parameters.newEmail, }) - let oldKeyPair: PkcKeyPair | undefined - let oldSigningKeyPair: PkcKeyPair | undefined - - try { - oldKeyPair = this.encryptionService.getKeyPair() - oldSigningKeyPair = this.encryptionService.getSigningKeyPair() - } catch (error) { - void error - } + const oldKeys = this._getKeyPairs.execute() const processedResponse = await this.processChangeCredentialsResponse( rawResponse, @@ -644,13 +642,12 @@ export class SessionManager if (!isErrorResponse(rawResponse)) { if (InternalFeatureService.get().isFeatureEnabled(InternalFeature.Vaults)) { const eventData: UserKeyPairChangedEventData = { - previous: - oldKeyPair && oldSigningKeyPair - ? { - encryption: oldKeyPair, - signing: oldSigningKeyPair, - } - : undefined, + previous: !oldKeys.isFailed() + ? { + encryption: oldKeys.getValue().encryption, + signing: oldKeys.getValue().signing, + } + : undefined, current: { encryption: parameters.newRootKey.encryptionKeyPair, signing: parameters.newRootKey.signingKeyPair, diff --git a/packages/snjs/mocha/TestRegistry/VaultTests.js b/packages/snjs/mocha/TestRegistry/VaultTests.js index 0b0029fcc..3b3437321 100644 --- a/packages/snjs/mocha/TestRegistry/VaultTests.js +++ b/packages/snjs/mocha/TestRegistry/VaultTests.js @@ -9,6 +9,7 @@ export const VaultTests = { 'vaults/importing.test.js', 'vaults/asymmetric-messages.test.js', 'vaults/keypair-change.test.js', + 'vaults/key-sharing.test.js', 'vaults/signatures.test.js', 'vaults/shared_vaults.test.js', 'vaults/invites.test.js', diff --git a/packages/snjs/mocha/lib/AppContext.js b/packages/snjs/mocha/lib/AppContext.js index 09c452df0..d6ea82cb0 100644 --- a/packages/snjs/mocha/lib/AppContext.js +++ b/packages/snjs/mocha/lib/AppContext.js @@ -149,16 +149,24 @@ export class AppContext { return this.application.asymmetric } + get keyPair() { + return this.application.dependencies.get(TYPES.GetKeyPairs).execute().getValue().encryption + } + + get signingKeyPair() { + return this.application.dependencies.get(TYPES.GetKeyPairs).execute().getValue().signing + } + get publicKey() { - return this.sessions.getPublicKey() + return this.keyPair.publicKey } get signingPublicKey() { - return this.sessions.getSigningPublicKey() + return this.signingKeyPair.publicKey } get privateKey() { - return this.encryption.getKeyPair().privateKey + return this.keyPair.privateKey } ignoreChallenges() { @@ -453,34 +461,6 @@ export class AppContext { return this.resolveWhenAsyncFunctionCompletes(objectToSpy, 'shareContactWithVaults') } - resolveWhenSharedVaultKeyRotationInvitesGetSent(targetVault) { - return new Promise((resolve) => { - const objectToSpy = this.sharedVaults - sinon.stub(objectToSpy, 'handleVaultRootKeyRotatedEvent').callsFake(async (vault) => { - objectToSpy.handleVaultRootKeyRotatedEvent.restore() - const result = await objectToSpy.handleVaultRootKeyRotatedEvent(vault) - if (vault.systemIdentifier === targetVault.systemIdentifier) { - resolve() - } - return result - }) - }) - } - - resolveWhenSharedVaultChangeInvitesAreSent(sharedVaultUuid) { - return new Promise((resolve) => { - const objectToSpy = this.sharedVaults - sinon.stub(objectToSpy, 'handleVaultRootKeyRotatedEvent').callsFake(async (vault) => { - objectToSpy.handleVaultRootKeyRotatedEvent.restore() - const result = await objectToSpy.handleVaultRootKeyRotatedEvent(vault) - if (vault.sharing.sharedVaultUuid === sharedVaultUuid) { - resolve() - } - return result - }) - }) - } - awaitUserPrefsSingletonCreation() { const preferences = this.application.preferences.preferences if (preferences) { diff --git a/packages/snjs/mocha/lib/VaultsContext.js b/packages/snjs/mocha/lib/VaultsContext.js index 244074e20..41f23d398 100644 --- a/packages/snjs/mocha/lib/VaultsContext.js +++ b/packages/snjs/mocha/lib/VaultsContext.js @@ -1,4 +1,5 @@ import { AppContext } from './AppContext.js' +import * as Collaboration from './Collaboration.js' export class VaultsContext extends AppContext { constructor(params) { @@ -6,17 +7,22 @@ export class VaultsContext extends AppContext { } async changeVaultName(vault, nameAndDesc) { - const sendDataChangePromise = this.resolveWhenAsyncFunctionCompletes( - this.sharedVaults._sendVaultDataChangeMessage, - 'execute', - ) - await this.vaults.changeVaultNameAndDescription(vault, { name: nameAndDesc.name, description: nameAndDesc.description, }) + } - await this.awaitPromiseOrThrow(sendDataChangePromise, undefined, 'Waiting for vault data change message to process') + getKeyPair() { + const result = this.application.dependencies.get(TYPES.GetKeyPairs).execute() + + return result.getValue().encryption + } + + getSigningKeyPair() { + const result = this.application.dependencies.get(TYPES.GetKeyPairs).execute() + + return result.getValue().signing } async changePassword(password) { @@ -51,4 +57,28 @@ export class VaultsContext extends AppContext { async runAnyRequestToPreventRefreshTokenFromExpiring() { await this.asymmetric.getInboundMessages() } + + async createSharedPasswordVault(password) { + const privateVault = await this.vaults.createUserInputtedPasswordVault({ + name: 'Our Vault', + userInputtedPassword: password, + storagePreference: KeySystemRootKeyStorageMode.Ephemeral, + }) + + const note = await this.createSyncedNote('foo', 'bar') + + await this.vaults.moveItemToVault(privateVault, note) + + const sharedVault = await this.sharedVaults.convertVaultToSharedVault(privateVault) + console.log('createSharedPasswordVault > sharedVault:', sharedVault) + + const { thirdPartyContext, deinitThirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault( + this, + sharedVault, + ) + + await Collaboration.acceptAllInvites(thirdPartyContext) + + return { sharedVault, thirdPartyContext, deinitThirdPartyContext } + } } diff --git a/packages/snjs/mocha/lib/factory.js b/packages/snjs/mocha/lib/factory.js index d62502ea4..afbcdd98e 100644 --- a/packages/snjs/mocha/lib/factory.js +++ b/packages/snjs/mocha/lib/factory.js @@ -158,7 +158,8 @@ export async function registerOldUser({ application, email, password, version }) mode: SyncMode.DownloadFirst, ...syncOptions, }) - await application.encryption.decryptErroredPayloads() + + await application.dependencies.get(TYPES.DecryptErroredPayloads).execute() } export function createStorageItemPayload(contentType) { diff --git a/packages/snjs/mocha/session-invalidation.test.js b/packages/snjs/mocha/session-invalidation.test.js index a70af3324..c78b1eeb2 100644 --- a/packages/snjs/mocha/session-invalidation.test.js +++ b/packages/snjs/mocha/session-invalidation.test.js @@ -1,3 +1,5 @@ +import * as Factory from './lib/factory.js' + describe.skip('session invalidation tests to revisit', function () { this.timeout(Factory.TwentySecondTimeout) diff --git a/packages/snjs/mocha/vaults/asymmetric-messages.test.js b/packages/snjs/mocha/vaults/asymmetric-messages.test.js index e8cebe33f..5859febda 100644 --- a/packages/snjs/mocha/vaults/asymmetric-messages.test.js +++ b/packages/snjs/mocha/vaults/asymmetric-messages.test.js @@ -189,12 +189,7 @@ describe('asymmetric messages', function () { contactContext.lockSyncing() - const promise = context.resolveWhenAsyncFunctionCompletes( - context.sharedVaults._notifyVaultUsersOfKeyRotation, - 'execute', - ) await context.vaults.rotateVaultRootKey(sharedVault) - await promise const firstPartySpy = sinon.spy(context.asymmetric, 'handleTrustedSharedVaultRootKeyChangedMessage') const secondPartySpy = sinon.spy(contactContext.asymmetric, 'handleTrustedSharedVaultRootKeyChangedMessage') @@ -333,8 +328,8 @@ describe('asymmetric messages', function () { it('sender keypair changed message should be signed using old key pair', async () => { const { contactContext, deinitContactContext } = await Collaboration.createSharedVaultWithAcceptedInvite(context) - const oldKeyPair = context.encryption.getKeyPair() - const oldSigningKeyPair = context.encryption.getSigningKeyPair() + const oldKeyPair = context.keyPair + const oldSigningKeyPair = context.signingKeyPair await context.changePassword('new password') @@ -360,8 +355,8 @@ describe('asymmetric messages', function () { await context.changePassword('new password') - const newKeyPair = context.encryption.getKeyPair() - const newSigningKeyPair = context.encryption.getSigningKeyPair() + const newKeyPair = context.keyPair + const newSigningKeyPair = context.signingKeyPair await contactContext.syncAndAwaitMessageProcessing() @@ -413,12 +408,12 @@ describe('asymmetric messages', function () { const usecase = context.application.dependencies.get(TYPES.ResendAllMessages) const result = await usecase.execute({ keys: { - encryption: context.encryption.getKeyPair(), - signing: context.encryption.getSigningKeyPair(), + encryption: context.keyPair, + signing: context.signingKeyPair, }, previousKeys: { - encryption: context.encryption.getKeyPair(), - signing: context.encryption.getSigningKeyPair(), + encryption: context.keyPair, + signing: context.signingKeyPair, }, }) diff --git a/packages/snjs/mocha/vaults/crypto.test.js b/packages/snjs/mocha/vaults/crypto.test.js index 911222e86..0d98caa48 100644 --- a/packages/snjs/mocha/vaults/crypto.test.js +++ b/packages/snjs/mocha/vaults/crypto.test.js @@ -31,8 +31,8 @@ describe('shared vault crypto', function () { let recreatedContext = await Factory.createVaultsContextWithRealCrypto(appIdentifier) await recreatedContext.launch() - expect(recreatedContext.encryption.getKeyPair()).to.not.be.undefined - expect(recreatedContext.encryption.getSigningKeyPair()).to.not.be.undefined + expect(recreatedContext.keyPair).to.not.be.undefined + expect(recreatedContext.signingKeyPair).to.not.be.undefined await recreatedContext.deinit() }) diff --git a/packages/snjs/mocha/vaults/invites.test.js b/packages/snjs/mocha/vaults/invites.test.js index b59962ff7..777aae856 100644 --- a/packages/snjs/mocha/vaults/invites.test.js +++ b/packages/snjs/mocha/vaults/invites.test.js @@ -28,7 +28,11 @@ describe('shared vault invites', function () { const contact = await Collaboration.createTrustedContactForUserOfContext(context, contactContext) const vaultInvite = ( - await context.vaultInvites.inviteContactToSharedVault(sharedVault, contact, SharedVaultUserPermission.PERMISSIONS.Write) + await context.vaultInvites.inviteContactToSharedVault( + sharedVault, + contact, + SharedVaultUserPermission.PERMISSIONS.Write, + ) ).getValue() expect(vaultInvite).to.not.be.undefined @@ -100,7 +104,11 @@ describe('shared vault invites', function () { /** Sync the contact context so that they wouldn't naturally receive changes made before this point */ await contactContext.sync() - await context.vaultInvites.inviteContactToSharedVault(sharedVault, contact, SharedVaultUserPermission.PERMISSIONS.Write) + await context.vaultInvites.inviteContactToSharedVault( + sharedVault, + contact, + SharedVaultUserPermission.PERMISSIONS.Write, + ) /** Contact should now sync and expect to find note */ const promise = contactContext.awaitNextSyncSharedVaultFromScratchEvent() @@ -214,31 +222,4 @@ describe('shared vault invites', function () { await deinitContactContext() }) - - it('sharing a vault with user inputted and ephemeral password should share the key as synced for the recipient', async () => { - const privateVault = await context.vaults.createUserInputtedPasswordVault({ - name: 'My Private Vault', - userInputtedPassword: 'password', - storagePreference: KeySystemRootKeyStorageMode.Ephemeral, - }) - - 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() - }) }) diff --git a/packages/snjs/mocha/vaults/key-management.test.js b/packages/snjs/mocha/vaults/key-management.test.js index ead6cfebc..70f44f5f2 100644 --- a/packages/snjs/mocha/vaults/key-management.test.js +++ b/packages/snjs/mocha/vaults/key-management.test.js @@ -110,7 +110,7 @@ describe('vault key management', function () { await context.vaultLocks.lockNonPersistentVault(vault) await Factory.expectThrowsAsync( - () => context.vaults.changeVaultOptions({ vault }), + () => context.vaults.changeVaultKeyOptions({ vault }), 'Attempting to change vault options on a locked vault', ) }) @@ -206,7 +206,7 @@ describe('vault key management', function () { }) }) - describe('changeVaultOptions', () => { + describe('changeVaultKeyOptions', () => { describe('change storage type', () => { it('should not be able to change randomized vault from synced to local', async () => { const vault = await context.vaults.createRandomizedVault({ @@ -214,13 +214,13 @@ describe('vault key management', function () { description: 'test vault description', }) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, newStorageMode: KeySystemRootKeyStorageMode.Local, }) expect(result.isFailed()).to.be.true - expect(result.getError()).to.equal('Vault uses randomized password and cannot change its storage preference') + expect(result.getError()).to.equal('Cannot change storage mode to non-synced for randomized vault') }) it('should not be able to change randomized vault from synced to ephemeral', async () => { @@ -229,13 +229,13 @@ describe('vault key management', function () { description: 'test vault description', }) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, - newStorageMode: KeySystemRootKeyStorageMode.Local, + newStorageMode: KeySystemRootKeyStorageMode.Ephemeral, }) expect(result.isFailed()).to.be.true - expect(result.getError()).to.equal('Vault uses randomized password and cannot change its storage preference') + expect(result.getError()).to.equal('Cannot change storage mode to non-synced for randomized vault') }) it('should change user password vault from synced to local', async () => { @@ -248,7 +248,7 @@ describe('vault key management', function () { let syncedKeys = context.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, newStorageMode: KeySystemRootKeyStorageMode.Local, }) @@ -272,7 +272,7 @@ describe('vault key management', function () { let syncedKeys = context.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, newStorageMode: KeySystemRootKeyStorageMode.Ephemeral, }) @@ -299,7 +299,7 @@ describe('vault key management', function () { let syncedKeys = context.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, newStorageMode: KeySystemRootKeyStorageMode.Synced, }) @@ -326,7 +326,7 @@ describe('vault key management', function () { let syncedKeys = context.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, newStorageMode: KeySystemRootKeyStorageMode.Ephemeral, }) @@ -351,9 +351,9 @@ describe('vault key management', function () { description: 'test vault description', }) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, - newPasswordType: { + newPasswordOptions: { passwordType: KeySystemPasswordType.UserInputted, }, }) @@ -370,9 +370,9 @@ describe('vault key management', function () { const rootKeysBeforeChange = context.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier) expect(rootKeysBeforeChange.length).to.equal(1) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, - newPasswordType: { + newPasswordOptions: { passwordType: KeySystemPasswordType.UserInputted, userInputtedPassword: 'test password', }, @@ -394,9 +394,9 @@ describe('vault key management', function () { storagePreference: KeySystemRootKeyStorageMode.Local, }) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, - newPasswordType: { + newPasswordOptions: { passwordType: KeySystemPasswordType.Randomized, }, }) @@ -404,7 +404,7 @@ describe('vault key management', function () { expect(result.isFailed()).to.be.false const rootKeysAfterChange = context.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier) - expect(rootKeysAfterChange.length).to.equal(1) + expect(rootKeysAfterChange.length).to.equal(2) const storedKey = context.keys.getRootKeyFromStorageForVault(vault.systemIdentifier) expect(storedKey).to.be.undefined @@ -421,9 +421,9 @@ describe('vault key management', function () { storagePreference: KeySystemRootKeyStorageMode.Local, }) - const result = await context.vaults.changeVaultOptions({ + const result = await context.vaults.changeVaultKeyOptions({ vault, - newPasswordType: { + newPasswordOptions: { passwordType: KeySystemPasswordType.Randomized, }, newStorageMode: KeySystemRootKeyStorageMode.Local, @@ -431,7 +431,7 @@ describe('vault key management', function () { expect(result.isFailed()).to.be.true - expect(result.getError()).to.equal('Vault uses randomized password and cannot change its storage preference') + expect(result.getError()).to.equal('Cannot change storage mode to non-synced for randomized vault') }) }) }) diff --git a/packages/snjs/mocha/vaults/key-rotation.test.js b/packages/snjs/mocha/vaults/key-rotation.test.js index 48c540d89..6094ce192 100644 --- a/packages/snjs/mocha/vaults/key-rotation.test.js +++ b/packages/snjs/mocha/vaults/key-rotation.test.js @@ -32,9 +32,7 @@ describe('vault key rotation', function () { 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(callSpy.callCount).to.equal(1) @@ -95,12 +93,10 @@ describe('vault key rotation', function () { contactContext.lockSyncing() - const promise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault) await context.vaults.rotateVaultRootKey(sharedVault) - await promise const outboundMessages = (await context.asymmetric.getOutboundMessages()).getValue() - const expectedMessages = ['root key change', 'vault metadata change'] + const expectedMessages = ['root key change'] expect(outboundMessages.length).to.equal(expectedMessages.length) const message = outboundMessages[0] @@ -122,9 +118,7 @@ describe('vault key rotation', function () { contactContext.lockSyncing() - const promise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault) await context.vaults.rotateVaultRootKey(sharedVault) - await promise const rootKey = context.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier) @@ -150,9 +144,7 @@ describe('vault key rotation', function () { const previousPrimaryItemsKey = contactContext.keys.getPrimaryKeySystemItemsKey(sharedVault.systemIdentifier) expect(previousPrimaryItemsKey).to.not.be.undefined - const promise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault) await context.vaults.rotateVaultRootKey(sharedVault) - await promise contactContext.unlockSyncing() await contactContext.syncAndAwaitMessageProcessing() @@ -175,9 +167,7 @@ describe('vault key rotation', function () { expect(originalOutboundInvites.length).to.equal(1) const originalInviteMessage = originalOutboundInvites[0].encrypted_message - const promise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault) await context.vaults.rotateVaultRootKey(sharedVault) - await promise const updatedOutboundInvites = await context.vaultInvites.getOutboundInvites() expect(updatedOutboundInvites.length).to.equal(1) @@ -211,19 +201,15 @@ describe('vault key rotation', function () { contactContext.lockSyncing() - const firstPromise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault) await context.vaults.rotateVaultRootKey(sharedVault) - await firstPromise const asymmetricMessageAfterFirstChange = (await context.asymmetric.getOutboundMessages()).getValue() - const expectedMessages = ['root key change', 'vault metadata change'] + const expectedMessages = ['root key change'] expect(asymmetricMessageAfterFirstChange.length).to.equal(expectedMessages.length) const messageAfterFirstChange = asymmetricMessageAfterFirstChange[0] - const secondPromise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault) await context.vaults.rotateVaultRootKey(sharedVault) - await secondPromise const asymmetricMessageAfterSecondChange = (await context.asymmetric.getOutboundMessages()).getValue() expect(asymmetricMessageAfterSecondChange.length).to.equal(expectedMessages.length) @@ -245,9 +231,7 @@ describe('vault key rotation', function () { ) contactContext.lockSyncing() - const promise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault) await context.vaults.rotateVaultRootKey(sharedVault) - await promise const acceptMessage = sinon.spy(contactContext.asymmetric, 'handleTrustedSharedVaultRootKeyChangedMessage') diff --git a/packages/snjs/mocha/vaults/key-sharing.test.js b/packages/snjs/mocha/vaults/key-sharing.test.js new file mode 100644 index 000000000..34a1d96b9 --- /dev/null +++ b/packages/snjs/mocha/vaults/key-sharing.test.js @@ -0,0 +1,79 @@ +import * as Factory from '../lib/factory.js' +import * as Collaboration from '../lib/Collaboration.js' + +chai.use(chaiAsPromised) +const expect = chai.expect + +describe('vault key sharing', function () { + this.timeout(Factory.TwentySecondTimeout) + + let context + + afterEach(async function () { + await context.deinit() + localStorage.clear() + }) + + beforeEach(async function () { + localStorage.clear() + + context = await Factory.createVaultsContextWithRealCrypto() + + await context.launch() + await context.register() + }) + + it('sharing a vault with user inputted and ephemeral password should share the key as synced for the recipient', async () => { + const privateVault = await context.vaults.createUserInputtedPasswordVault({ + name: 'My Private Vault', + userInputtedPassword: 'password', + storagePreference: KeySystemRootKeyStorageMode.Ephemeral, + }) + + 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 rootKey = thirdPartyContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier) + expect(rootKey).to.not.be.undefined + + 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() + }) + + it('should send key change message when vault password is changed', async () => { + const { sharedVault, thirdPartyContext, deinitThirdPartyContext } = await context.createSharedPasswordVault( + 'test password', + ) + + const rootKeyBeforeChange = thirdPartyContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier) + + await context.vaults.changeVaultKeyOptions({ + vault: sharedVault, + newPasswordOptions: { + passwordType: KeySystemPasswordType.UserInputted, + userInputtedPassword: 'new password', + }, + }) + + await thirdPartyContext.syncAndAwaitMessageProcessing() + + const rootKeyAfterChange = thirdPartyContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier) + + expect(rootKeyBeforeChange.itemsKey).to.not.equal(rootKeyAfterChange.itemsKey) + + await deinitThirdPartyContext() + }) +}) diff --git a/packages/snjs/mocha/vaults/keypair-change.test.js b/packages/snjs/mocha/vaults/keypair-change.test.js index af979bfdf..22249fa9f 100644 --- a/packages/snjs/mocha/vaults/keypair-change.test.js +++ b/packages/snjs/mocha/vaults/keypair-change.test.js @@ -82,13 +82,14 @@ describe('keypair change', function () { contactContext.lockSyncing() - const previousKeyPair = context.encryption.getKeyPair() - const previousSigningKeyPair = context.encryption.getSigningKeyPair() + const previousKeyPair = context.keyPair + const previousSigningKeyPair = context.signingKeyPair await context.changePassword('new_password') - sinon.stub(context.encryption, 'getKeyPair').returns(previousKeyPair) - sinon.stub(context.encryption, 'getSigningKeyPair').returns(previousSigningKeyPair) + sinon + .stub(context.application.dependencies.get(TYPES.GetKeyPairs), 'execute') + .returns(Result.ok({ encryption: previousKeyPair, signing: previousSigningKeyPair })) await context.changeVaultName(sharedVault, { name: 'New Name', diff --git a/packages/snjs/mocha/vaults/pkc.test.js b/packages/snjs/mocha/vaults/pkc.test.js index c1d76f8f0..70eaf9934 100644 --- a/packages/snjs/mocha/vaults/pkc.test.js +++ b/packages/snjs/mocha/vaults/pkc.test.js @@ -28,11 +28,11 @@ describe('public key cryptography', function () { }) it('should create keypair during registration', () => { - expect(sessions.getPublicKey()).to.not.be.undefined - expect(encryption.getKeyPair().privateKey).to.not.be.undefined + expect(context.publicKey).to.not.be.undefined + expect(context.keyPair.privateKey).to.not.be.undefined - expect(sessions.getSigningPublicKey()).to.not.be.undefined - expect(encryption.getSigningKeyPair().privateKey).to.not.be.undefined + expect(context.signingPublicKey).to.not.be.undefined + expect(context.signingKeyPair.privateKey).to.not.be.undefined }) it('should populate keypair during sign in', async () => { @@ -46,33 +46,33 @@ describe('public key cryptography', function () { recreatedContext.password = password await recreatedContext.signIn() - expect(recreatedContext.sessions.getPublicKey()).to.not.be.undefined - expect(recreatedContext.encryption.getKeyPair().privateKey).to.not.be.undefined + expect(recreatedContext.publicKey).to.not.be.undefined + expect(recreatedContext.privateKey).to.not.be.undefined - expect(recreatedContext.sessions.getSigningPublicKey()).to.not.be.undefined - expect(recreatedContext.encryption.getSigningKeyPair().privateKey).to.not.be.undefined + expect(recreatedContext.signingPublicKey).to.not.be.undefined + expect(recreatedContext.signingKeyPair.privateKey).to.not.be.undefined await recreatedContext.deinit() }) it('should rotate keypair during password change', async () => { - const oldPublicKey = sessions.getPublicKey() - const oldPrivateKey = encryption.getKeyPair().privateKey + const oldPublicKey = context.publicKey + const oldPrivateKey = context.privateKey - const oldSigningPublicKey = sessions.getSigningPublicKey() - const oldSigningPrivateKey = encryption.getSigningKeyPair().privateKey + const oldSigningPublicKey = context.signingPublicKey + const oldSigningPrivateKey = context.signingKeyPair.privateKey await context.changePassword('new_password') - expect(sessions.getPublicKey()).to.not.be.undefined - expect(encryption.getKeyPair().privateKey).to.not.be.undefined - expect(sessions.getPublicKey()).to.not.equal(oldPublicKey) - expect(encryption.getKeyPair().privateKey).to.not.equal(oldPrivateKey) + expect(context.publicKey).to.not.be.undefined + expect(context.keyPair.privateKey).to.not.be.undefined + expect(context.publicKey).to.not.equal(oldPublicKey) + expect(context.keyPair.privateKey).to.not.equal(oldPrivateKey) - expect(sessions.getSigningPublicKey()).to.not.be.undefined - expect(encryption.getSigningKeyPair().privateKey).to.not.be.undefined - expect(sessions.getSigningPublicKey()).to.not.equal(oldSigningPublicKey) - expect(encryption.getSigningKeyPair().privateKey).to.not.equal(oldSigningPrivateKey) + expect(context.signingPublicKey).to.not.be.undefined + expect(context.signingKeyPair.privateKey).to.not.be.undefined + expect(context.signingPublicKey).to.not.equal(oldSigningPublicKey) + expect(context.signingKeyPair.privateKey).to.not.equal(oldSigningPrivateKey) }) it('should allow option to enable collaboration for previously signed in accounts', async () => { diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal.tsx index 4d1405c3e..5dbe3a23e 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal.tsx @@ -87,7 +87,7 @@ const EditVaultModal: FunctionComponent = ({ onCloseDialog, existingVault const isChangingPasswordType = vault.keyPasswordType !== passwordType const isChangingKeyStorageMode = vault.keyStorageMode !== keyStorageMode - const getPasswordTypeParams = (): ChangeVaultKeyOptionsDTO['newPasswordType'] => { + const getPasswordTypeParams = (): ChangeVaultKeyOptionsDTO['newPasswordOptions'] => { if (!isChangingPasswordType) { throw new Error('Password type is not changing') } @@ -108,9 +108,9 @@ const EditVaultModal: FunctionComponent = ({ onCloseDialog, existingVault } if (isChangingPasswordType || isChangingKeyStorageMode) { - await application.vaults.changeVaultOptions({ + await application.vaults.changeVaultKeyOptions({ vault, - newPasswordType: isChangingPasswordType ? getPasswordTypeParams() : undefined, + newPasswordOptions: isChangingPasswordType ? getPasswordTypeParams() : undefined, newStorageMode: isChangingKeyStorageMode ? keyStorageMode : undefined, }) } diff --git a/packages/web/src/javascripts/Event/ApplicationEventObserver.spec.ts b/packages/web/src/javascripts/Event/ApplicationEventObserver.spec.ts index a3c8e8562..0e4ce9bb1 100644 --- a/packages/web/src/javascripts/Event/ApplicationEventObserver.spec.ts +++ b/packages/web/src/javascripts/Event/ApplicationEventObserver.spec.ts @@ -17,7 +17,7 @@ import { SyncOpStatus, SyncServiceInterface, User, - UserClientInterface, + UserServiceInterface, UserRequestType, } from '@standardnotes/snjs' @@ -41,7 +41,7 @@ describe('ApplicationEventObserver', () => { let sessionManager: SessionsClientInterface let subscriptionManager: SubscriptionManagerInterface let toastService: ToastServiceInterface - let userService: UserClientInterface + let userService: UserServiceInterface const createObserver = () => new ApplicationEventObserver( @@ -94,7 +94,7 @@ describe('ApplicationEventObserver', () => { toastService.showToast = jest.fn().mockReturnValue('1') toastService.hideToast = jest.fn() - userService = {} as jest.Mocked + userService = {} as jest.Mocked userService.submitUserRequest = jest.fn().mockReturnValue(true) }) diff --git a/packages/web/src/javascripts/Event/ApplicationEventObserver.ts b/packages/web/src/javascripts/Event/ApplicationEventObserver.ts index 3ee997972..68b45c62e 100644 --- a/packages/web/src/javascripts/Event/ApplicationEventObserver.ts +++ b/packages/web/src/javascripts/Event/ApplicationEventObserver.ts @@ -10,7 +10,7 @@ import { SessionsClientInterface, SubscriptionManagerInterface, SyncServiceInterface, - UserClientInterface, + UserServiceInterface, } from '@standardnotes/snjs' import { ToastType } from '@standardnotes/toast' @@ -37,7 +37,7 @@ export class ApplicationEventObserver implements EventObserverInterface { private sessionManager: SessionsClientInterface, private subscriptionManager: SubscriptionManagerInterface, private toastService: ToastServiceInterface, - private userService: UserClientInterface, + private userService: UserServiceInterface, ) {} async handle(event: ApplicationEvent): Promise {