mirror of
https://github.com/standardnotes/app
synced 2026-01-16 19:04:58 -05:00
chore: loosen coupling with encryption services
This commit is contained in:
@@ -72,7 +72,6 @@ export interface EncryptionProviderInterface {
|
||||
}
|
||||
>
|
||||
|
||||
decryptErroredPayloads(): Promise<void>
|
||||
deleteWorkspaceSpecificKeyStateFromDevice(): Promise<void>
|
||||
|
||||
computeRootKey(password: string, keyParams: SNRootKeyParams): Promise<RootKeyInterface>
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
} from '@standardnotes/models'
|
||||
import { HandleTrustedSharedVaultRootKeyChangedMessage } from './UseCase/HandleTrustedSharedVaultRootKeyChangedMessage'
|
||||
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
|
||||
import { SyncServiceInterface } from '../Sync/SyncServiceInterface'
|
||||
import { SessionEvent } from '../Session/SessionEvent'
|
||||
import { AsymmetricMessageServer, HttpServiceInterface } from '@standardnotes/api'
|
||||
import { UserKeyPairChangedEventData } from '../Session/UserKeyPairChangedEventData'
|
||||
@@ -41,7 +40,7 @@ export class AsymmetricMessageService
|
||||
private contacts: ContactServiceInterface,
|
||||
private items: ItemManagerInterface,
|
||||
private mutator: MutatorClientInterface,
|
||||
private sync: SyncServiceInterface,
|
||||
private handleTrustedSharedVaultRootKeyChangedMessageUseCase: HandleTrustedSharedVaultRootKeyChangedMessage,
|
||||
eventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(eventBus)
|
||||
@@ -189,12 +188,9 @@ export class AsymmetricMessageService
|
||||
_message: AsymmetricMessageServerHash,
|
||||
trustedPayload: AsymmetricMessageSharedVaultRootKeyChanged,
|
||||
): Promise<void> {
|
||||
const useCase = new HandleTrustedSharedVaultRootKeyChangedMessage(
|
||||
this.mutator,
|
||||
this.items,
|
||||
this.sync,
|
||||
this.encryption,
|
||||
)
|
||||
await useCase.execute(trustedPayload)
|
||||
const resultOrError = await this.handleTrustedSharedVaultRootKeyChangedMessageUseCase.execute(trustedPayload)
|
||||
if (resultOrError.isFailed()) {
|
||||
throw new Error(resultOrError.getError())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import { ItemManagerInterface } from './../../Item/ItemManagerInterface'
|
||||
import { MutatorClientInterface } from './../../Mutator/MutatorClientInterface'
|
||||
import { SyncServiceInterface } from '../../Sync/SyncServiceInterface'
|
||||
import {
|
||||
KeySystemRootKeyInterface,
|
||||
AsymmetricMessageSharedVaultRootKeyChanged,
|
||||
@@ -8,20 +5,23 @@ import {
|
||||
KeySystemRootKeyContent,
|
||||
VaultListingMutator,
|
||||
} from '@standardnotes/models'
|
||||
import { ContentType, UseCaseInterface, Result } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from '@standardnotes/domain-core'
|
||||
import { ItemManagerInterface } from './../../Item/ItemManagerInterface'
|
||||
import { MutatorClientInterface } from './../../Mutator/MutatorClientInterface'
|
||||
import { SyncServiceInterface } from '../../Sync/SyncServiceInterface'
|
||||
import { GetVaultUseCase } from '../../Vaults/UseCase/GetVault'
|
||||
import { EncryptionProviderInterface } from '@standardnotes/encryption'
|
||||
import { EmitDecryptedErroredPayloads } from '../../Encryption/UseCase/EmitDecryptedErroredPayloads/EmitDecryptedErroredPayloads'
|
||||
|
||||
export class HandleTrustedSharedVaultRootKeyChangedMessage {
|
||||
export class HandleTrustedSharedVaultRootKeyChangedMessage implements UseCaseInterface<void> {
|
||||
constructor(
|
||||
private mutator: MutatorClientInterface,
|
||||
private items: ItemManagerInterface,
|
||||
private sync: SyncServiceInterface,
|
||||
private encryption: EncryptionProviderInterface,
|
||||
private emitDecryptedErroredPayloadsUseCase: EmitDecryptedErroredPayloads,
|
||||
) {}
|
||||
|
||||
async execute(message: AsymmetricMessageSharedVaultRootKeyChanged): Promise<void> {
|
||||
async execute(message: AsymmetricMessageSharedVaultRootKeyChanged): Promise<Result<void>> {
|
||||
const rootKeyContent = message.data.rootKey
|
||||
|
||||
await this.mutator.createItem<KeySystemRootKeyInterface>(
|
||||
@@ -37,8 +37,13 @@ export class HandleTrustedSharedVaultRootKeyChangedMessage {
|
||||
})
|
||||
}
|
||||
|
||||
await this.encryption.decryptErroredPayloads()
|
||||
const emitedOrFailed = await this.emitDecryptedErroredPayloadsUseCase.execute()
|
||||
if (emitedOrFailed.isFailed()) {
|
||||
return Result.fail(emitedOrFailed.getError())
|
||||
}
|
||||
|
||||
void this.sync.sync({ sourceDescription: 'Not awaiting due to this event handler running from sync response' })
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,14 +49,13 @@ import {
|
||||
RootKeyParamsInterface,
|
||||
} from '@standardnotes/models'
|
||||
import { ClientDisplayableError } from '@standardnotes/responses'
|
||||
import { PkcKeyPair, PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
||||
import { PkcKeyPair } from '@standardnotes/sncrypto-common'
|
||||
import {
|
||||
extendArray,
|
||||
isNotUndefined,
|
||||
isNullOrUndefined,
|
||||
isReactNativeEnvironment,
|
||||
isWebCryptoAvailable,
|
||||
UuidGenerator,
|
||||
} from '@standardnotes/utils'
|
||||
import {
|
||||
AnyKeyParamsContent,
|
||||
@@ -83,15 +82,12 @@ import { DecryptedParameters } from '@standardnotes/encryption/src/Domain/Types/
|
||||
import { RootKeyManager } from './RootKey/RootKeyManager'
|
||||
import { RootKeyManagerEvent } from './RootKey/RootKeyManagerEvent'
|
||||
import { CreateNewItemsKeyWithRollbackUseCase } from './UseCase/ItemsKey/CreateNewItemsKeyWithRollback'
|
||||
import { DecryptErroredRootPayloadsUseCase } from './UseCase/RootEncryption/DecryptErroredPayloads'
|
||||
import { CreateNewDefaultItemsKeyUseCase } from './UseCase/ItemsKey/CreateNewDefaultItemsKey'
|
||||
import { RootKeyDecryptPayloadUseCase } from './UseCase/RootEncryption/DecryptPayload'
|
||||
import { RootKeyDecryptPayloadWithKeyLookupUseCase } from './UseCase/RootEncryption/DecryptPayloadWithKeyLookup'
|
||||
import { RootKeyEncryptPayloadWithKeyLookupUseCase } from './UseCase/RootEncryption/EncryptPayloadWithKeyLookup'
|
||||
import { RootKeyEncryptPayloadUseCase } from './UseCase/RootEncryption/EncryptPayload'
|
||||
import { ValidateAccountPasswordResult } from './RootKey/ValidateAccountPasswordResult'
|
||||
import { ValidatePasscodeResult } from './RootKey/ValidatePasscodeResult'
|
||||
import { ContentType } from '@standardnotes/domain-core'
|
||||
import { EncryptPayloads } from './UseCase/EncryptPayloads/EncryptPayloads'
|
||||
import { DecryptPayloads } from './UseCase/DecryptPayloads/DecryptPayloads'
|
||||
|
||||
/**
|
||||
* The encryption service is responsible for the encryption and decryption of payloads, and
|
||||
@@ -124,9 +120,7 @@ export class EncryptionService
|
||||
extends AbstractService<EncryptionServiceEvent>
|
||||
implements EncryptionProviderInterface, InternalEventHandlerInterface
|
||||
{
|
||||
private operators: OperatorManager
|
||||
private readonly itemsEncryption: ItemsEncryptionService
|
||||
private readonly rootKeyManager: RootKeyManager
|
||||
|
||||
constructor(
|
||||
private items: ItemManagerInterface,
|
||||
@@ -135,30 +129,18 @@ export class EncryptionService
|
||||
public device: DeviceInterface,
|
||||
private storage: StorageServiceInterface,
|
||||
public readonly keys: KeySystemKeyManagerInterface,
|
||||
identifier: ApplicationIdentifier,
|
||||
public crypto: PureCryptoInterface,
|
||||
private rootKeyManager: RootKeyManager,
|
||||
public identifier: ApplicationIdentifier,
|
||||
private encryptPayloadsUseCase: EncryptPayloads,
|
||||
private decryptPayloadsUseCase: DecryptPayloads,
|
||||
private operators: OperatorManager,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
this.crypto = crypto
|
||||
|
||||
this.operators = new OperatorManager(crypto)
|
||||
|
||||
this.rootKeyManager = new RootKeyManager(
|
||||
device,
|
||||
storage,
|
||||
items,
|
||||
mutator,
|
||||
this.operators,
|
||||
identifier,
|
||||
internalEventBus,
|
||||
)
|
||||
|
||||
internalEventBus.addEventHandler(this, RootKeyManagerEvent.RootKeyManagerKeyStatusChanged)
|
||||
|
||||
this.itemsEncryption = new ItemsEncryptionService(items, payloads, storage, this.operators, keys, internalEventBus)
|
||||
|
||||
UuidGenerator.SetGenerator(this.crypto.generateUUID)
|
||||
}
|
||||
|
||||
async handleEvent(event: InternalEventInterface): Promise<void> {
|
||||
@@ -179,7 +161,6 @@ export class EncryptionService
|
||||
;(this.payloads as unknown) = undefined
|
||||
;(this.device as unknown) = undefined
|
||||
;(this.storage as unknown) = undefined
|
||||
;(this.crypto as unknown) = undefined
|
||||
;(this.operators as unknown) = undefined
|
||||
|
||||
this.itemsEncryption.deinit()
|
||||
@@ -290,13 +271,6 @@ export class EncryptionService
|
||||
return usecase.execute()
|
||||
}
|
||||
|
||||
public async decryptErroredPayloads(): Promise<void> {
|
||||
const usecase = new DecryptErroredRootPayloadsUseCase(this.payloads, this.operators, this.keys, this.rootKeyManager)
|
||||
await usecase.execute()
|
||||
|
||||
await this.itemsEncryption.decryptErroredItemPayloads()
|
||||
}
|
||||
|
||||
public itemsKeyForEncryptedPayload(
|
||||
payload: EncryptedPayloadInterface,
|
||||
): ItemsKeyInterface | KeySystemItemsKeyInterface | undefined {
|
||||
@@ -326,47 +300,41 @@ export class EncryptionService
|
||||
usesKeySystemRootKeyWithKeyLookup,
|
||||
} = split
|
||||
|
||||
const rootKeyEncryptWithKeyLookupUsecase = new RootKeyEncryptPayloadWithKeyLookupUseCase(
|
||||
this.operators,
|
||||
this.keys,
|
||||
this.rootKeyManager,
|
||||
)
|
||||
|
||||
const rootKeyEncryptUsecase = new RootKeyEncryptPayloadUseCase(this.operators)
|
||||
|
||||
const signingKeyPair = this.hasSigningKeyPair() ? this.getSigningKeyPair() : undefined
|
||||
|
||||
if (usesRootKey) {
|
||||
const rootKeyEncrypted = await rootKeyEncryptUsecase.executeMany(
|
||||
usesRootKey.items,
|
||||
usesRootKey.key,
|
||||
const rootKeyEncrypted = await this.encryptPayloads({
|
||||
payloads: usesRootKey.items,
|
||||
key: usesRootKey.key,
|
||||
signingKeyPair,
|
||||
)
|
||||
})
|
||||
|
||||
extendArray(allEncryptedParams, rootKeyEncrypted)
|
||||
}
|
||||
|
||||
if (usesRootKeyWithKeyLookup) {
|
||||
const rootKeyEncrypted = await rootKeyEncryptWithKeyLookupUsecase.executeMany(
|
||||
usesRootKeyWithKeyLookup.items,
|
||||
const rootKeyEncrypted = await this.encryptPayloads({
|
||||
payloads: usesRootKeyWithKeyLookup.items,
|
||||
signingKeyPair,
|
||||
)
|
||||
})
|
||||
|
||||
extendArray(allEncryptedParams, rootKeyEncrypted)
|
||||
}
|
||||
|
||||
if (usesKeySystemRootKey) {
|
||||
const keySystemRootKeyEncrypted = await rootKeyEncryptUsecase.executeMany(
|
||||
usesKeySystemRootKey.items,
|
||||
usesKeySystemRootKey.key,
|
||||
const keySystemRootKeyEncrypted = await this.encryptPayloads({
|
||||
payloads: usesKeySystemRootKey.items,
|
||||
key: usesKeySystemRootKey.key,
|
||||
signingKeyPair,
|
||||
)
|
||||
})
|
||||
extendArray(allEncryptedParams, keySystemRootKeyEncrypted)
|
||||
}
|
||||
|
||||
if (usesKeySystemRootKeyWithKeyLookup) {
|
||||
const keySystemRootKeyEncrypted = await rootKeyEncryptWithKeyLookupUsecase.executeMany(
|
||||
usesKeySystemRootKeyWithKeyLookup.items,
|
||||
const keySystemRootKeyEncrypted = await this.encryptPayloads({
|
||||
payloads: usesKeySystemRootKeyWithKeyLookup.items,
|
||||
signingKeyPair,
|
||||
)
|
||||
})
|
||||
extendArray(allEncryptedParams, keySystemRootKeyEncrypted)
|
||||
}
|
||||
|
||||
@@ -423,34 +391,29 @@ export class EncryptionService
|
||||
usesKeySystemRootKeyWithKeyLookup,
|
||||
} = split
|
||||
|
||||
const rootKeyDecryptUseCase = new RootKeyDecryptPayloadUseCase(this.operators)
|
||||
|
||||
const rootKeyDecryptWithKeyLookupUsecase = new RootKeyDecryptPayloadWithKeyLookupUseCase(
|
||||
this.operators,
|
||||
this.keys,
|
||||
this.rootKeyManager,
|
||||
)
|
||||
|
||||
if (usesRootKey) {
|
||||
const rootKeyDecrypted = await rootKeyDecryptUseCase.executeMany<C>(usesRootKey.items, usesRootKey.key)
|
||||
const rootKeyDecrypted = await this.decryptPayloads<C>({
|
||||
payloads: usesRootKey.items,
|
||||
key: usesRootKey.key,
|
||||
})
|
||||
extendArray(resultParams, rootKeyDecrypted)
|
||||
}
|
||||
|
||||
if (usesRootKeyWithKeyLookup) {
|
||||
const rootKeyDecrypted = await rootKeyDecryptWithKeyLookupUsecase.executeMany<C>(usesRootKeyWithKeyLookup.items)
|
||||
const rootKeyDecrypted = await this.decryptPayloads<C>({ payloads: usesRootKeyWithKeyLookup.items })
|
||||
extendArray(resultParams, rootKeyDecrypted)
|
||||
}
|
||||
if (usesKeySystemRootKey) {
|
||||
const keySystemRootKeyDecrypted = await rootKeyDecryptUseCase.executeMany<C>(
|
||||
usesKeySystemRootKey.items,
|
||||
usesKeySystemRootKey.key,
|
||||
)
|
||||
const keySystemRootKeyDecrypted = await this.decryptPayloads<C>({
|
||||
payloads: usesKeySystemRootKey.items,
|
||||
key: usesKeySystemRootKey.key,
|
||||
})
|
||||
extendArray(resultParams, keySystemRootKeyDecrypted)
|
||||
}
|
||||
if (usesKeySystemRootKeyWithKeyLookup) {
|
||||
const keySystemRootKeyDecrypted = await rootKeyDecryptWithKeyLookupUsecase.executeMany<C>(
|
||||
usesKeySystemRootKeyWithKeyLookup.items,
|
||||
)
|
||||
const keySystemRootKeyDecrypted = await this.decryptPayloads<C>({
|
||||
payloads: usesKeySystemRootKeyWithKeyLookup.items,
|
||||
})
|
||||
extendArray(resultParams, keySystemRootKeyDecrypted)
|
||||
}
|
||||
|
||||
@@ -1026,4 +989,37 @@ export class EncryptionService
|
||||
void this.mutator.setItemsDirty(unsyncedKeys)
|
||||
}
|
||||
}
|
||||
|
||||
private async encryptPayloads(dto: {
|
||||
payloads: DecryptedPayloadInterface[]
|
||||
key?: RootKeyInterface | KeySystemRootKeyInterface
|
||||
signingKeyPair?: PkcKeyPair
|
||||
}): Promise<EncryptedOutputParameters[]> {
|
||||
const encryptedPayloadsOrError = await this.encryptPayloadsUseCase.execute({
|
||||
...dto,
|
||||
fallbackRootKey: this.rootKeyManager.getRootKey(),
|
||||
})
|
||||
if (encryptedPayloadsOrError.isFailed()) {
|
||||
throw new Error(encryptedPayloadsOrError.getError())
|
||||
}
|
||||
const encryptedPayloads = encryptedPayloadsOrError.getValue()
|
||||
|
||||
return encryptedPayloads
|
||||
}
|
||||
|
||||
private async decryptPayloads<C extends ItemContent = ItemContent>(dto: {
|
||||
payloads: EncryptedPayloadInterface[]
|
||||
key?: RootKeyInterface | KeySystemRootKeyInterface
|
||||
}): Promise<(DecryptedParameters<C> | ErrorDecryptingParameters)[]> {
|
||||
const decryptedPayloadsOrError = await this.decryptPayloadsUseCase.execute<C>({
|
||||
...dto,
|
||||
fallbackRootKey: this.rootKeyManager.getRootKey(),
|
||||
})
|
||||
if (decryptedPayloadsOrError.isFailed()) {
|
||||
throw new Error(decryptedPayloadsOrError.getError())
|
||||
}
|
||||
const decryptedPayloads = decryptedPayloadsOrError.getValue()
|
||||
|
||||
return decryptedPayloads
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,28 +16,28 @@ import {
|
||||
import {
|
||||
ContentTypesUsingRootKeyEncryption,
|
||||
DecryptedPayload,
|
||||
DecryptedTransferPayload,
|
||||
EncryptedPayload,
|
||||
EncryptedTransferPayload,
|
||||
FillItemContentSpecialized,
|
||||
NamespacedRootKeyInKeychain,
|
||||
RootKeyContent,
|
||||
RootKeyInterface,
|
||||
RootKeyParamsInterface,
|
||||
DecryptedTransferPayload,
|
||||
FillItemContentSpecialized,
|
||||
} from '@standardnotes/models'
|
||||
import { DeviceInterface } from '../../Device/DeviceInterface'
|
||||
import { InternalEventBusInterface } from '../../Internal/InternalEventBusInterface'
|
||||
import { StorageKey } from '../../Storage/StorageKeys'
|
||||
import { StorageServiceInterface } from '../../Storage/StorageServiceInterface'
|
||||
import { StorageValueModes } from '../../Storage/StorageTypes'
|
||||
import { RootKeyEncryptPayloadUseCase } from '../UseCase/RootEncryption/EncryptPayload'
|
||||
import { RootKeyDecryptPayloadUseCase } from '../UseCase/RootEncryption/DecryptPayload'
|
||||
import { AbstractService } from '../../Service/AbstractService'
|
||||
import { ItemManagerInterface } from '../../Item/ItemManagerInterface'
|
||||
import { MutatorClientInterface } from '../../Mutator/MutatorClientInterface'
|
||||
import { RootKeyManagerEvent } from './RootKeyManagerEvent'
|
||||
import { ValidatePasscodeResult } from './ValidatePasscodeResult'
|
||||
import { ValidateAccountPasswordResult } from './ValidateAccountPasswordResult'
|
||||
import { DecryptPayloads } from '../UseCase/DecryptPayloads/DecryptPayloads'
|
||||
import { EncryptPayloads } from '../UseCase/EncryptPayloads/EncryptPayloads'
|
||||
|
||||
export class RootKeyManager extends AbstractService<RootKeyManagerEvent> {
|
||||
private rootKey?: RootKeyInterface
|
||||
@@ -51,6 +51,8 @@ export class RootKeyManager extends AbstractService<RootKeyManagerEvent> {
|
||||
private mutator: MutatorClientInterface,
|
||||
private operators: OperatorManager,
|
||||
private identifier: ApplicationIdentifier,
|
||||
private encryptPayloadsUseCase: EncryptPayloads,
|
||||
private decryptPayloadsUseCase: DecryptPayloads,
|
||||
eventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(eventBus)
|
||||
@@ -249,8 +251,16 @@ export class RootKeyManager extends AbstractService<RootKeyManagerEvent> {
|
||||
|
||||
const payload = new DecryptedPayload(value)
|
||||
|
||||
const usecase = new RootKeyEncryptPayloadUseCase(this.operators)
|
||||
const wrappedKey = await usecase.executeOne(payload, wrappingKey)
|
||||
const wrappedKeysOrError = await this.encryptPayloadsUseCase.execute({
|
||||
payloads: [payload],
|
||||
key: wrappingKey,
|
||||
fallbackRootKey: this.getRootKey(),
|
||||
})
|
||||
if (wrappedKeysOrError.isFailed()) {
|
||||
throw Error(wrappedKeysOrError.getError())
|
||||
}
|
||||
const wrappedKey = wrappedKeysOrError.getValue()[0]
|
||||
|
||||
const wrappedKeyPayload = new EncryptedPayload({
|
||||
...payload.ejected(),
|
||||
...wrappedKey,
|
||||
@@ -273,8 +283,15 @@ export class RootKeyManager extends AbstractService<RootKeyManagerEvent> {
|
||||
|
||||
const wrappedKey = this.getWrappedRootKey()
|
||||
const payload = new EncryptedPayload(wrappedKey)
|
||||
const usecase = new RootKeyDecryptPayloadUseCase(this.operators)
|
||||
const decrypted = await usecase.executeOne<RootKeyContent>(payload, wrappingKey)
|
||||
const decryptedPayloadsOrError = await this.decryptPayloadsUseCase.execute<RootKeyContent>({
|
||||
payloads: [payload],
|
||||
key: wrappingKey,
|
||||
fallbackRootKey: this.getRootKey(),
|
||||
})
|
||||
if (decryptedPayloadsOrError.isFailed()) {
|
||||
throw Error(decryptedPayloadsOrError.getError())
|
||||
}
|
||||
const decrypted = decryptedPayloadsOrError.getValue()[0]
|
||||
|
||||
if (isErrorDecryptingParameters(decrypted)) {
|
||||
throw Error('Unable to decrypt root key with provided wrapping key.')
|
||||
@@ -433,8 +450,16 @@ export class RootKeyManager extends AbstractService<RootKeyManagerEvent> {
|
||||
* by attempting to decrypt account keys.
|
||||
*/
|
||||
const wrappedKeyPayload = new EncryptedPayload(wrappedRootKey)
|
||||
const usecase = new RootKeyDecryptPayloadUseCase(this.operators)
|
||||
const decrypted = await usecase.executeOne(wrappedKeyPayload, wrappingKey)
|
||||
const decryptedPayloadsOrError = await this.decryptPayloadsUseCase.execute({
|
||||
payloads: [wrappedKeyPayload],
|
||||
key: wrappingKey,
|
||||
fallbackRootKey: this.getRootKey(),
|
||||
})
|
||||
if (decryptedPayloadsOrError.isFailed()) {
|
||||
throw Error(decryptedPayloadsOrError.getError())
|
||||
}
|
||||
const decrypted = decryptedPayloadsOrError.getValue()[0]
|
||||
|
||||
return !isErrorDecryptingParameters(decrypted)
|
||||
} else {
|
||||
throw 'Unhandled case in validateWrappingKey'
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import {
|
||||
DecryptedParameters,
|
||||
ErrorDecryptingParameters,
|
||||
KeySystemKeyManagerInterface,
|
||||
OperatorManager,
|
||||
decryptPayload,
|
||||
} from '@standardnotes/encryption'
|
||||
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
|
||||
import {
|
||||
ContentTypeUsesKeySystemRootKeyEncryption,
|
||||
EncryptedPayloadInterface,
|
||||
ItemContent,
|
||||
KeySystemRootKeyInterface,
|
||||
RootKeyInterface,
|
||||
} from '@standardnotes/models'
|
||||
|
||||
import { DecryptPayloadsDTO } from './DecryptPayloadsDTO'
|
||||
|
||||
export class DecryptPayloads implements UseCaseInterface<(DecryptedParameters | ErrorDecryptingParameters)[]> {
|
||||
constructor(private operatorManager: OperatorManager, private keySystemKeyManager: KeySystemKeyManagerInterface) {}
|
||||
|
||||
async execute<C extends ItemContent = ItemContent>(
|
||||
dto: DecryptPayloadsDTO,
|
||||
): Promise<Result<(DecryptedParameters<C> | ErrorDecryptingParameters)[]>> {
|
||||
const decryptedOrErroredParameters = []
|
||||
for (const payload of dto.payloads) {
|
||||
const keyForPayloadOrError = this.getKeyForPayload({
|
||||
payload,
|
||||
existingKey: dto.key,
|
||||
fallbackRootKey: dto.fallbackRootKey,
|
||||
})
|
||||
if (keyForPayloadOrError.isFailed()) {
|
||||
const errorDecryptingParamteres: ErrorDecryptingParameters = {
|
||||
uuid: payload.uuid,
|
||||
errorDecrypting: true,
|
||||
waitingForKey: true,
|
||||
}
|
||||
decryptedOrErroredParameters.push(errorDecryptingParamteres)
|
||||
|
||||
continue
|
||||
}
|
||||
const key = keyForPayloadOrError.getValue()
|
||||
|
||||
decryptedOrErroredParameters.push(await decryptPayload<C>(payload, key, this.operatorManager))
|
||||
}
|
||||
|
||||
return Result.ok(decryptedOrErroredParameters)
|
||||
}
|
||||
|
||||
private getKeyForPayload(dto: {
|
||||
payload: EncryptedPayloadInterface
|
||||
existingKey?: RootKeyInterface | KeySystemRootKeyInterface
|
||||
fallbackRootKey?: RootKeyInterface
|
||||
}): Result<RootKeyInterface | KeySystemRootKeyInterface> {
|
||||
let key = dto.existingKey
|
||||
if (key === undefined) {
|
||||
if (ContentTypeUsesKeySystemRootKeyEncryption(dto.payload.content_type)) {
|
||||
if (!dto.payload.key_system_identifier) {
|
||||
return Result.fail('Key system root key encrypted payload is missing key_system_identifier')
|
||||
}
|
||||
key = this.keySystemKeyManager.getPrimaryKeySystemRootKey(dto.payload.key_system_identifier)
|
||||
} else {
|
||||
key = dto.fallbackRootKey
|
||||
}
|
||||
}
|
||||
|
||||
if (key === undefined) {
|
||||
return Result.fail('Attempting root key decryption with no root key')
|
||||
}
|
||||
|
||||
return Result.ok(key)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { EncryptedPayloadInterface, KeySystemRootKeyInterface, RootKeyInterface } from '@standardnotes/models'
|
||||
|
||||
export interface DecryptPayloadsDTO {
|
||||
payloads: EncryptedPayloadInterface[]
|
||||
key?: RootKeyInterface | KeySystemRootKeyInterface
|
||||
fallbackRootKey?: RootKeyInterface
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import {
|
||||
ContentTypeUsesKeySystemRootKeyEncryption,
|
||||
ContentTypeUsesRootKeyEncryption,
|
||||
DecryptedPayload,
|
||||
EncryptedPayload,
|
||||
PayloadEmitSource,
|
||||
SureFindPayload,
|
||||
} from '@standardnotes/models'
|
||||
import { isErrorDecryptingParameters } from '@standardnotes/encryption'
|
||||
import { UseCaseInterface, Result } from '@standardnotes/domain-core'
|
||||
|
||||
import { PayloadManagerInterface } from '../../../Payloads/PayloadManagerInterface'
|
||||
|
||||
import { DecryptPayloads } from '../DecryptPayloads/DecryptPayloads'
|
||||
|
||||
export class EmitDecryptedErroredPayloads implements UseCaseInterface<void> {
|
||||
constructor(private payloadsManager: PayloadManagerInterface, private decryptPayloadsUseCase: DecryptPayloads) {}
|
||||
|
||||
async execute(): Promise<Result<void>> {
|
||||
const erroredRootPayloads = this.payloadsManager.invalidPayloads.filter(
|
||||
(i) =>
|
||||
ContentTypeUsesRootKeyEncryption(i.content_type) || ContentTypeUsesKeySystemRootKeyEncryption(i.content_type),
|
||||
)
|
||||
if (erroredRootPayloads.length === 0) {
|
||||
return Result.fail('No errored payloads found')
|
||||
}
|
||||
|
||||
const decryptedPaylodsAndErrorsOrFail = await this.decryptPayloadsUseCase.execute({
|
||||
payloads: erroredRootPayloads,
|
||||
})
|
||||
if (decryptedPaylodsAndErrorsOrFail.isFailed()) {
|
||||
return Result.fail(decryptedPaylodsAndErrorsOrFail.getError())
|
||||
}
|
||||
const decryptedPaylodsAndErrors = decryptedPaylodsAndErrorsOrFail.getValue()
|
||||
|
||||
const decryptedPayloads = decryptedPaylodsAndErrors.map((params) => {
|
||||
const original = SureFindPayload(erroredRootPayloads, params.uuid)
|
||||
if (isErrorDecryptingParameters(params)) {
|
||||
return new EncryptedPayload({
|
||||
...original.ejected(),
|
||||
...params,
|
||||
})
|
||||
} else {
|
||||
return new DecryptedPayload({
|
||||
...original.ejected(),
|
||||
...params,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
await this.payloadsManager.emitPayloads(decryptedPayloads, PayloadEmitSource.LocalChanged)
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import {
|
||||
EncryptedOutputParameters,
|
||||
KeySystemKeyManagerInterface,
|
||||
OperatorManager,
|
||||
encryptPayload,
|
||||
} from '@standardnotes/encryption'
|
||||
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
|
||||
import {
|
||||
ContentTypeUsesKeySystemRootKeyEncryption,
|
||||
DecryptedPayloadInterface,
|
||||
KeySystemRootKeyInterface,
|
||||
RootKeyInterface,
|
||||
} from '@standardnotes/models'
|
||||
|
||||
import { EncryptPayloadsDTO } from './EncryptPayloadsDTO'
|
||||
|
||||
export class EncryptPayloads implements UseCaseInterface<EncryptedOutputParameters[]> {
|
||||
constructor(private operatorManager: OperatorManager, private keySystemKeyManager: KeySystemKeyManagerInterface) {}
|
||||
|
||||
async execute(dto: EncryptPayloadsDTO): Promise<Result<EncryptedOutputParameters[]>> {
|
||||
try {
|
||||
const encryptedPayloads = []
|
||||
for (const payload of dto.payloads) {
|
||||
const keyForPayloadOrError = this.getKeyForPayload({
|
||||
payload,
|
||||
existingKey: dto.key,
|
||||
fallbackRootKey: dto.fallbackRootKey,
|
||||
})
|
||||
if (keyForPayloadOrError.isFailed()) {
|
||||
return Result.fail(keyForPayloadOrError.getError())
|
||||
}
|
||||
const key = keyForPayloadOrError.getValue()
|
||||
|
||||
encryptedPayloads.push(await encryptPayload(payload, key, this.operatorManager, dto.signingKeyPair))
|
||||
}
|
||||
|
||||
return Result.ok(encryptedPayloads)
|
||||
} catch (error) {
|
||||
return Result.fail((error as Error).message)
|
||||
}
|
||||
}
|
||||
|
||||
private getKeyForPayload(dto: {
|
||||
payload: DecryptedPayloadInterface
|
||||
existingKey?: RootKeyInterface | KeySystemRootKeyInterface
|
||||
fallbackRootKey?: RootKeyInterface
|
||||
}): Result<RootKeyInterface | KeySystemRootKeyInterface> {
|
||||
let key = dto.existingKey
|
||||
if (key === undefined) {
|
||||
if (ContentTypeUsesKeySystemRootKeyEncryption(dto.payload.content_type)) {
|
||||
if (!dto.payload.key_system_identifier) {
|
||||
return Result.fail(
|
||||
`Key system-encrypted payload ${dto.payload.content_type}is missing a key_system_identifier`,
|
||||
)
|
||||
}
|
||||
key = this.keySystemKeyManager.getPrimaryKeySystemRootKey(dto.payload.key_system_identifier)
|
||||
} else {
|
||||
key = dto.fallbackRootKey
|
||||
}
|
||||
}
|
||||
|
||||
if (key === undefined) {
|
||||
return Result.fail('Attempting root key encryption with no root key')
|
||||
}
|
||||
|
||||
return Result.ok(key)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { DecryptedPayloadInterface, KeySystemRootKeyInterface, RootKeyInterface } from '@standardnotes/models'
|
||||
import { PkcKeyPair } from '@standardnotes/sncrypto-common'
|
||||
|
||||
export interface EncryptPayloadsDTO {
|
||||
payloads: DecryptedPayloadInterface[]
|
||||
key?: RootKeyInterface | KeySystemRootKeyInterface
|
||||
fallbackRootKey?: RootKeyInterface
|
||||
signingKeyPair?: PkcKeyPair
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import {
|
||||
ContentTypeUsesKeySystemRootKeyEncryption,
|
||||
ContentTypeUsesRootKeyEncryption,
|
||||
DecryptedPayload,
|
||||
EncryptedPayload,
|
||||
PayloadEmitSource,
|
||||
SureFindPayload,
|
||||
} from '@standardnotes/models'
|
||||
import { PayloadManagerInterface } from './../../../Payloads/PayloadManagerInterface'
|
||||
import { KeySystemKeyManagerInterface, OperatorManager, isErrorDecryptingParameters } from '@standardnotes/encryption'
|
||||
import { RootKeyDecryptPayloadWithKeyLookupUseCase } from './DecryptPayloadWithKeyLookup'
|
||||
import { RootKeyManager } from '../../RootKey/RootKeyManager'
|
||||
|
||||
export class DecryptErroredRootPayloadsUseCase {
|
||||
constructor(
|
||||
private payloads: PayloadManagerInterface,
|
||||
private operatorManager: OperatorManager,
|
||||
private keySystemKeyManager: KeySystemKeyManagerInterface,
|
||||
private rootKeyManager: RootKeyManager,
|
||||
) {}
|
||||
|
||||
async execute(): Promise<void> {
|
||||
const erroredRootPayloads = this.payloads.invalidPayloads.filter(
|
||||
(i) =>
|
||||
ContentTypeUsesRootKeyEncryption(i.content_type) || ContentTypeUsesKeySystemRootKeyEncryption(i.content_type),
|
||||
)
|
||||
if (erroredRootPayloads.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const usecase = new RootKeyDecryptPayloadWithKeyLookupUseCase(
|
||||
this.operatorManager,
|
||||
this.keySystemKeyManager,
|
||||
this.rootKeyManager,
|
||||
)
|
||||
const resultParams = await usecase.executeMany(erroredRootPayloads)
|
||||
|
||||
const decryptedPayloads = resultParams.map((params) => {
|
||||
const original = SureFindPayload(erroredRootPayloads, params.uuid)
|
||||
if (isErrorDecryptingParameters(params)) {
|
||||
return new EncryptedPayload({
|
||||
...original.ejected(),
|
||||
...params,
|
||||
})
|
||||
} else {
|
||||
return new DecryptedPayload({
|
||||
...original.ejected(),
|
||||
...params,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
await this.payloads.emitPayloads(decryptedPayloads, PayloadEmitSource.LocalChanged)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import {
|
||||
DecryptedParameters,
|
||||
ErrorDecryptingParameters,
|
||||
OperatorManager,
|
||||
decryptPayload,
|
||||
} from '@standardnotes/encryption'
|
||||
import {
|
||||
EncryptedPayloadInterface,
|
||||
ItemContent,
|
||||
KeySystemRootKeyInterface,
|
||||
RootKeyInterface,
|
||||
} from '@standardnotes/models'
|
||||
|
||||
export class RootKeyDecryptPayloadUseCase {
|
||||
constructor(private operatorManager: OperatorManager) {}
|
||||
|
||||
async executeOne<C extends ItemContent = ItemContent>(
|
||||
payload: EncryptedPayloadInterface,
|
||||
key: RootKeyInterface | KeySystemRootKeyInterface,
|
||||
): Promise<DecryptedParameters<C> | ErrorDecryptingParameters> {
|
||||
return decryptPayload(payload, key, this.operatorManager)
|
||||
}
|
||||
|
||||
async executeMany<C extends ItemContent = ItemContent>(
|
||||
payloads: EncryptedPayloadInterface[],
|
||||
key: RootKeyInterface | KeySystemRootKeyInterface,
|
||||
): Promise<(DecryptedParameters<C> | ErrorDecryptingParameters)[]> {
|
||||
return Promise.all(payloads.map((payload) => this.executeOne<C>(payload, key)))
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
import {
|
||||
DecryptedParameters,
|
||||
ErrorDecryptingParameters,
|
||||
KeySystemKeyManagerInterface,
|
||||
OperatorManager,
|
||||
} from '@standardnotes/encryption'
|
||||
import {
|
||||
ContentTypeUsesKeySystemRootKeyEncryption,
|
||||
EncryptedPayloadInterface,
|
||||
ItemContent,
|
||||
KeySystemRootKeyInterface,
|
||||
RootKeyInterface,
|
||||
} from '@standardnotes/models'
|
||||
|
||||
import { RootKeyDecryptPayloadUseCase } from './DecryptPayload'
|
||||
import { RootKeyManager } from '../../RootKey/RootKeyManager'
|
||||
|
||||
export class RootKeyDecryptPayloadWithKeyLookupUseCase {
|
||||
constructor(
|
||||
private operatorManager: OperatorManager,
|
||||
private keySystemKeyManager: KeySystemKeyManagerInterface,
|
||||
private rootKeyManager: RootKeyManager,
|
||||
) {}
|
||||
|
||||
async executeOne<C extends ItemContent = ItemContent>(
|
||||
payload: EncryptedPayloadInterface,
|
||||
): Promise<DecryptedParameters<C> | ErrorDecryptingParameters> {
|
||||
let key: RootKeyInterface | KeySystemRootKeyInterface | undefined
|
||||
if (ContentTypeUsesKeySystemRootKeyEncryption(payload.content_type)) {
|
||||
if (!payload.key_system_identifier) {
|
||||
throw Error('Key system root key encrypted payload is missing key_system_identifier')
|
||||
}
|
||||
key = this.keySystemKeyManager.getPrimaryKeySystemRootKey(payload.key_system_identifier)
|
||||
} else {
|
||||
key = this.rootKeyManager.getRootKey()
|
||||
}
|
||||
|
||||
if (key == undefined) {
|
||||
return {
|
||||
uuid: payload.uuid,
|
||||
errorDecrypting: true,
|
||||
waitingForKey: true,
|
||||
}
|
||||
}
|
||||
|
||||
const usecase = new RootKeyDecryptPayloadUseCase(this.operatorManager)
|
||||
|
||||
return usecase.executeOne(payload, key)
|
||||
}
|
||||
|
||||
async executeMany<C extends ItemContent = ItemContent>(
|
||||
payloads: EncryptedPayloadInterface[],
|
||||
): Promise<(DecryptedParameters<C> | ErrorDecryptingParameters)[]> {
|
||||
return Promise.all(payloads.map((payload) => this.executeOne<C>(payload)))
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { EncryptedOutputParameters, OperatorManager, encryptPayload } from '@standardnotes/encryption'
|
||||
import { DecryptedPayloadInterface, KeySystemRootKeyInterface, RootKeyInterface } from '@standardnotes/models'
|
||||
import { PkcKeyPair } from '@standardnotes/sncrypto-common'
|
||||
|
||||
export class RootKeyEncryptPayloadUseCase {
|
||||
constructor(private operatorManager: OperatorManager) {}
|
||||
|
||||
async executeOne(
|
||||
payload: DecryptedPayloadInterface,
|
||||
key: RootKeyInterface | KeySystemRootKeyInterface,
|
||||
signingKeyPair?: PkcKeyPair,
|
||||
): Promise<EncryptedOutputParameters> {
|
||||
return encryptPayload(payload, key, this.operatorManager, signingKeyPair)
|
||||
}
|
||||
|
||||
async executeMany(
|
||||
payloads: DecryptedPayloadInterface[],
|
||||
key: RootKeyInterface | KeySystemRootKeyInterface,
|
||||
signingKeyPair?: PkcKeyPair,
|
||||
): Promise<EncryptedOutputParameters[]> {
|
||||
return Promise.all(payloads.map((payload) => this.executeOne(payload, key, signingKeyPair)))
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import { EncryptedOutputParameters, KeySystemKeyManagerInterface, OperatorManager } from '@standardnotes/encryption'
|
||||
import {
|
||||
ContentTypeUsesKeySystemRootKeyEncryption,
|
||||
DecryptedPayloadInterface,
|
||||
KeySystemRootKeyInterface,
|
||||
RootKeyInterface,
|
||||
} from '@standardnotes/models'
|
||||
import { PkcKeyPair } from '@standardnotes/sncrypto-common'
|
||||
|
||||
import { RootKeyEncryptPayloadUseCase } from './EncryptPayload'
|
||||
import { RootKeyManager } from '../../RootKey/RootKeyManager'
|
||||
|
||||
export class RootKeyEncryptPayloadWithKeyLookupUseCase {
|
||||
constructor(
|
||||
private operatorManager: OperatorManager,
|
||||
private keySystemKeyManager: KeySystemKeyManagerInterface,
|
||||
private rootKeyManager: RootKeyManager,
|
||||
) {}
|
||||
|
||||
async executeOne(
|
||||
payload: DecryptedPayloadInterface,
|
||||
signingKeyPair?: PkcKeyPair,
|
||||
): Promise<EncryptedOutputParameters> {
|
||||
let key: RootKeyInterface | KeySystemRootKeyInterface | undefined
|
||||
if (ContentTypeUsesKeySystemRootKeyEncryption(payload.content_type)) {
|
||||
if (!payload.key_system_identifier) {
|
||||
throw Error(`Key system-encrypted payload ${payload.content_type}is missing a key_system_identifier`)
|
||||
}
|
||||
key = this.keySystemKeyManager.getPrimaryKeySystemRootKey(payload.key_system_identifier)
|
||||
} else {
|
||||
key = this.rootKeyManager.getRootKey()
|
||||
}
|
||||
|
||||
if (key == undefined) {
|
||||
throw Error('Attempting root key encryption with no root key')
|
||||
}
|
||||
|
||||
const usecase = new RootKeyEncryptPayloadUseCase(this.operatorManager)
|
||||
return usecase.executeOne(payload, key, signingKeyPair)
|
||||
}
|
||||
|
||||
async executeMany(
|
||||
payloads: DecryptedPayloadInterface[],
|
||||
signingKeyPair?: PkcKeyPair,
|
||||
): Promise<EncryptedOutputParameters[]> {
|
||||
return Promise.all(payloads.map((payload) => this.executeOne(payload, signingKeyPair)))
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,7 @@ import { SendSharedVaultMetadataChangedMessageToAll } from './UseCase/SendShared
|
||||
import { ConvertToSharedVaultUseCase } from './UseCase/ConvertToSharedVault'
|
||||
import { GetVaultUseCase } from '../Vaults/UseCase/GetVault'
|
||||
import { ContentType } from '@standardnotes/domain-core'
|
||||
import { EmitDecryptedErroredPayloads } from '../Encryption/UseCase/EmitDecryptedErroredPayloads/EmitDecryptedErroredPayloads'
|
||||
|
||||
export class SharedVaultService
|
||||
extends AbstractService<SharedVaultServiceEvent, SharedVaultServiceEventPayload>
|
||||
@@ -87,6 +88,7 @@ export class SharedVaultService
|
||||
private files: FilesClientInterface,
|
||||
private vaults: VaultServiceInterface,
|
||||
private storage: StorageServiceInterface,
|
||||
private emitDecryptedErroredPayloadsUseCase: EmitDecryptedErroredPayloads,
|
||||
eventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(eventBus)
|
||||
@@ -399,15 +401,14 @@ export class SharedVaultService
|
||||
|
||||
void this.sync.sync()
|
||||
|
||||
await this.decryptErroredItemsAfterInviteAccept()
|
||||
const emitedOrFailed = await this.emitDecryptedErroredPayloadsUseCase.execute()
|
||||
if (emitedOrFailed.isFailed()) {
|
||||
throw new Error(emitedOrFailed.getError())
|
||||
}
|
||||
|
||||
await this.sync.syncSharedVaultsFromScratch([pendingInvite.invite.shared_vault_uuid])
|
||||
}
|
||||
|
||||
private async decryptErroredItemsAfterInviteAccept(): Promise<void> {
|
||||
await this.encryption.decryptErroredPayloads()
|
||||
}
|
||||
|
||||
public async getInvitableContactsForSharedVault(
|
||||
sharedVault: SharedVaultListingInterface,
|
||||
): Promise<TrustedContactInterface[]> {
|
||||
|
||||
@@ -36,6 +36,7 @@ import { AccountEventData } from './AccountEventData'
|
||||
import { AccountEvent } from './AccountEvent'
|
||||
import { SignedInOrRegisteredEventPayload } from './SignedInOrRegisteredEventPayload'
|
||||
import { CredentialsChangeFunctionResponse } from './CredentialsChangeFunctionResponse'
|
||||
import { EmitDecryptedErroredPayloads } from '../Encryption/UseCase/EmitDecryptedErroredPayloads/EmitDecryptedErroredPayloads'
|
||||
|
||||
export class UserService
|
||||
extends AbstractService<AccountEvent, AccountEventData>
|
||||
@@ -57,6 +58,7 @@ export class UserService
|
||||
private challengeService: ChallengeServiceInterface,
|
||||
private protectionService: ProtectionsClientInterface,
|
||||
private userApiService: UserApiServiceInterface,
|
||||
private emitDecryptedErroredPayloadsUseCase: EmitDecryptedErroredPayloads,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
@@ -87,14 +89,14 @@ export class UserService
|
||||
})
|
||||
.then(() => {
|
||||
if (!payload.awaitSync) {
|
||||
void this.encryptionService.decryptErroredPayloads()
|
||||
void this.emitDecryptedErroredPayloadsUseCase.execute()
|
||||
}
|
||||
})
|
||||
|
||||
if (payload.awaitSync) {
|
||||
await syncPromise
|
||||
|
||||
await this.encryptionService.decryptErroredPayloads()
|
||||
await this.emitDecryptedErroredPayloadsUseCase.execute()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import { ChangeVaultKeyOptionsUseCase } from './UseCase/ChangeVaultKeyOptions'
|
||||
import { MutatorClientInterface } from '../Mutator/MutatorClientInterface'
|
||||
import { AlertService } from '../Alert/AlertService'
|
||||
import { ContentType } from '@standardnotes/domain-core'
|
||||
import { EmitDecryptedErroredPayloads } from '../Encryption/UseCase/EmitDecryptedErroredPayloads/EmitDecryptedErroredPayloads'
|
||||
|
||||
export class VaultService
|
||||
extends AbstractService<VaultServiceEvent, VaultServiceEventPayload[VaultServiceEvent]>
|
||||
@@ -43,6 +44,7 @@ export class VaultService
|
||||
private encryption: EncryptionProviderInterface,
|
||||
private files: FilesClientInterface,
|
||||
private alerts: AlertService,
|
||||
private emitDecryptedErroredPayloadsUseCase: EmitDecryptedErroredPayloads,
|
||||
eventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(eventBus)
|
||||
@@ -271,7 +273,10 @@ export class VaultService
|
||||
|
||||
this.encryption.keys.intakeNonPersistentKeySystemRootKey(derivedRootKey, vault.keyStorageMode)
|
||||
|
||||
await this.encryption.decryptErroredPayloads()
|
||||
const emitedOrFailed = await this.emitDecryptedErroredPayloadsUseCase.execute()
|
||||
if (emitedOrFailed.isFailed()) {
|
||||
throw emitedOrFailed.getError()
|
||||
}
|
||||
|
||||
if (this.computeVaultLockState(vault) === 'locked') {
|
||||
this.encryption.keys.undoIntakeNonPersistentKeySystemRootKey(vault.systemIdentifier)
|
||||
|
||||
@@ -15,6 +15,7 @@ export * from './Application/DeinitSource'
|
||||
|
||||
export * from './AsymmetricMessage/AsymmetricMessageService'
|
||||
export * from './AsymmetricMessage/AsymmetricMessageServiceInterface'
|
||||
export * from './AsymmetricMessage/UseCase/HandleTrustedSharedVaultRootKeyChangedMessage'
|
||||
|
||||
export * from './Auth/AuthClientInterface'
|
||||
export * from './Auth/AuthManager'
|
||||
@@ -68,6 +69,12 @@ export * from './Encryption/EncryptionService'
|
||||
export * from './Encryption/EncryptionServiceEvent'
|
||||
export * from './Encryption/Functions'
|
||||
export * from './Encryption/ItemsEncryption'
|
||||
export * from './Encryption/RootKey/RootKeyManager'
|
||||
export * from './Encryption/UseCase/DecryptPayloads/DecryptPayloads'
|
||||
export * from './Encryption/UseCase/DecryptPayloads/DecryptPayloadsDTO'
|
||||
export * from './Encryption/UseCase/EmitDecryptedErroredPayloads/EmitDecryptedErroredPayloads'
|
||||
export * from './Encryption/UseCase/EncryptPayloads/EncryptPayloads'
|
||||
export * from './Encryption/UseCase/EncryptPayloads/EncryptPayloadsDTO'
|
||||
|
||||
export * from './Event/ApplicationEvent'
|
||||
export * from './Event/ApplicationEventCallback'
|
||||
|
||||
@@ -68,6 +68,11 @@ import {
|
||||
RevisionClientInterface,
|
||||
RevisionManager,
|
||||
ApiServiceEvent,
|
||||
DecryptPayloads,
|
||||
EncryptPayloads,
|
||||
RootKeyManager,
|
||||
HandleTrustedSharedVaultRootKeyChangedMessage,
|
||||
EmitDecryptedErroredPayloads,
|
||||
} from '@standardnotes/services'
|
||||
import {
|
||||
BackupServiceInterface,
|
||||
@@ -75,7 +80,7 @@ import {
|
||||
FileBackupsDevice,
|
||||
FilesClientInterface,
|
||||
} from '@standardnotes/files'
|
||||
import { ComputePrivateUsername } from '@standardnotes/encryption'
|
||||
import { ComputePrivateUsername, OperatorManager } from '@standardnotes/encryption'
|
||||
import { useBoolean } from '@standardnotes/utils'
|
||||
import {
|
||||
BackupFile,
|
||||
@@ -189,6 +194,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
private declare authManager: AuthClientInterface
|
||||
private declare revisionManager: RevisionClientInterface
|
||||
private homeServerService?: ExternalServices.HomeServerService
|
||||
private declare operatorManager: OperatorManager
|
||||
|
||||
private declare _signInWithRecoveryCodes: SignInWithRecoveryCodes
|
||||
private declare _getRecoveryCodes: GetRecoveryCodes
|
||||
@@ -200,6 +206,9 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
private declare _listRevisions: ListRevisions
|
||||
private declare _getRevision: GetRevision
|
||||
private declare _deleteRevision: DeleteRevision
|
||||
private declare _encryptPayloads: EncryptPayloads
|
||||
private declare _decryptPayloads: DecryptPayloads
|
||||
private declare _emitDecryptedErroredPayloads: EmitDecryptedErroredPayloads
|
||||
|
||||
public internalEventBus!: ExternalServices.InternalEventBusInterface
|
||||
|
||||
@@ -1308,6 +1317,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
;(this.httpService as unknown) = undefined
|
||||
;(this.payloadManager as unknown) = undefined
|
||||
;(this.encryptionService as unknown) = undefined
|
||||
;(this.operatorManager as unknown) = undefined
|
||||
;(this.diskStorageService as unknown) = undefined
|
||||
;(this.inMemoryStore as unknown) = undefined
|
||||
;(this.apiService as unknown) = undefined
|
||||
@@ -1356,6 +1366,9 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
;(this._listRevisions as unknown) = undefined
|
||||
;(this._getRevision as unknown) = undefined
|
||||
;(this._deleteRevision as unknown) = undefined
|
||||
;(this._encryptPayloads as unknown) = undefined
|
||||
;(this._decryptPayloads as unknown) = undefined
|
||||
;(this._emitDecryptedErroredPayloads as unknown) = undefined
|
||||
;(this.vaultService as unknown) = undefined
|
||||
;(this.contactService as unknown) = undefined
|
||||
;(this.sharedVaultService as unknown) = undefined
|
||||
@@ -1389,13 +1402,20 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
}
|
||||
|
||||
private createAsymmetricMessageService() {
|
||||
const handleTrustedSharedVaultRootKeyChangedMessageUseCase = new HandleTrustedSharedVaultRootKeyChangedMessage(
|
||||
this.mutator,
|
||||
this.itemManager,
|
||||
this.syncService,
|
||||
this._emitDecryptedErroredPayloads,
|
||||
)
|
||||
|
||||
this.asymmetricMessageService = new ExternalServices.AsymmetricMessageService(
|
||||
this.httpService,
|
||||
this.encryptionService,
|
||||
this.contacts,
|
||||
this.itemManager,
|
||||
this.mutator,
|
||||
this.syncService,
|
||||
handleTrustedSharedVaultRootKeyChangedMessageUseCase,
|
||||
this.internalEventBus,
|
||||
)
|
||||
this.services.push(this.asymmetricMessageService)
|
||||
@@ -1429,6 +1449,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
this.files,
|
||||
this.vaults,
|
||||
this.storage,
|
||||
this._emitDecryptedErroredPayloads,
|
||||
this.internalEventBus,
|
||||
)
|
||||
this.services.push(this.sharedVaultService)
|
||||
@@ -1442,6 +1463,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
this.encryptionService,
|
||||
this.files,
|
||||
this.alertService,
|
||||
this._emitDecryptedErroredPayloads,
|
||||
this.internalEventBus,
|
||||
)
|
||||
|
||||
@@ -1573,6 +1595,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
this.challengeService,
|
||||
this.protectionService,
|
||||
this.userApiService,
|
||||
this._emitDecryptedErroredPayloads,
|
||||
this.internalEventBus,
|
||||
)
|
||||
this.serviceObservers.push(
|
||||
@@ -1727,6 +1750,26 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
}
|
||||
|
||||
private createProtocolService() {
|
||||
this.operatorManager = new OperatorManager(this.options.crypto)
|
||||
|
||||
this._decryptPayloads = new DecryptPayloads(this.operatorManager, this.keySystemKeyManager)
|
||||
|
||||
this._encryptPayloads = new EncryptPayloads(this.operatorManager, this.keySystemKeyManager)
|
||||
|
||||
this._emitDecryptedErroredPayloads = new EmitDecryptedErroredPayloads(this.payloadManager, this._decryptPayloads)
|
||||
|
||||
const rootKeyManager = new RootKeyManager(
|
||||
this.deviceInterface,
|
||||
this.diskStorageService,
|
||||
this.itemManager,
|
||||
this.mutator,
|
||||
this.operatorManager,
|
||||
this.identifier,
|
||||
this._encryptPayloads,
|
||||
this._decryptPayloads,
|
||||
this.internalEventBus,
|
||||
)
|
||||
|
||||
this.encryptionService = new EncryptionService(
|
||||
this.itemManager,
|
||||
this.mutator,
|
||||
@@ -1734,8 +1777,11 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
this.deviceInterface,
|
||||
this.diskStorageService,
|
||||
this.keySystemKeyManager,
|
||||
rootKeyManager,
|
||||
this.identifier,
|
||||
this.options.crypto,
|
||||
this._encryptPayloads,
|
||||
this._decryptPayloads,
|
||||
this.operatorManager,
|
||||
this.internalEventBus,
|
||||
)
|
||||
this.serviceObservers.push(
|
||||
@@ -1788,6 +1834,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
||||
this.sessionStorageMapper,
|
||||
this.legacySessionStorageMapper,
|
||||
this.identifier,
|
||||
this.options.crypto,
|
||||
this.internalEventBus,
|
||||
)
|
||||
this.serviceObservers.push(
|
||||
|
||||
@@ -65,6 +65,7 @@ import {
|
||||
UserApiServiceInterface,
|
||||
UserRegistrationResponseBody,
|
||||
} from '@standardnotes/api'
|
||||
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
||||
|
||||
export const MINIMUM_PASSWORD_LENGTH = 8
|
||||
export const MissingAccountParams = 'missing-params'
|
||||
@@ -98,6 +99,7 @@ export class SNSessionManager
|
||||
private sessionStorageMapper: MapperInterface<Session, Record<string, unknown>>,
|
||||
private legacySessionStorageMapper: MapperInterface<LegacySession, Record<string, unknown>>,
|
||||
private workspaceIdentifier: string,
|
||||
private crypto: PureCryptoInterface,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
@@ -694,7 +696,7 @@ export class SNSessionManager
|
||||
}
|
||||
|
||||
private decodeDemoShareToken(token: Base64String): ShareToken {
|
||||
const jsonString = this.encryptionService.crypto.base64Decode(token)
|
||||
const jsonString = this.crypto.base64Decode(token)
|
||||
return JSON.parse(jsonString)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user