feat(encryption): refactor circular dependencies on services
This commit is contained in:
@@ -39,7 +39,6 @@
|
||||
"@standardnotes/common": "^1.23.1",
|
||||
"@standardnotes/models": "workspace:*",
|
||||
"@standardnotes/responses": "workspace:*",
|
||||
"@standardnotes/services": "workspace:*",
|
||||
"@standardnotes/sncrypto-common": "workspace:*",
|
||||
"@standardnotes/utils": "workspace:*",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import * as Models from '@standardnotes/models'
|
||||
import {
|
||||
DecryptedPayloadInterface,
|
||||
ItemsKeyInterface,
|
||||
RootKeyInterface,
|
||||
ItemContent,
|
||||
EncryptedPayloadInterface,
|
||||
} from '@standardnotes/models'
|
||||
import {
|
||||
DecryptedParameters,
|
||||
EncryptedParameters,
|
||||
@@ -9,8 +15,8 @@ import { isAsyncOperator } from './Functions'
|
||||
import { OperatorManager } from './OperatorManager'
|
||||
|
||||
export async function encryptPayload(
|
||||
payload: Models.DecryptedPayloadInterface,
|
||||
key: Models.ItemsKeyInterface | Models.RootKeyInterface,
|
||||
payload: DecryptedPayloadInterface,
|
||||
key: ItemsKeyInterface | RootKeyInterface,
|
||||
operatorManager: OperatorManager,
|
||||
): Promise<EncryptedParameters> {
|
||||
const operator = operatorManager.operatorForVersion(key.keyVersion)
|
||||
@@ -29,9 +35,9 @@ export async function encryptPayload(
|
||||
return encryptionParameters
|
||||
}
|
||||
|
||||
export async function decryptPayload<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payload: Models.EncryptedPayloadInterface,
|
||||
key: Models.ItemsKeyInterface | Models.RootKeyInterface,
|
||||
export async function decryptPayload<C extends ItemContent = ItemContent>(
|
||||
payload: EncryptedPayloadInterface,
|
||||
key: ItemsKeyInterface | RootKeyInterface,
|
||||
operatorManager: OperatorManager,
|
||||
): Promise<DecryptedParameters<C> | ErrorDecryptingParameters> {
|
||||
const operator = operatorManager.operatorForVersion(payload.version)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export enum RootKeyServiceEvent {
|
||||
RootKeyStatusChanged = 'RootKeyStatusChanged',
|
||||
}
|
||||
22
packages/encryption/src/Domain/Types/EncryptedParameters.d.ts
vendored
Normal file
22
packages/encryption/src/Domain/Types/EncryptedParameters.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ProtocolVersion } from '@standardnotes/common';
|
||||
import { EncryptedPayloadInterface, ItemContent } from '@standardnotes/models';
|
||||
export declare type EncryptedParameters = {
|
||||
uuid: string;
|
||||
content: string;
|
||||
items_key_id: string | undefined;
|
||||
enc_item_key: string;
|
||||
version: ProtocolVersion;
|
||||
/** @deprecated */
|
||||
auth_hash?: string;
|
||||
};
|
||||
export declare type DecryptedParameters<C extends ItemContent = ItemContent> = {
|
||||
uuid: string;
|
||||
content: C;
|
||||
};
|
||||
export declare type ErrorDecryptingParameters = {
|
||||
uuid: string;
|
||||
errorDecrypting: true;
|
||||
waitingForKey?: boolean;
|
||||
};
|
||||
export declare function isErrorDecryptingParameters(x: EncryptedParameters | DecryptedParameters | ErrorDecryptingParameters): x is ErrorDecryptingParameters;
|
||||
export declare function encryptedParametersFromPayload(payload: EncryptedPayloadInterface): EncryptedParameters;
|
||||
18
packages/encryption/src/Domain/Types/EncryptedParameters.js
Normal file
18
packages/encryption/src/Domain/Types/EncryptedParameters.js
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.encryptedParametersFromPayload = exports.isErrorDecryptingParameters = void 0;
|
||||
function isErrorDecryptingParameters(x) {
|
||||
return x.errorDecrypting;
|
||||
}
|
||||
exports.isErrorDecryptingParameters = isErrorDecryptingParameters;
|
||||
function encryptedParametersFromPayload(payload) {
|
||||
return {
|
||||
uuid: payload.uuid,
|
||||
content: payload.content,
|
||||
items_key_id: payload.items_key_id,
|
||||
enc_item_key: payload.enc_item_key,
|
||||
version: payload.version,
|
||||
auth_hash: payload.auth_hash,
|
||||
};
|
||||
}
|
||||
exports.encryptedParametersFromPayload = encryptedParametersFromPayload;
|
||||
@@ -1,5 +1,4 @@
|
||||
export * from './Algorithm'
|
||||
export * from './Backups/BackupFileDecryptor'
|
||||
export * from './Backups/BackupFileType'
|
||||
export * from './Keys/ItemsKey/ItemsKey'
|
||||
export * from './Keys/ItemsKey/ItemsKeyMutator'
|
||||
@@ -10,7 +9,6 @@ export * from './Keys/RootKey/ProtocolVersionForKeyParams'
|
||||
export * from './Keys/RootKey/RootKey'
|
||||
export * from './Keys/RootKey/RootKeyParams'
|
||||
export * from './Keys/RootKey/ValidKeyParamsKeys'
|
||||
export * from './Keys/Utils/DecryptItemsKey'
|
||||
export * from './Keys/Utils/KeyRecoveryStrings'
|
||||
export * from './Operator/001/Operator001'
|
||||
export * from './Operator/002/Operator002'
|
||||
@@ -21,11 +19,9 @@ export * from './Operator/Operator'
|
||||
export * from './Operator/OperatorManager'
|
||||
export * from './Operator/OperatorWrapper'
|
||||
export * from './Service/Encryption/EncryptionProvider'
|
||||
export * from './Service/Encryption/EncryptionService'
|
||||
export * from './Service/Functions'
|
||||
export * from './Service/Items/ItemsEncryption'
|
||||
export * from './Service/RootKey/KeyMode'
|
||||
export * from './Service/RootKey/RootKeyEncryption'
|
||||
export * from './Service/RootKey/RootKeyServiceEvent'
|
||||
export * from './Split/AbstractKeySplit'
|
||||
export * from './Split/EncryptionSplit'
|
||||
export * from './Split/EncryptionTypeSplit'
|
||||
|
||||
@@ -5,4 +5,3 @@ export * from './Streaming/StreamingReader'
|
||||
export * from './Streaming/StreamingSaver'
|
||||
export * from './Streaming/StreamingApi'
|
||||
export * from './utils'
|
||||
export * from './Cache/FileMemoryCache'
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { EncryptedBytes } from '@standardnotes/files'
|
||||
|
||||
import { EncryptedBytes } from '../Types/EncryptedBytes'
|
||||
import { FileMemoryCache } from './FileMemoryCache'
|
||||
|
||||
describe('file memory cache', () => {
|
||||
@@ -1,6 +1,7 @@
|
||||
import { removeFromArray } from '@standardnotes/utils'
|
||||
import { Uuid } from '@standardnotes/common'
|
||||
import { EncryptedBytes } from '@standardnotes/files'
|
||||
|
||||
import { EncryptedBytes } from '../Types/EncryptedBytes'
|
||||
|
||||
export class FileMemoryCache {
|
||||
private cache: Record<Uuid, EncryptedBytes> = {}
|
||||
@@ -5,6 +5,7 @@ export * from './Api/FileSystemApi'
|
||||
export * from './Api/FileSystemNoSelection'
|
||||
export * from './Api/FileSystemResult'
|
||||
export * from './Api/FilesApiInterface'
|
||||
export * from './Cache/FileMemoryCache'
|
||||
export * from './Chunker/ByteChunker'
|
||||
export * from './Chunker/OnChunkCallback'
|
||||
export * from './Chunker/OrderedByteChunker'
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"dependencies": {
|
||||
"@standardnotes/auth": "^3.19.4",
|
||||
"@standardnotes/common": "^1.30.0",
|
||||
"@standardnotes/encryption": "workspace:^",
|
||||
"@standardnotes/files": "workspace:^",
|
||||
"@standardnotes/models": "workspace:^",
|
||||
"@standardnotes/responses": "workspace:*",
|
||||
|
||||
@@ -2,8 +2,7 @@ import { ContentType, Uuid } from '@standardnotes/common'
|
||||
import { EncryptionProvider } from '@standardnotes/encryption'
|
||||
import { PayloadEmitSource, FileItem, CreateEncryptedBackupFileContextPayload } from '@standardnotes/models'
|
||||
import { ClientDisplayableError } from '@standardnotes/responses'
|
||||
import { FileBackupMetadataFile, FileBackupsDevice, FileBackupsMapping } from '../Device/FileBackupsDevice'
|
||||
import { FilesApiInterface } from '@standardnotes/files'
|
||||
import { FilesApiInterface, FileBackupMetadataFile, FileBackupsDevice, FileBackupsMapping } from '@standardnotes/files'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
|
||||
import { AbstractService } from '../Service/AbstractService'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DecryptedTransferPayload } from '@standardnotes/models'
|
||||
import { FileBackupsDevice } from './FileBackupsDevice'
|
||||
import { FileBackupsDevice } from '@standardnotes/files'
|
||||
|
||||
export interface WebClientRequiresDesktopMethods extends FileBackupsDevice {
|
||||
localBackupsCount(): Promise<number>
|
||||
|
||||
@@ -5,6 +5,15 @@ import {
|
||||
leftVersionGreaterThanOrEqualToRight,
|
||||
ProtocolVersion,
|
||||
} from '@standardnotes/common'
|
||||
import {
|
||||
BackupFileType,
|
||||
ContentTypeUsesRootKeyEncryption,
|
||||
CreateAnyKeyParams,
|
||||
isItemsKey,
|
||||
SNItemsKey,
|
||||
SNRootKey,
|
||||
SNRootKeyParams,
|
||||
} from '@standardnotes/encryption'
|
||||
import {
|
||||
BackupFile,
|
||||
CreateDecryptedItemFromPayload,
|
||||
@@ -23,13 +32,7 @@ import {
|
||||
} from '@standardnotes/models'
|
||||
import { ClientDisplayableError } from '@standardnotes/responses'
|
||||
import { extendArray } from '@standardnotes/utils'
|
||||
import { isItemsKey, SNItemsKey } from '../Keys/ItemsKey/ItemsKey'
|
||||
import { ContentTypeUsesRootKeyEncryption } from '../Keys/RootKey/Functions'
|
||||
import { CreateAnyKeyParams } from '../Keys/RootKey/KeyParamsFunctions'
|
||||
import { SNRootKey } from '../Keys/RootKey/RootKey'
|
||||
import { SNRootKeyParams } from '../Keys/RootKey/RootKeyParams'
|
||||
import { EncryptionService } from '../Service/Encryption/EncryptionService'
|
||||
import { BackupFileType } from './BackupFileType'
|
||||
import { EncryptionService } from './EncryptionService'
|
||||
|
||||
export async function DecryptBackupFile(
|
||||
file: BackupFile,
|
||||
@@ -1,53 +1,77 @@
|
||||
import * as Common from '@standardnotes/common'
|
||||
import * as Models from '@standardnotes/models'
|
||||
import {
|
||||
CreateAnyKeyParams,
|
||||
CreateEncryptionSplitWithKeyLookup,
|
||||
DecryptedParameters,
|
||||
EncryptedParameters,
|
||||
encryptedParametersFromPayload,
|
||||
EncryptionProvider,
|
||||
ErrorDecryptingParameters,
|
||||
findDefaultItemsKey,
|
||||
FindPayloadInDecryptionSplit,
|
||||
FindPayloadInEncryptionSplit,
|
||||
isErrorDecryptingParameters,
|
||||
ItemAuthenticatedData,
|
||||
KeyedDecryptionSplit,
|
||||
KeyedEncryptionSplit,
|
||||
KeyMode,
|
||||
LegacyAttachedData,
|
||||
OperatorManager,
|
||||
RootKeyEncryptedAuthenticatedData,
|
||||
RootKeyServiceEvent,
|
||||
SNRootKey,
|
||||
SNRootKeyParams,
|
||||
SplitPayloadsByEncryptionType,
|
||||
V001Algorithm,
|
||||
V002Algorithm,
|
||||
} from '@standardnotes/encryption'
|
||||
import {
|
||||
BackupFile,
|
||||
CreateDecryptedBackupFileContextPayload,
|
||||
CreateEncryptedBackupFileContextPayload,
|
||||
DecryptedPayload,
|
||||
DecryptedPayloadInterface,
|
||||
EncryptedPayload,
|
||||
EncryptedPayloadInterface,
|
||||
isDecryptedPayload,
|
||||
isEncryptedPayload,
|
||||
ItemContent,
|
||||
ItemsKeyInterface,
|
||||
RootKeyInterface,
|
||||
} from '@standardnotes/models'
|
||||
import { ClientDisplayableError } from '@standardnotes/responses'
|
||||
import * as Services from '@standardnotes/services'
|
||||
import { DiagnosticInfo } from '@standardnotes/services'
|
||||
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
||||
import * as Utils from '@standardnotes/utils'
|
||||
import { isNotUndefined } from '@standardnotes/utils'
|
||||
import { V001Algorithm, V002Algorithm } from '../../Algorithm'
|
||||
import { DecryptBackupFile } from '../../Backups/BackupFileDecryptor'
|
||||
import { CreateAnyKeyParams } from '../../Keys/RootKey/KeyParamsFunctions'
|
||||
import { SNRootKey } from '../../Keys/RootKey/RootKey'
|
||||
import { SNRootKeyParams } from '../../Keys/RootKey/RootKeyParams'
|
||||
import { OperatorManager } from '../../Operator/OperatorManager'
|
||||
import {
|
||||
CreateEncryptionSplitWithKeyLookup,
|
||||
FindPayloadInDecryptionSplit,
|
||||
FindPayloadInEncryptionSplit,
|
||||
} from '../../Split/EncryptionSplit'
|
||||
import { SplitPayloadsByEncryptionType } from '../../Split/Functions'
|
||||
import { KeyedDecryptionSplit } from '../../Split/KeyedDecryptionSplit'
|
||||
import { KeyedEncryptionSplit } from '../../Split/KeyedEncryptionSplit'
|
||||
extendArray,
|
||||
isNotUndefined,
|
||||
isNullOrUndefined,
|
||||
isReactNativeEnvironment,
|
||||
isWebCryptoAvailable,
|
||||
UuidGenerator,
|
||||
} from '@standardnotes/utils'
|
||||
import {
|
||||
DecryptedParameters,
|
||||
EncryptedParameters,
|
||||
encryptedParametersFromPayload,
|
||||
ErrorDecryptingParameters,
|
||||
isErrorDecryptingParameters,
|
||||
} from '../../Types/EncryptedParameters'
|
||||
import { ItemAuthenticatedData } from '../../Types/ItemAuthenticatedData'
|
||||
import { LegacyAttachedData } from '../../Types/LegacyAttachedData'
|
||||
import { RootKeyEncryptedAuthenticatedData } from '../../Types/RootKeyEncryptedAuthenticatedData'
|
||||
import { findDefaultItemsKey } from '../Functions'
|
||||
import { ItemsEncryptionService } from '../Items/ItemsEncryption'
|
||||
import { KeyMode } from '../RootKey/KeyMode'
|
||||
import * as RootKeyEncryption from '../RootKey/RootKeyEncryption'
|
||||
import { EncryptionProvider } from './EncryptionProvider'
|
||||
AnyKeyParamsContent,
|
||||
ApplicationIdentifier,
|
||||
compareVersions,
|
||||
ContentType,
|
||||
isVersionLessThanOrEqualTo,
|
||||
KeyParamsOrigination,
|
||||
ProtocolVersion,
|
||||
ProtocolVersionLastNonrootItemsKey,
|
||||
ProtocolVersionLatest,
|
||||
} from '@standardnotes/common'
|
||||
|
||||
export enum EncryptionServiceEvent {
|
||||
RootKeyStatusChanged = 'RootKeyStatusChanged',
|
||||
}
|
||||
import { AbstractService } from '../Service/AbstractService'
|
||||
import { ItemsEncryptionService } from './ItemsEncryption'
|
||||
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
|
||||
import { PayloadManagerInterface } from '../Payloads/PayloadManagerInterface'
|
||||
import { DeviceInterface } from '../Device/DeviceInterface'
|
||||
import { StorageServiceInterface } from '../Storage/StorageServiceInterface'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { SyncEvent } from '../Event/SyncEvent'
|
||||
import { DiagnosticInfo } from '../Diagnostics/ServiceDiagnostics'
|
||||
import { RootKeyEncryptionService } from './RootKeyEncryption'
|
||||
import { DecryptBackupFile } from './BackupFileDecryptor'
|
||||
import { EncryptionServiceEvent } from './EncryptionServiceEvent'
|
||||
|
||||
/**
|
||||
* The encryption service is responsible for the encryption and decryption of payloads, and
|
||||
@@ -76,20 +100,20 @@ export enum EncryptionServiceEvent {
|
||||
* It also exposes public methods that allows consumers to retrieve an items key
|
||||
* for a particular payload, and also retrieve all available items keys.
|
||||
*/
|
||||
export class EncryptionService extends Services.AbstractService<EncryptionServiceEvent> implements EncryptionProvider {
|
||||
export class EncryptionService extends AbstractService<EncryptionServiceEvent> implements EncryptionProvider {
|
||||
private operatorManager: OperatorManager
|
||||
private readonly itemsEncryption: ItemsEncryptionService
|
||||
private readonly rootKeyEncryption: RootKeyEncryption.RootKeyEncryptionService
|
||||
private readonly rootKeyEncryption: RootKeyEncryptionService
|
||||
private rootKeyObserverDisposer: () => void
|
||||
|
||||
constructor(
|
||||
private itemManager: Services.ItemManagerInterface,
|
||||
private payloadManager: Services.PayloadManagerInterface,
|
||||
public deviceInterface: Services.DeviceInterface,
|
||||
private storageService: Services.StorageServiceInterface,
|
||||
private identifier: Common.ApplicationIdentifier,
|
||||
private itemManager: ItemManagerInterface,
|
||||
private payloadManager: PayloadManagerInterface,
|
||||
public deviceInterface: DeviceInterface,
|
||||
private storageService: StorageServiceInterface,
|
||||
private identifier: ApplicationIdentifier,
|
||||
public crypto: PureCryptoInterface,
|
||||
protected override internalEventBus: Services.InternalEventBusInterface,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
this.crypto = crypto
|
||||
@@ -104,7 +128,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
internalEventBus,
|
||||
)
|
||||
|
||||
this.rootKeyEncryption = new RootKeyEncryption.RootKeyEncryptionService(
|
||||
this.rootKeyEncryption = new RootKeyEncryptionService(
|
||||
this.itemManager,
|
||||
this.operatorManager,
|
||||
this.deviceInterface,
|
||||
@@ -114,12 +138,12 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
)
|
||||
this.rootKeyObserverDisposer = this.rootKeyEncryption.addEventObserver((event) => {
|
||||
this.itemsEncryption.userVersion = this.getUserVersion()
|
||||
if (event === RootKeyEncryption.RootKeyServiceEvent.RootKeyStatusChanged) {
|
||||
if (event === RootKeyServiceEvent.RootKeyStatusChanged) {
|
||||
void this.notifyEvent(EncryptionServiceEvent.RootKeyStatusChanged)
|
||||
}
|
||||
})
|
||||
|
||||
Utils.UuidGenerator.SetGenerator(this.crypto.generateUUID)
|
||||
UuidGenerator.SetGenerator(this.crypto.generateUUID)
|
||||
}
|
||||
|
||||
public override deinit(): void {
|
||||
@@ -160,7 +184,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
}
|
||||
|
||||
public getLatestVersion() {
|
||||
return Common.ProtocolVersionLatest
|
||||
return ProtocolVersionLatest
|
||||
}
|
||||
|
||||
public hasAccount() {
|
||||
@@ -171,7 +195,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
return this.rootKeyEncryption.hasRootKeyEncryptionSource()
|
||||
}
|
||||
|
||||
public getUserVersion(): Common.ProtocolVersion | undefined {
|
||||
public getUserVersion(): ProtocolVersion | undefined {
|
||||
return this.rootKeyEncryption.getUserVersion()
|
||||
}
|
||||
|
||||
@@ -181,8 +205,8 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
return accountUpgradeAvailable || passcodeUpgradeAvailable
|
||||
}
|
||||
|
||||
public getSureDefaultItemsKey(): Models.ItemsKeyInterface {
|
||||
return this.itemsEncryption.getDefaultItemsKey() as Models.ItemsKeyInterface
|
||||
public getSureDefaultItemsKey(): ItemsKeyInterface {
|
||||
return this.itemsEncryption.getDefaultItemsKey() as ItemsKeyInterface
|
||||
}
|
||||
|
||||
async repersistAllItems(): Promise<void> {
|
||||
@@ -201,22 +225,22 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
await this.itemsEncryption.decryptErroredPayloads()
|
||||
}
|
||||
|
||||
public itemsKeyForPayload(payload: Models.EncryptedPayloadInterface): Models.ItemsKeyInterface | undefined {
|
||||
public itemsKeyForPayload(payload: EncryptedPayloadInterface): ItemsKeyInterface | undefined {
|
||||
return this.itemsEncryption.itemsKeyForPayload(payload)
|
||||
}
|
||||
|
||||
public defaultItemsKeyForItemVersion(
|
||||
version: Common.ProtocolVersion,
|
||||
fromKeys?: Models.ItemsKeyInterface[],
|
||||
): Models.ItemsKeyInterface | undefined {
|
||||
version: ProtocolVersion,
|
||||
fromKeys?: ItemsKeyInterface[],
|
||||
): ItemsKeyInterface | undefined {
|
||||
return this.itemsEncryption.defaultItemsKeyForItemVersion(version, fromKeys)
|
||||
}
|
||||
|
||||
public async encryptSplitSingle(split: KeyedEncryptionSplit): Promise<Models.EncryptedPayloadInterface> {
|
||||
public async encryptSplitSingle(split: KeyedEncryptionSplit): Promise<EncryptedPayloadInterface> {
|
||||
return (await this.encryptSplit(split))[0]
|
||||
}
|
||||
|
||||
public async encryptSplit(split: KeyedEncryptionSplit): Promise<Models.EncryptedPayloadInterface[]> {
|
||||
public async encryptSplit(split: KeyedEncryptionSplit): Promise<EncryptedPayloadInterface[]> {
|
||||
const allEncryptedParams: EncryptedParameters[] = []
|
||||
|
||||
if (split.usesRootKey) {
|
||||
@@ -224,7 +248,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
split.usesRootKey.items,
|
||||
split.usesRootKey.key,
|
||||
)
|
||||
Utils.extendArray(allEncryptedParams, rootKeyEncrypted)
|
||||
extendArray(allEncryptedParams, rootKeyEncrypted)
|
||||
}
|
||||
|
||||
if (split.usesItemsKey) {
|
||||
@@ -232,21 +256,21 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
split.usesItemsKey.items,
|
||||
split.usesItemsKey.key,
|
||||
)
|
||||
Utils.extendArray(allEncryptedParams, itemsKeyEncrypted)
|
||||
extendArray(allEncryptedParams, itemsKeyEncrypted)
|
||||
}
|
||||
|
||||
if (split.usesRootKeyWithKeyLookup) {
|
||||
const rootKeyEncrypted = await this.rootKeyEncryption.encryptPayloadsWithKeyLookup(
|
||||
split.usesRootKeyWithKeyLookup.items,
|
||||
)
|
||||
Utils.extendArray(allEncryptedParams, rootKeyEncrypted)
|
||||
extendArray(allEncryptedParams, rootKeyEncrypted)
|
||||
}
|
||||
|
||||
if (split.usesItemsKeyWithKeyLookup) {
|
||||
const itemsKeyEncrypted = await this.itemsEncryption.encryptPayloadsWithKeyLookup(
|
||||
split.usesItemsKeyWithKeyLookup.items,
|
||||
)
|
||||
Utils.extendArray(allEncryptedParams, itemsKeyEncrypted)
|
||||
extendArray(allEncryptedParams, itemsKeyEncrypted)
|
||||
}
|
||||
|
||||
const packagedEncrypted = allEncryptedParams.map((encryptedParams) => {
|
||||
@@ -263,17 +287,17 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
}
|
||||
|
||||
public async decryptSplitSingle<
|
||||
C extends Models.ItemContent = Models.ItemContent,
|
||||
P extends Models.DecryptedPayloadInterface<C> = Models.DecryptedPayloadInterface<C>,
|
||||
>(split: KeyedDecryptionSplit): Promise<P | Models.EncryptedPayloadInterface> {
|
||||
C extends ItemContent = ItemContent,
|
||||
P extends DecryptedPayloadInterface<C> = DecryptedPayloadInterface<C>,
|
||||
>(split: KeyedDecryptionSplit): Promise<P | EncryptedPayloadInterface> {
|
||||
const results = await this.decryptSplit<C, P>(split)
|
||||
return results[0]
|
||||
}
|
||||
|
||||
public async decryptSplit<
|
||||
C extends Models.ItemContent = Models.ItemContent,
|
||||
P extends Models.DecryptedPayloadInterface<C> = Models.DecryptedPayloadInterface<C>,
|
||||
>(split: KeyedDecryptionSplit): Promise<(P | Models.EncryptedPayloadInterface)[]> {
|
||||
C extends ItemContent = ItemContent,
|
||||
P extends DecryptedPayloadInterface<C> = DecryptedPayloadInterface<C>,
|
||||
>(split: KeyedDecryptionSplit): Promise<(P | EncryptedPayloadInterface)[]> {
|
||||
const resultParams: (DecryptedParameters<C> | ErrorDecryptingParameters)[] = []
|
||||
|
||||
if (split.usesRootKey) {
|
||||
@@ -281,14 +305,14 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
split.usesRootKey.items,
|
||||
split.usesRootKey.key,
|
||||
)
|
||||
Utils.extendArray(resultParams, rootKeyDecrypted)
|
||||
extendArray(resultParams, rootKeyDecrypted)
|
||||
}
|
||||
|
||||
if (split.usesRootKeyWithKeyLookup) {
|
||||
const rootKeyDecrypted = await this.rootKeyEncryption.decryptPayloadsWithKeyLookup<C>(
|
||||
split.usesRootKeyWithKeyLookup.items,
|
||||
)
|
||||
Utils.extendArray(resultParams, rootKeyDecrypted)
|
||||
extendArray(resultParams, rootKeyDecrypted)
|
||||
}
|
||||
|
||||
if (split.usesItemsKey) {
|
||||
@@ -296,26 +320,26 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
split.usesItemsKey.items,
|
||||
split.usesItemsKey.key,
|
||||
)
|
||||
Utils.extendArray(resultParams, itemsKeyDecrypted)
|
||||
extendArray(resultParams, itemsKeyDecrypted)
|
||||
}
|
||||
|
||||
if (split.usesItemsKeyWithKeyLookup) {
|
||||
const itemsKeyDecrypted = await this.itemsEncryption.decryptPayloadsWithKeyLookup<C>(
|
||||
split.usesItemsKeyWithKeyLookup.items,
|
||||
)
|
||||
Utils.extendArray(resultParams, itemsKeyDecrypted)
|
||||
extendArray(resultParams, itemsKeyDecrypted)
|
||||
}
|
||||
|
||||
const packagedResults = resultParams.map((params) => {
|
||||
const original = FindPayloadInDecryptionSplit(params.uuid, split)
|
||||
|
||||
if (isErrorDecryptingParameters(params)) {
|
||||
return new Models.EncryptedPayload({
|
||||
return new EncryptedPayload({
|
||||
...original.ejected(),
|
||||
...params,
|
||||
})
|
||||
} else {
|
||||
return new Models.DecryptedPayload<C>({
|
||||
return new DecryptedPayload<C>({
|
||||
...original.ejected(),
|
||||
...params,
|
||||
}) as P
|
||||
@@ -333,7 +357,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
if (!userVersion) {
|
||||
return false
|
||||
}
|
||||
return userVersion !== Common.ProtocolVersionLatest
|
||||
return userVersion !== ProtocolVersionLatest
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,29 +378,24 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
*
|
||||
* Versions 004 and above are always supported.
|
||||
*/
|
||||
if (Common.compareVersions(keyParams.version, Common.ProtocolVersion.V004) >= 0) {
|
||||
if (compareVersions(keyParams.version, ProtocolVersion.V004) >= 0) {
|
||||
/* keyParams.version >= 004 */
|
||||
return true
|
||||
} else {
|
||||
return !!Utils.isWebCryptoAvailable() || Utils.isReactNativeEnvironment()
|
||||
return !!isWebCryptoAvailable() || isReactNativeEnvironment()
|
||||
}
|
||||
}
|
||||
|
||||
public supportedVersions(): Common.ProtocolVersion[] {
|
||||
return [
|
||||
Common.ProtocolVersion.V001,
|
||||
Common.ProtocolVersion.V002,
|
||||
Common.ProtocolVersion.V003,
|
||||
Common.ProtocolVersion.V004,
|
||||
]
|
||||
public supportedVersions(): ProtocolVersion[] {
|
||||
return [ProtocolVersion.V001, ProtocolVersion.V002, ProtocolVersion.V003, ProtocolVersion.V004]
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the input version is greater than the latest supported library version.
|
||||
*/
|
||||
public isVersionNewerThanLibraryVersion(version: Common.ProtocolVersion) {
|
||||
const libraryVersion = Common.ProtocolVersionLatest
|
||||
return Common.compareVersions(version, libraryVersion) === 1
|
||||
public isVersionNewerThanLibraryVersion(version: ProtocolVersion) {
|
||||
const libraryVersion = ProtocolVersionLatest
|
||||
return compareVersions(version, libraryVersion) === 1
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,13 +403,13 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
* This function returns the client-enforced minimum cost, to prevent the server from
|
||||
* overwhelmingly under-reporting the cost.
|
||||
*/
|
||||
public costMinimumForVersion(version: Common.ProtocolVersion) {
|
||||
if (Common.compareVersions(version, Common.ProtocolVersion.V003) >= 0) {
|
||||
public costMinimumForVersion(version: ProtocolVersion) {
|
||||
if (compareVersions(version, ProtocolVersion.V003) >= 0) {
|
||||
throw 'Cost minimums only apply to versions <= 002'
|
||||
}
|
||||
if (version === Common.ProtocolVersion.V001) {
|
||||
if (version === ProtocolVersion.V001) {
|
||||
return V001Algorithm.PbkdfMinCost
|
||||
} else if (version === Common.ProtocolVersion.V002) {
|
||||
} else if (version === ProtocolVersion.V002) {
|
||||
return V002Algorithm.PbkdfMinCost
|
||||
} else {
|
||||
throw `Invalid version for cost minimum: ${version}`
|
||||
@@ -411,8 +430,8 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
public async createRootKey(
|
||||
identifier: string,
|
||||
password: string,
|
||||
origination: Common.KeyParamsOrigination,
|
||||
version?: Common.ProtocolVersion,
|
||||
origination: KeyParamsOrigination,
|
||||
version?: ProtocolVersion,
|
||||
) {
|
||||
return this.rootKeyEncryption.createRootKey(identifier, password, origination, version)
|
||||
}
|
||||
@@ -420,9 +439,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
public async decryptBackupFile(
|
||||
file: BackupFile,
|
||||
password?: string,
|
||||
): Promise<
|
||||
ClientDisplayableError | (Models.EncryptedPayloadInterface | Models.DecryptedPayloadInterface<Models.ItemContent>)[]
|
||||
> {
|
||||
): Promise<ClientDisplayableError | (EncryptedPayloadInterface | DecryptedPayloadInterface<ItemContent>)[]> {
|
||||
const result = await DecryptBackupFile(file, this, password)
|
||||
return result
|
||||
}
|
||||
@@ -431,7 +448,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
* Creates a key params object from a raw object
|
||||
* @param keyParams - The raw key params object to create a KeyParams object from
|
||||
*/
|
||||
public createKeyParams(keyParams: Common.AnyKeyParamsContent) {
|
||||
public createKeyParams(keyParams: AnyKeyParamsContent) {
|
||||
return CreateAnyKeyParams(keyParams)
|
||||
}
|
||||
|
||||
@@ -447,7 +464,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
const ejected = result.map((payload) => CreateEncryptedBackupFileContextPayload(payload))
|
||||
|
||||
const data: BackupFile = {
|
||||
version: Common.ProtocolVersionLatest,
|
||||
version: ProtocolVersionLatest,
|
||||
items: ejected,
|
||||
}
|
||||
|
||||
@@ -457,12 +474,10 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
}
|
||||
|
||||
public createDecryptedBackupFile(): BackupFile {
|
||||
const payloads = this.payloadManager.nonDeletedItems.filter(
|
||||
(item) => item.content_type !== Common.ContentType.ItemsKey,
|
||||
)
|
||||
const payloads = this.payloadManager.nonDeletedItems.filter((item) => item.content_type !== ContentType.ItemsKey)
|
||||
|
||||
const data: BackupFile = {
|
||||
version: Common.ProtocolVersionLatest,
|
||||
version: ProtocolVersionLatest,
|
||||
items: payloads
|
||||
.map((payload) => {
|
||||
if (isDecryptedPayload(payload)) {
|
||||
@@ -557,7 +572,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
}
|
||||
|
||||
public getEmbeddedPayloadAuthenticatedData(
|
||||
payload: Models.EncryptedPayloadInterface,
|
||||
payload: EncryptedPayloadInterface,
|
||||
): RootKeyEncryptedAuthenticatedData | ItemAuthenticatedData | LegacyAttachedData | undefined {
|
||||
const version = payload.version
|
||||
if (!version) {
|
||||
@@ -569,12 +584,12 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
}
|
||||
|
||||
/** Returns the key params attached to this key's encrypted payload */
|
||||
public getKeyEmbeddedKeyParams(key: Models.EncryptedPayloadInterface): SNRootKeyParams | undefined {
|
||||
public getKeyEmbeddedKeyParams(key: EncryptedPayloadInterface): SNRootKeyParams | undefined {
|
||||
const authenticatedData = this.getEmbeddedPayloadAuthenticatedData(key)
|
||||
if (!authenticatedData) {
|
||||
return undefined
|
||||
}
|
||||
if (Common.isVersionLessThanOrEqualTo(key.version, Common.ProtocolVersion.V003)) {
|
||||
if (isVersionLessThanOrEqualTo(key.version, ProtocolVersion.V003)) {
|
||||
const rawKeyParams = authenticatedData as LegacyAttachedData
|
||||
return this.createKeyParams(rawKeyParams)
|
||||
} else {
|
||||
@@ -597,7 +612,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
return false
|
||||
}
|
||||
|
||||
if (Common.compareVersions(rootKey.keyVersion, Common.ProtocolVersionLastNonrootItemsKey) > 0) {
|
||||
if (compareVersions(rootKey.keyVersion, ProtocolVersionLastNonrootItemsKey) > 0) {
|
||||
/** Is >= 004, not needed */
|
||||
return false
|
||||
}
|
||||
@@ -616,7 +631,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
return defaultItemsKey.itemsKey !== rootKey.itemsKey
|
||||
}
|
||||
|
||||
public async createNewDefaultItemsKey(): Promise<Models.ItemsKeyInterface> {
|
||||
public async createNewDefaultItemsKey(): Promise<ItemsKeyInterface> {
|
||||
return this.rootKeyEncryption.createNewDefaultItemsKey()
|
||||
}
|
||||
|
||||
@@ -625,11 +640,11 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
return rootKey ? rootKey.keyParams.createdDate : undefined
|
||||
}
|
||||
|
||||
public async onSyncEvent(eventName: Services.SyncEvent) {
|
||||
if (eventName === Services.SyncEvent.SyncCompletedWithAllItemsUploaded) {
|
||||
public async onSyncEvent(eventName: SyncEvent) {
|
||||
if (eventName === SyncEvent.SyncCompletedWithAllItemsUploaded) {
|
||||
await this.handleFullSyncCompletion()
|
||||
}
|
||||
if (eventName === Services.SyncEvent.DownloadFirstSyncCompleted) {
|
||||
if (eventName === SyncEvent.DownloadFirstSyncCompleted) {
|
||||
await this.handleDownloadFirstSyncCompletion()
|
||||
}
|
||||
}
|
||||
@@ -665,7 +680,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
return key.isDefault
|
||||
})
|
||||
|
||||
const hasSyncedItemsKey = !Utils.isNullOrUndefined(defaultSyncedKey)
|
||||
const hasSyncedItemsKey = !isNullOrUndefined(defaultSyncedKey)
|
||||
if (hasSyncedItemsKey) {
|
||||
/** Delete all never synced keys */
|
||||
await this.itemManager.setItemsToBeDeleted(neverSyncedKeys)
|
||||
@@ -695,7 +710,7 @@ export class EncryptionService extends Services.AbstractService<EncryptionServic
|
||||
/** If we do not have an items key for our current account version, create one */
|
||||
const userVersion = this.getUserVersion()
|
||||
const accountVersionedKey = this.itemsEncryption.getItemsKeys().find((key) => key.keyVersion === userVersion)
|
||||
if (Utils.isNullOrUndefined(accountVersionedKey)) {
|
||||
if (isNullOrUndefined(accountVersionedKey)) {
|
||||
await this.rootKeyEncryption.createNewDefaultItemsKey()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export enum EncryptionServiceEvent {
|
||||
RootKeyStatusChanged = 'RootKeyStatusChanged',
|
||||
}
|
||||
@@ -5,15 +5,11 @@ import {
|
||||
ItemsKeyContent,
|
||||
RootKeyInterface,
|
||||
} from '@standardnotes/models'
|
||||
import {
|
||||
ChallengePrompt,
|
||||
ChallengeReason,
|
||||
ChallengeServiceInterface,
|
||||
ChallengeValidation,
|
||||
} from '@standardnotes/services'
|
||||
import { EncryptionProvider } from '../../Service/Encryption/EncryptionProvider'
|
||||
import { SNRootKeyParams } from '../RootKey/RootKeyParams'
|
||||
import { KeyRecoveryStrings } from './KeyRecoveryStrings'
|
||||
import { EncryptionProvider, KeyRecoveryStrings, SNRootKeyParams } from '@standardnotes/encryption'
|
||||
import { ChallengeServiceInterface } from '../Challenge/ChallengeServiceInterface'
|
||||
import { ChallengePrompt } from '../Challenge/Prompt/ChallengePrompt'
|
||||
import { ChallengeReason } from '../Challenge/Types/ChallengeReason'
|
||||
import { ChallengeValidation } from '../Challenge/Types/ChallengeValidation'
|
||||
|
||||
export async function DecryptItemsKeyWithUserFallback(
|
||||
itemsKey: EncryptedPayloadInterface,
|
||||
@@ -1,30 +1,45 @@
|
||||
import { ContentType, ProtocolVersion } from '@standardnotes/common'
|
||||
import * as Models from '@standardnotes/models'
|
||||
import { isEncryptedPayload } from '@standardnotes/models'
|
||||
import * as Services from '@standardnotes/services'
|
||||
import { DiagnosticInfo } from '@standardnotes/services'
|
||||
import { Uuids } from '@standardnotes/utils'
|
||||
import { OperatorManager } from '../../Operator/OperatorManager'
|
||||
import * as OperatorWrapper from '../../Operator/OperatorWrapper'
|
||||
import { StandardException } from '../../StandardException'
|
||||
import {
|
||||
DecryptedParameters,
|
||||
EncryptedParameters,
|
||||
ErrorDecryptingParameters,
|
||||
findDefaultItemsKey,
|
||||
isErrorDecryptingParameters,
|
||||
} from '../../Types/EncryptedParameters'
|
||||
import { findDefaultItemsKey } from '../Functions'
|
||||
OperatorManager,
|
||||
StandardException,
|
||||
encryptPayload,
|
||||
decryptPayload,
|
||||
} from '@standardnotes/encryption'
|
||||
import {
|
||||
DecryptedPayload,
|
||||
DecryptedPayloadInterface,
|
||||
EncryptedPayload,
|
||||
EncryptedPayloadInterface,
|
||||
isEncryptedPayload,
|
||||
ItemContent,
|
||||
ItemsKeyInterface,
|
||||
PayloadEmitSource,
|
||||
SureFindPayload,
|
||||
} from '@standardnotes/models'
|
||||
import { Uuids } from '@standardnotes/utils'
|
||||
|
||||
export class ItemsEncryptionService extends Services.AbstractService {
|
||||
import { DiagnosticInfo } from '../Diagnostics/ServiceDiagnostics'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
|
||||
import { PayloadManagerInterface } from '../Payloads/PayloadManagerInterface'
|
||||
import { AbstractService } from '../Service/AbstractService'
|
||||
import { StorageServiceInterface } from '../Storage/StorageServiceInterface'
|
||||
|
||||
export class ItemsEncryptionService extends AbstractService {
|
||||
private removeItemsObserver!: () => void
|
||||
public userVersion?: ProtocolVersion
|
||||
|
||||
constructor(
|
||||
private itemManager: Services.ItemManagerInterface,
|
||||
private payloadManager: Services.PayloadManagerInterface,
|
||||
private storageService: Services.StorageServiceInterface,
|
||||
private itemManager: ItemManagerInterface,
|
||||
private payloadManager: PayloadManagerInterface,
|
||||
private storageService: StorageServiceInterface,
|
||||
private operatorManager: OperatorManager,
|
||||
protected override internalEventBus: Services.InternalEventBusInterface,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
|
||||
@@ -59,19 +74,19 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
return this.itemManager.getDisplayableItemsKeys()
|
||||
}
|
||||
|
||||
public itemsKeyForPayload(payload: Models.EncryptedPayloadInterface): Models.ItemsKeyInterface | undefined {
|
||||
public itemsKeyForPayload(payload: EncryptedPayloadInterface): ItemsKeyInterface | undefined {
|
||||
return this.getItemsKeys().find(
|
||||
(key) => key.uuid === payload.items_key_id || key.duplicateOf === payload.items_key_id,
|
||||
)
|
||||
}
|
||||
|
||||
public getDefaultItemsKey(): Models.ItemsKeyInterface | undefined {
|
||||
public getDefaultItemsKey(): ItemsKeyInterface | undefined {
|
||||
return findDefaultItemsKey(this.getItemsKeys())
|
||||
}
|
||||
|
||||
private keyToUseForItemEncryption(): Models.ItemsKeyInterface | StandardException {
|
||||
private keyToUseForItemEncryption(): ItemsKeyInterface | StandardException {
|
||||
const defaultKey = this.getDefaultItemsKey()
|
||||
let result: Models.ItemsKeyInterface | undefined = undefined
|
||||
let result: ItemsKeyInterface | undefined = undefined
|
||||
|
||||
if (this.userVersion && this.userVersion !== defaultKey?.keyVersion) {
|
||||
/**
|
||||
@@ -92,9 +107,7 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
return result
|
||||
}
|
||||
|
||||
private keyToUseForDecryptionOfPayload(
|
||||
payload: Models.EncryptedPayloadInterface,
|
||||
): Models.ItemsKeyInterface | undefined {
|
||||
private keyToUseForDecryptionOfPayload(payload: EncryptedPayloadInterface): ItemsKeyInterface | undefined {
|
||||
if (payload.items_key_id) {
|
||||
const itemsKey = this.itemsKeyForPayload(payload)
|
||||
return itemsKey
|
||||
@@ -104,7 +117,7 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
return defaultKey
|
||||
}
|
||||
|
||||
public async encryptPayloadWithKeyLookup(payload: Models.DecryptedPayloadInterface): Promise<EncryptedParameters> {
|
||||
public async encryptPayloadWithKeyLookup(payload: DecryptedPayloadInterface): Promise<EncryptedParameters> {
|
||||
const key = this.keyToUseForItemEncryption()
|
||||
|
||||
if (key instanceof StandardException) {
|
||||
@@ -115,8 +128,8 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
}
|
||||
|
||||
public async encryptPayload(
|
||||
payload: Models.DecryptedPayloadInterface,
|
||||
key: Models.ItemsKeyInterface,
|
||||
payload: DecryptedPayloadInterface,
|
||||
key: ItemsKeyInterface,
|
||||
): Promise<EncryptedParameters> {
|
||||
if (isEncryptedPayload(payload)) {
|
||||
throw Error('Attempting to encrypt already encrypted payload.')
|
||||
@@ -128,24 +141,22 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
throw Error('Attempting to encrypt payload with no UuidGenerator.')
|
||||
}
|
||||
|
||||
return OperatorWrapper.encryptPayload(payload, key, this.operatorManager)
|
||||
return encryptPayload(payload, key, this.operatorManager)
|
||||
}
|
||||
|
||||
public async encryptPayloads(
|
||||
payloads: Models.DecryptedPayloadInterface[],
|
||||
key: Models.ItemsKeyInterface,
|
||||
payloads: DecryptedPayloadInterface[],
|
||||
key: ItemsKeyInterface,
|
||||
): Promise<EncryptedParameters[]> {
|
||||
return Promise.all(payloads.map((payload) => this.encryptPayload(payload, key)))
|
||||
}
|
||||
|
||||
public async encryptPayloadsWithKeyLookup(
|
||||
payloads: Models.DecryptedPayloadInterface[],
|
||||
): Promise<EncryptedParameters[]> {
|
||||
public async encryptPayloadsWithKeyLookup(payloads: DecryptedPayloadInterface[]): Promise<EncryptedParameters[]> {
|
||||
return Promise.all(payloads.map((payload) => this.encryptPayloadWithKeyLookup(payload)))
|
||||
}
|
||||
|
||||
public async decryptPayloadWithKeyLookup<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payload: Models.EncryptedPayloadInterface,
|
||||
public async decryptPayloadWithKeyLookup<C extends ItemContent = ItemContent>(
|
||||
payload: EncryptedPayloadInterface,
|
||||
): Promise<DecryptedParameters<C> | ErrorDecryptingParameters> {
|
||||
const key = this.keyToUseForDecryptionOfPayload(payload)
|
||||
|
||||
@@ -160,9 +171,9 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
return this.decryptPayload(payload, key)
|
||||
}
|
||||
|
||||
public async decryptPayload<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payload: Models.EncryptedPayloadInterface,
|
||||
key: Models.ItemsKeyInterface,
|
||||
public async decryptPayload<C extends ItemContent = ItemContent>(
|
||||
payload: EncryptedPayloadInterface,
|
||||
key: ItemsKeyInterface,
|
||||
): Promise<DecryptedParameters<C> | ErrorDecryptingParameters> {
|
||||
if (!payload.content) {
|
||||
return {
|
||||
@@ -171,18 +182,18 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
}
|
||||
}
|
||||
|
||||
return OperatorWrapper.decryptPayload(payload, key, this.operatorManager)
|
||||
return decryptPayload(payload, key, this.operatorManager)
|
||||
}
|
||||
|
||||
public async decryptPayloadsWithKeyLookup<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payloads: Models.EncryptedPayloadInterface[],
|
||||
public async decryptPayloadsWithKeyLookup<C extends ItemContent = ItemContent>(
|
||||
payloads: EncryptedPayloadInterface[],
|
||||
): Promise<(DecryptedParameters<C> | ErrorDecryptingParameters)[]> {
|
||||
return Promise.all(payloads.map((payload) => this.decryptPayloadWithKeyLookup<C>(payload)))
|
||||
}
|
||||
|
||||
public async decryptPayloads<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payloads: Models.EncryptedPayloadInterface[],
|
||||
key: Models.ItemsKeyInterface,
|
||||
public async decryptPayloads<C extends ItemContent = ItemContent>(
|
||||
payloads: EncryptedPayloadInterface[],
|
||||
key: ItemsKeyInterface,
|
||||
): Promise<(DecryptedParameters<C> | ErrorDecryptingParameters)[]> {
|
||||
return Promise.all(payloads.map((payload) => this.decryptPayload<C>(payload, key)))
|
||||
}
|
||||
@@ -196,21 +207,21 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
const resultParams = await this.decryptPayloadsWithKeyLookup(payloads)
|
||||
|
||||
const decryptedPayloads = resultParams.map((params) => {
|
||||
const original = Models.SureFindPayload(payloads, params.uuid)
|
||||
const original = SureFindPayload(payloads, params.uuid)
|
||||
if (isErrorDecryptingParameters(params)) {
|
||||
return new Models.EncryptedPayload({
|
||||
return new EncryptedPayload({
|
||||
...original.ejected(),
|
||||
...params,
|
||||
})
|
||||
} else {
|
||||
return new Models.DecryptedPayload({
|
||||
return new DecryptedPayload({
|
||||
...original.ejected(),
|
||||
...params,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
await this.payloadManager.emitPayloads(decryptedPayloads, Models.PayloadEmitSource.LocalChanged)
|
||||
await this.payloadManager.emitPayloads(decryptedPayloads, PayloadEmitSource.LocalChanged)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,8 +233,8 @@ export class ItemsEncryptionService extends Services.AbstractService {
|
||||
*/
|
||||
public defaultItemsKeyForItemVersion(
|
||||
version: ProtocolVersion,
|
||||
fromKeys?: Models.ItemsKeyInterface[],
|
||||
): Models.ItemsKeyInterface | undefined {
|
||||
fromKeys?: ItemsKeyInterface[],
|
||||
): ItemsKeyInterface | undefined {
|
||||
/** Try to find one marked default first */
|
||||
const searchKeys = fromKeys || this.getItemsKeys()
|
||||
const priorityKey = searchKeys.find((key) => {
|
||||
@@ -1,49 +1,71 @@
|
||||
import * as Common from '@standardnotes/common'
|
||||
import * as Models from '@standardnotes/models'
|
||||
import {
|
||||
ApplicationIdentifier,
|
||||
ProtocolVersionLatest,
|
||||
ProtocolVersion,
|
||||
AnyKeyParamsContent,
|
||||
KeyParamsOrigination,
|
||||
compareVersions,
|
||||
ProtocolVersionLastNonrootItemsKey,
|
||||
ContentType,
|
||||
} from '@standardnotes/common'
|
||||
import {
|
||||
RootKeyServiceEvent,
|
||||
KeyMode,
|
||||
SNRootKeyParams,
|
||||
OperatorManager,
|
||||
CreateNewRootKey,
|
||||
CreateAnyKeyParams,
|
||||
SNRootKey,
|
||||
isErrorDecryptingParameters,
|
||||
EncryptedParameters,
|
||||
DecryptedParameters,
|
||||
ErrorDecryptingParameters,
|
||||
findDefaultItemsKey,
|
||||
ItemsKeyMutator,
|
||||
encryptPayload,
|
||||
decryptPayload,
|
||||
} from '@standardnotes/encryption'
|
||||
import {
|
||||
CreateDecryptedItemFromPayload,
|
||||
DecryptedPayload,
|
||||
DecryptedPayloadInterface,
|
||||
DecryptedTransferPayload,
|
||||
EncryptedPayload,
|
||||
EncryptedPayloadInterface,
|
||||
EncryptedTransferPayload,
|
||||
FillItemContentSpecialized,
|
||||
ItemContent,
|
||||
ItemsKeyContent,
|
||||
ItemsKeyContentSpecialized,
|
||||
ItemsKeyInterface,
|
||||
NamespacedRootKeyInKeychain,
|
||||
PayloadTimestampDefaults,
|
||||
RootKeyContent,
|
||||
RootKeyInterface,
|
||||
} from '@standardnotes/models'
|
||||
import * as Services from '@standardnotes/services'
|
||||
import { UuidGenerator } from '@standardnotes/utils'
|
||||
import { ItemsKeyMutator } from '../../Keys/ItemsKey/ItemsKeyMutator'
|
||||
import { CreateNewRootKey } from '../../Keys/RootKey/Functions'
|
||||
import { CreateAnyKeyParams } from '../../Keys/RootKey/KeyParamsFunctions'
|
||||
import { SNRootKey } from '../../Keys/RootKey/RootKey'
|
||||
import { SNRootKeyParams } from '../../Keys/RootKey/RootKeyParams'
|
||||
import { OperatorManager } from '../../Operator/OperatorManager'
|
||||
import * as OperatorWrapper from '../../Operator/OperatorWrapper'
|
||||
import {
|
||||
DecryptedParameters,
|
||||
EncryptedParameters,
|
||||
ErrorDecryptingParameters,
|
||||
isErrorDecryptingParameters,
|
||||
} from '../../Types/EncryptedParameters'
|
||||
import { findDefaultItemsKey } from '../Functions'
|
||||
import { KeyMode } from './KeyMode'
|
||||
|
||||
export enum RootKeyServiceEvent {
|
||||
RootKeyStatusChanged = 'RootKeyStatusChanged',
|
||||
}
|
||||
import { DeviceInterface } from '../Device/DeviceInterface'
|
||||
import { DiagnosticInfo } from '../Diagnostics/ServiceDiagnostics'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
|
||||
import { AbstractService } from '../Service/AbstractService'
|
||||
import { StorageKey } from '../Storage/StorageKeys'
|
||||
import { StorageServiceInterface } from '../Storage/StorageServiceInterface'
|
||||
import { StorageValueModes } from '../Storage/StorageTypes'
|
||||
|
||||
export class RootKeyEncryptionService extends Services.AbstractService<RootKeyServiceEvent> {
|
||||
export class RootKeyEncryptionService extends AbstractService<RootKeyServiceEvent> {
|
||||
private rootKey?: RootKeyInterface
|
||||
public keyMode = KeyMode.RootKeyNone
|
||||
public memoizedRootKeyParams?: SNRootKeyParams
|
||||
|
||||
constructor(
|
||||
private itemManager: Services.ItemManagerInterface,
|
||||
private itemManager: ItemManagerInterface,
|
||||
private operatorManager: OperatorManager,
|
||||
public deviceInterface: Services.DeviceInterface,
|
||||
private storageService: Services.StorageServiceInterface,
|
||||
private identifier: Common.ApplicationIdentifier,
|
||||
protected override internalEventBus: Services.InternalEventBusInterface,
|
||||
public deviceInterface: DeviceInterface,
|
||||
private storageService: StorageServiceInterface,
|
||||
private identifier: ApplicationIdentifier,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
}
|
||||
@@ -89,7 +111,7 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
if (!passcodeParams) {
|
||||
return false
|
||||
}
|
||||
return passcodeParams.version !== Common.ProtocolVersionLatest
|
||||
return passcodeParams.version !== ProtocolVersionLatest
|
||||
}
|
||||
|
||||
public async hasRootKeyWrapper() {
|
||||
@@ -118,7 +140,7 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
return this.keyMode === KeyMode.WrapperOnly || this.keyMode === KeyMode.RootKeyPlusWrapper
|
||||
}
|
||||
|
||||
public async getEncryptionSourceVersion(): Promise<Common.ProtocolVersion> {
|
||||
public async getEncryptionSourceVersion(): Promise<ProtocolVersion> {
|
||||
if (this.hasAccount()) {
|
||||
return this.getSureUserVersion()
|
||||
} else if (this.hasPasscode()) {
|
||||
@@ -129,12 +151,12 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
throw Error('Attempting to access encryption source version without source')
|
||||
}
|
||||
|
||||
public getUserVersion(): Common.ProtocolVersion | undefined {
|
||||
public getUserVersion(): ProtocolVersion | undefined {
|
||||
const keyParams = this.memoizedRootKeyParams
|
||||
return keyParams?.version
|
||||
}
|
||||
|
||||
private getSureUserVersion(): Common.ProtocolVersion {
|
||||
private getSureUserVersion(): ProtocolVersion {
|
||||
const keyParams = this.memoizedRootKeyParams as SNRootKeyParams
|
||||
return keyParams.version
|
||||
}
|
||||
@@ -173,15 +195,15 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
|
||||
public async getRootKeyWrapperKeyParams(): Promise<SNRootKeyParams | undefined> {
|
||||
const rawKeyParams = await this.storageService.getValue(
|
||||
Services.StorageKey.RootKeyWrapperKeyParams,
|
||||
Services.StorageValueModes.Nonwrapped,
|
||||
StorageKey.RootKeyWrapperKeyParams,
|
||||
StorageValueModes.Nonwrapped,
|
||||
)
|
||||
|
||||
if (!rawKeyParams) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return CreateAnyKeyParams(rawKeyParams as Common.AnyKeyParamsContent)
|
||||
return CreateAnyKeyParams(rawKeyParams as AnyKeyParamsContent)
|
||||
}
|
||||
|
||||
public async getSureRootKeyWrapperKeyParams() {
|
||||
@@ -213,8 +235,8 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
public async createRootKey(
|
||||
identifier: string,
|
||||
password: string,
|
||||
origination: Common.KeyParamsOrigination,
|
||||
version?: Common.ProtocolVersion,
|
||||
origination: KeyParamsOrigination,
|
||||
version?: ProtocolVersion,
|
||||
) {
|
||||
const operator = version ? this.operatorManager.operatorForVersion(version) : this.operatorManager.defaultOperator()
|
||||
return operator.createRootKey(identifier, password, origination)
|
||||
@@ -261,7 +283,7 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
* account keys are encrypted with wrappingKey. Here we validate
|
||||
* by attempting to decrypt account keys.
|
||||
*/
|
||||
const wrappedKeyPayload = new Models.EncryptedPayload(wrappedRootKey)
|
||||
const wrappedKeyPayload = new EncryptedPayload(wrappedRootKey)
|
||||
const decrypted = await this.decryptPayload(wrappedKeyPayload, wrappingKey)
|
||||
return !isErrorDecryptingParameters(decrypted)
|
||||
} else {
|
||||
@@ -270,16 +292,13 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
}
|
||||
|
||||
private async recomputeAccountKeyParams(): Promise<SNRootKeyParams | undefined> {
|
||||
const rawKeyParams = await this.storageService.getValue(
|
||||
Services.StorageKey.RootKeyParams,
|
||||
Services.StorageValueModes.Nonwrapped,
|
||||
)
|
||||
const rawKeyParams = await this.storageService.getValue(StorageKey.RootKeyParams, StorageValueModes.Nonwrapped)
|
||||
|
||||
if (!rawKeyParams) {
|
||||
return
|
||||
}
|
||||
|
||||
this.memoizedRootKeyParams = CreateAnyKeyParams(rawKeyParams as Common.AnyKeyParamsContent)
|
||||
this.memoizedRootKeyParams = CreateAnyKeyParams(rawKeyParams as AnyKeyParamsContent)
|
||||
return this.memoizedRootKeyParams
|
||||
}
|
||||
|
||||
@@ -289,25 +308,21 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
*/
|
||||
private async wrapAndPersistRootKey(wrappingKey: SNRootKey) {
|
||||
const rootKey = this.getSureRootKey()
|
||||
const value: Models.DecryptedTransferPayload = {
|
||||
const value: DecryptedTransferPayload = {
|
||||
...rootKey.payload.ejected(),
|
||||
content: FillItemContentSpecialized(rootKey.persistableValueWhenWrapping()),
|
||||
}
|
||||
const payload = new Models.DecryptedPayload(value)
|
||||
const payload = new DecryptedPayload(value)
|
||||
|
||||
const wrappedKey = await this.encryptPayload(payload, wrappingKey)
|
||||
const wrappedKeyPayload = new Models.EncryptedPayload({
|
||||
const wrappedKeyPayload = new EncryptedPayload({
|
||||
...payload.ejected(),
|
||||
...wrappedKey,
|
||||
errorDecrypting: false,
|
||||
waitingForKey: false,
|
||||
})
|
||||
|
||||
this.storageService.setValue(
|
||||
Services.StorageKey.WrappedRootKey,
|
||||
wrappedKeyPayload.ejected(),
|
||||
Services.StorageValueModes.Nonwrapped,
|
||||
)
|
||||
this.storageService.setValue(StorageKey.WrappedRootKey, wrappedKeyPayload.ejected(), StorageValueModes.Nonwrapped)
|
||||
}
|
||||
|
||||
public async unwrapRootKey(wrappingKey: RootKeyInterface) {
|
||||
@@ -321,8 +336,8 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
}
|
||||
|
||||
const wrappedKey = this.getWrappedRootKey()
|
||||
const payload = new Models.EncryptedPayload(wrappedKey)
|
||||
const decrypted = await this.decryptPayload<Models.RootKeyContent>(payload, wrappingKey)
|
||||
const payload = new EncryptedPayload(wrappedKey)
|
||||
const decrypted = await this.decryptPayload<RootKeyContent>(payload, wrappingKey)
|
||||
|
||||
if (isErrorDecryptingParameters(decrypted)) {
|
||||
throw Error('Unable to decrypt root key with provided wrapping key.')
|
||||
@@ -362,9 +377,9 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
}
|
||||
|
||||
this.storageService.setValue(
|
||||
Services.StorageKey.RootKeyWrapperKeyParams,
|
||||
StorageKey.RootKeyWrapperKeyParams,
|
||||
wrappingKey.keyParams.getPortableValue(),
|
||||
Services.StorageValueModes.Nonwrapped,
|
||||
StorageValueModes.Nonwrapped,
|
||||
)
|
||||
|
||||
await this.handleKeyStatusChange()
|
||||
@@ -388,11 +403,8 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
this.keyMode = KeyMode.RootKeyOnly
|
||||
}
|
||||
|
||||
await this.storageService.removeValue(Services.StorageKey.WrappedRootKey, Services.StorageValueModes.Nonwrapped)
|
||||
await this.storageService.removeValue(
|
||||
Services.StorageKey.RootKeyWrapperKeyParams,
|
||||
Services.StorageValueModes.Nonwrapped,
|
||||
)
|
||||
await this.storageService.removeValue(StorageKey.WrappedRootKey, StorageValueModes.Nonwrapped)
|
||||
await this.storageService.removeValue(StorageKey.RootKeyWrapperKeyParams, StorageValueModes.Nonwrapped)
|
||||
|
||||
if (this.keyMode === KeyMode.RootKeyOnly) {
|
||||
await this.saveRootKeyToKeychain()
|
||||
@@ -424,9 +436,9 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
this.setRootKeyInstance(key)
|
||||
|
||||
this.storageService.setValue(
|
||||
Services.StorageKey.RootKeyParams,
|
||||
StorageKey.RootKeyParams,
|
||||
key.keyParams.getPortableValue(),
|
||||
Services.StorageValueModes.Nonwrapped,
|
||||
StorageValueModes.Nonwrapped,
|
||||
)
|
||||
|
||||
if (this.keyMode === KeyMode.RootKeyOnly) {
|
||||
@@ -446,12 +458,9 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
*/
|
||||
public async deleteWorkspaceSpecificKeyStateFromDevice() {
|
||||
await this.deviceInterface.clearNamespacedKeychainValue(this.identifier)
|
||||
await this.storageService.removeValue(Services.StorageKey.WrappedRootKey, Services.StorageValueModes.Nonwrapped)
|
||||
await this.storageService.removeValue(
|
||||
Services.StorageKey.RootKeyWrapperKeyParams,
|
||||
Services.StorageValueModes.Nonwrapped,
|
||||
)
|
||||
await this.storageService.removeValue(Services.StorageKey.RootKeyParams, Services.StorageValueModes.Nonwrapped)
|
||||
await this.storageService.removeValue(StorageKey.WrappedRootKey, StorageValueModes.Nonwrapped)
|
||||
await this.storageService.removeValue(StorageKey.RootKeyWrapperKeyParams, StorageValueModes.Nonwrapped)
|
||||
await this.storageService.removeValue(StorageKey.RootKeyParams, StorageValueModes.Nonwrapped)
|
||||
this.keyMode = KeyMode.RootKeyNone
|
||||
this.setRootKeyInstance(undefined)
|
||||
|
||||
@@ -459,9 +468,9 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
}
|
||||
|
||||
private getWrappedRootKey() {
|
||||
return this.storageService.getValue<Models.EncryptedTransferPayload>(
|
||||
Services.StorageKey.WrappedRootKey,
|
||||
Services.StorageValueModes.Nonwrapped,
|
||||
return this.storageService.getValue<EncryptedTransferPayload>(
|
||||
StorageKey.WrappedRootKey,
|
||||
StorageValueModes.Nonwrapped,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -481,7 +490,7 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
return this.itemManager.getDisplayableItemsKeys()
|
||||
}
|
||||
|
||||
public async encrypPayloadWithKeyLookup(payload: Models.DecryptedPayloadInterface): Promise<EncryptedParameters> {
|
||||
public async encrypPayloadWithKeyLookup(payload: DecryptedPayloadInterface): Promise<EncryptedParameters> {
|
||||
const key = this.getRootKey()
|
||||
|
||||
if (key == undefined) {
|
||||
@@ -491,25 +500,20 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
return this.encryptPayload(payload, key)
|
||||
}
|
||||
|
||||
public async encryptPayloadsWithKeyLookup(
|
||||
payloads: Models.DecryptedPayloadInterface[],
|
||||
): Promise<EncryptedParameters[]> {
|
||||
public async encryptPayloadsWithKeyLookup(payloads: DecryptedPayloadInterface[]): Promise<EncryptedParameters[]> {
|
||||
return Promise.all(payloads.map((payload) => this.encrypPayloadWithKeyLookup(payload)))
|
||||
}
|
||||
|
||||
public async encryptPayload(
|
||||
payload: Models.DecryptedPayloadInterface,
|
||||
key: RootKeyInterface,
|
||||
): Promise<EncryptedParameters> {
|
||||
return OperatorWrapper.encryptPayload(payload, key, this.operatorManager)
|
||||
public async encryptPayload(payload: DecryptedPayloadInterface, key: RootKeyInterface): Promise<EncryptedParameters> {
|
||||
return encryptPayload(payload, key, this.operatorManager)
|
||||
}
|
||||
|
||||
public async encryptPayloads(payloads: Models.DecryptedPayloadInterface[], key: RootKeyInterface) {
|
||||
public async encryptPayloads(payloads: DecryptedPayloadInterface[], key: RootKeyInterface) {
|
||||
return Promise.all(payloads.map((payload) => this.encryptPayload(payload, key)))
|
||||
}
|
||||
|
||||
public async decryptPayloadWithKeyLookup<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payload: Models.EncryptedPayloadInterface,
|
||||
public async decryptPayloadWithKeyLookup<C extends ItemContent = ItemContent>(
|
||||
payload: EncryptedPayloadInterface,
|
||||
): Promise<DecryptedParameters<C> | ErrorDecryptingParameters> {
|
||||
const key = this.getRootKey()
|
||||
|
||||
@@ -524,21 +528,21 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
return this.decryptPayload(payload, key)
|
||||
}
|
||||
|
||||
public async decryptPayload<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payload: Models.EncryptedPayloadInterface,
|
||||
public async decryptPayload<C extends ItemContent = ItemContent>(
|
||||
payload: EncryptedPayloadInterface,
|
||||
key: RootKeyInterface,
|
||||
): Promise<DecryptedParameters<C> | ErrorDecryptingParameters> {
|
||||
return OperatorWrapper.decryptPayload(payload, key, this.operatorManager)
|
||||
return decryptPayload(payload, key, this.operatorManager)
|
||||
}
|
||||
|
||||
public async decryptPayloadsWithKeyLookup<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payloads: Models.EncryptedPayloadInterface[],
|
||||
public async decryptPayloadsWithKeyLookup<C extends ItemContent = ItemContent>(
|
||||
payloads: EncryptedPayloadInterface[],
|
||||
): Promise<(DecryptedParameters<C> | ErrorDecryptingParameters)[]> {
|
||||
return Promise.all(payloads.map((payload) => this.decryptPayloadWithKeyLookup<C>(payload)))
|
||||
}
|
||||
|
||||
public async decryptPayloads<C extends Models.ItemContent = Models.ItemContent>(
|
||||
payloads: Models.EncryptedPayloadInterface[],
|
||||
public async decryptPayloads<C extends ItemContent = ItemContent>(
|
||||
payloads: EncryptedPayloadInterface[],
|
||||
key: RootKeyInterface,
|
||||
): Promise<(DecryptedParameters<C> | ErrorDecryptingParameters)[]> {
|
||||
return Promise.all(payloads.map((payload) => this.decryptPayload<C>(payload, key)))
|
||||
@@ -566,24 +570,24 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
* Consumer must call sync. If the protocol version <= 003, only one items key should be created,
|
||||
* and its .itemsKey value should be equal to the root key masterKey value.
|
||||
*/
|
||||
public async createNewDefaultItemsKey(): Promise<Models.ItemsKeyInterface> {
|
||||
public async createNewDefaultItemsKey(): Promise<ItemsKeyInterface> {
|
||||
const rootKey = this.getSureRootKey()
|
||||
const operatorVersion = rootKey ? rootKey.keyVersion : Common.ProtocolVersionLatest
|
||||
let itemTemplate: Models.ItemsKeyInterface
|
||||
const operatorVersion = rootKey ? rootKey.keyVersion : ProtocolVersionLatest
|
||||
let itemTemplate: ItemsKeyInterface
|
||||
|
||||
if (Common.compareVersions(operatorVersion, Common.ProtocolVersionLastNonrootItemsKey) <= 0) {
|
||||
if (compareVersions(operatorVersion, ProtocolVersionLastNonrootItemsKey) <= 0) {
|
||||
/** Create root key based items key */
|
||||
const payload = new DecryptedPayload<ItemsKeyContent>({
|
||||
uuid: UuidGenerator.GenerateUuid(),
|
||||
content_type: Common.ContentType.ItemsKey,
|
||||
content: Models.FillItemContentSpecialized<ItemsKeyContentSpecialized, ItemsKeyContent>({
|
||||
content_type: ContentType.ItemsKey,
|
||||
content: FillItemContentSpecialized<ItemsKeyContentSpecialized, ItemsKeyContent>({
|
||||
itemsKey: rootKey.masterKey,
|
||||
dataAuthenticationKey: rootKey.dataAuthenticationKey,
|
||||
version: operatorVersion,
|
||||
}),
|
||||
...PayloadTimestampDefaults(),
|
||||
})
|
||||
itemTemplate = Models.CreateDecryptedItemFromPayload(payload)
|
||||
itemTemplate = CreateDecryptedItemFromPayload(payload)
|
||||
} else {
|
||||
/** Create independent items key */
|
||||
itemTemplate = this.operatorManager.operatorForVersion(operatorVersion).createItemsKey()
|
||||
@@ -600,7 +604,7 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
})
|
||||
}
|
||||
|
||||
const itemsKey = (await this.itemManager.insertItem(itemTemplate)) as Models.ItemsKeyInterface
|
||||
const itemsKey = (await this.itemManager.insertItem(itemTemplate)) as ItemsKeyInterface
|
||||
|
||||
await this.itemManager.changeItemsKey(itemsKey, (mutator) => {
|
||||
mutator.isDefault = true
|
||||
@@ -626,7 +630,7 @@ export class RootKeyEncryptionService extends Services.AbstractService<RootKeySe
|
||||
return rollback
|
||||
}
|
||||
|
||||
override async getDiagnostics(): Promise<Services.DiagnosticInfo | undefined> {
|
||||
override async getDiagnostics(): Promise<DiagnosticInfo | undefined> {
|
||||
return {
|
||||
rootKeyEncryption: {
|
||||
hasRootKey: this.rootKey != undefined,
|
||||
@@ -1,4 +1,3 @@
|
||||
import { DecryptedBytes, EncryptedBytes, FileMemoryCache, OrderedByteChunker } from '@standardnotes/filepicker'
|
||||
import { ClientDisplayableError } from '@standardnotes/responses'
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
import {
|
||||
@@ -13,21 +12,7 @@ import {
|
||||
} from '@standardnotes/models'
|
||||
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
||||
import { UuidGenerator } from '@standardnotes/utils'
|
||||
import {
|
||||
AbstractService,
|
||||
InternalEventBusInterface,
|
||||
ItemManagerInterface,
|
||||
SyncServiceInterface,
|
||||
AlertService,
|
||||
FileSystemApi,
|
||||
FilesApiInterface,
|
||||
FileBackupMetadataFile,
|
||||
FileHandleRead,
|
||||
FileSystemNoSelection,
|
||||
ChallengeServiceInterface,
|
||||
FileBackupsConstantsV1,
|
||||
} from '@standardnotes/services'
|
||||
import { DecryptItemsKeyWithUserFallback, EncryptionProvider, SNItemsKey } from '@standardnotes/encryption'
|
||||
import { EncryptionProvider, SNItemsKey } from '@standardnotes/encryption'
|
||||
import {
|
||||
DownloadAndDecryptFileOperation,
|
||||
EncryptAndUploadFileOperation,
|
||||
@@ -35,8 +20,26 @@ import {
|
||||
FileDownloadProgress,
|
||||
FilesClientInterface,
|
||||
readAndDecryptBackupFile,
|
||||
FilesApiInterface,
|
||||
FileBackupsConstantsV1,
|
||||
FileBackupMetadataFile,
|
||||
FileSystemApi,
|
||||
FileHandleRead,
|
||||
FileSystemNoSelection,
|
||||
EncryptedBytes,
|
||||
DecryptedBytes,
|
||||
OrderedByteChunker,
|
||||
FileMemoryCache,
|
||||
} from '@standardnotes/files'
|
||||
|
||||
import { AlertService } from '../Alert/AlertService'
|
||||
import { ChallengeServiceInterface } from '../Challenge'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
|
||||
import { AbstractService } from '../Service/AbstractService'
|
||||
import { SyncServiceInterface } from '../Sync/SyncServiceInterface'
|
||||
import { DecryptItemsKeyWithUserFallback } from '../Encryption/Functions'
|
||||
|
||||
const OneHundredMb = 100 * 1_000_000
|
||||
|
||||
export class FileService extends AbstractService implements FilesClientInterface {
|
||||
|
||||
@@ -18,11 +18,16 @@ export * from './Device/DesktopManagerInterface'
|
||||
export * from './Device/DesktopWebCommunication'
|
||||
export * from './Device/DeviceInterface'
|
||||
export * from './Device/Environments'
|
||||
export * from './Device/FileBackupsDevice'
|
||||
export * from './Device/MobileDeviceInterface'
|
||||
export * from './Device/TypeCheck'
|
||||
export * from './Device/WebOrDesktopDeviceInterface'
|
||||
export * from './Diagnostics/ServiceDiagnostics'
|
||||
export * from './Encryption/BackupFileDecryptor'
|
||||
export * from './Encryption/EncryptionService'
|
||||
export * from './Encryption/EncryptionServiceEvent'
|
||||
export * from './Encryption/Functions'
|
||||
export * from './Encryption/ItemsEncryption'
|
||||
export * from './Encryption/RootKeyEncryption'
|
||||
export * from './Event/ApplicationEvent'
|
||||
export * from './Event/ApplicationEventCallback'
|
||||
export * from './Event/EventObserver'
|
||||
@@ -34,6 +39,7 @@ export * from './Feature/FeaturesClientInterface'
|
||||
export * from './Feature/FeaturesEvent'
|
||||
export * from './Feature/OfflineSubscriptionEntitlements'
|
||||
export * from './Feature/SetOfflineFeaturesFunctionResponse'
|
||||
export * from './Files/FileService'
|
||||
export * from './Integrity/IntegrityApiInterface'
|
||||
export * from './Integrity/IntegrityEvent'
|
||||
export * from './Integrity/IntegrityEventPayload'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { SnjsVersion } from './../Version'
|
||||
import {
|
||||
HttpService,
|
||||
HttpServiceInterface,
|
||||
@@ -10,13 +9,11 @@ import {
|
||||
} from '@standardnotes/api'
|
||||
import * as Common from '@standardnotes/common'
|
||||
import * as ExternalServices from '@standardnotes/services'
|
||||
import * as Encryption from '@standardnotes/encryption'
|
||||
import * as Models from '@standardnotes/models'
|
||||
import * as Responses from '@standardnotes/responses'
|
||||
import * as InternalServices from '../Services'
|
||||
import * as Utils from '@standardnotes/utils'
|
||||
import * as Settings from '@standardnotes/settings'
|
||||
import * as Files from '@standardnotes/files'
|
||||
import { Subscription } from '@standardnotes/security'
|
||||
import { UuidString, ApplicationEventPayload } from '../Types'
|
||||
import { applicationEventForSyncEvent } from '@Lib/Application/Event'
|
||||
@@ -36,11 +33,19 @@ import {
|
||||
DeinitSource,
|
||||
AppGroupManagedApplication,
|
||||
ApplicationInterface,
|
||||
EncryptionService,
|
||||
EncryptionServiceEvent,
|
||||
FilesBackupService,
|
||||
FileService,
|
||||
} from '@standardnotes/services'
|
||||
import { SNLog } from '../Log'
|
||||
import { FilesClientInterface } from '@standardnotes/files'
|
||||
import { ComputePrivateWorkspaceIdentifier } from '@standardnotes/encryption'
|
||||
import { useBoolean } from '@standardnotes/utils'
|
||||
import { BackupFile, DecryptedItemInterface, EncryptedItemInterface, ItemStream } from '@standardnotes/models'
|
||||
import { ClientDisplayableError } from '@standardnotes/responses'
|
||||
|
||||
import { SnjsVersion } from './../Version'
|
||||
import { SNLog } from '../Log'
|
||||
import { Challenge, ChallengeResponse } from '../Services'
|
||||
import { ApplicationConstructorOptions, FullyResolvedApplicationOptions } from './Options/ApplicationOptions'
|
||||
import { ApplicationOptionsDefaults } from './Options/Defaults'
|
||||
@@ -78,7 +83,7 @@ export class SNApplication
|
||||
private deprecatedHttpService!: InternalServices.SNHttpService
|
||||
private declare httpService: HttpServiceInterface
|
||||
private payloadManager!: InternalServices.PayloadManager
|
||||
public protocolService!: Encryption.EncryptionService
|
||||
public protocolService!: EncryptionService
|
||||
private diskStorageService!: InternalServices.DiskStorageService
|
||||
private inMemoryStore!: ExternalServices.KeyValueStoreInterface<string>
|
||||
/**
|
||||
@@ -104,11 +109,11 @@ export class SNApplication
|
||||
private settingsService!: InternalServices.SNSettingsService
|
||||
private mfaService!: InternalServices.SNMfaService
|
||||
private listedService!: InternalServices.ListedService
|
||||
private fileService!: Files.FileService
|
||||
private fileService!: FileService
|
||||
private mutatorService!: InternalServices.MutatorService
|
||||
private integrityService!: ExternalServices.IntegrityService
|
||||
private statusService!: ExternalServices.StatusService
|
||||
private filesBackupService?: Files.FilesBackupService
|
||||
private filesBackupService?: FilesBackupService
|
||||
|
||||
private internalEventBus!: ExternalServices.InternalEventBusInterface
|
||||
|
||||
@@ -182,7 +187,7 @@ export class SNApplication
|
||||
this.defineInternalEventHandlers()
|
||||
}
|
||||
|
||||
public get files(): Files.FilesClientInterface {
|
||||
public get files(): FilesClientInterface {
|
||||
return this.fileService
|
||||
}
|
||||
|
||||
@@ -222,7 +227,7 @@ export class SNApplication
|
||||
return this.statusService
|
||||
}
|
||||
|
||||
public get fileBackups(): Files.FilesBackupService | undefined {
|
||||
public get fileBackups(): FilesBackupService | undefined {
|
||||
return this.filesBackupService
|
||||
}
|
||||
|
||||
@@ -231,7 +236,7 @@ export class SNApplication
|
||||
}
|
||||
|
||||
public computePrivateWorkspaceIdentifier(userphrase: string, name: string): Promise<string | undefined> {
|
||||
return Encryption.ComputePrivateWorkspaceIdentifier(this.options.crypto, userphrase, name)
|
||||
return ComputePrivateWorkspaceIdentifier(this.options.crypto, userphrase, name)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1117,7 +1122,7 @@ export class SNApplication
|
||||
}
|
||||
|
||||
private createFileService() {
|
||||
this.fileService = new Files.FileService(
|
||||
this.fileService = new FileService(
|
||||
this.apiService,
|
||||
this.itemManager,
|
||||
this.syncService,
|
||||
@@ -1328,7 +1333,7 @@ export class SNApplication
|
||||
}
|
||||
|
||||
private createProtocolService() {
|
||||
this.protocolService = new Encryption.EncryptionService(
|
||||
this.protocolService = new EncryptionService(
|
||||
this.itemManager,
|
||||
this.payloadManager,
|
||||
this.deviceInterface,
|
||||
@@ -1339,7 +1344,7 @@ export class SNApplication
|
||||
)
|
||||
this.serviceObservers.push(
|
||||
this.protocolService.addEventObserver(async (event) => {
|
||||
if (event === Encryption.EncryptionServiceEvent.RootKeyStatusChanged) {
|
||||
if (event === EncryptionServiceEvent.RootKeyStatusChanged) {
|
||||
await this.notifyEvent(ApplicationEvent.KeyStatusChanged)
|
||||
}
|
||||
}),
|
||||
@@ -1539,7 +1544,7 @@ export class SNApplication
|
||||
}
|
||||
|
||||
private createFilesBackupService(device: ExternalServices.DesktopDeviceInterface): void {
|
||||
this.filesBackupService = new Files.FilesBackupService(
|
||||
this.filesBackupService = new FilesBackupService(
|
||||
this.itemManager,
|
||||
this.apiService,
|
||||
this.protocolService,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { SNSessionManager } from '../Services/Session/SessionManager'
|
||||
import { ApplicationIdentifier } from '@standardnotes/common'
|
||||
import { ItemManager } from '@Lib/Services/Items/ItemManager'
|
||||
import { EncryptionService } from '@standardnotes/encryption'
|
||||
import { DeviceInterface, InternalEventBusInterface, Environment } from '@standardnotes/services'
|
||||
import { DeviceInterface, InternalEventBusInterface, Environment, EncryptionService } from '@standardnotes/services'
|
||||
import { ChallengeService, SNSingletonManager, SNFeaturesService, DiskStorageService } from '@Lib/Services'
|
||||
|
||||
export type MigrationServices = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EncryptionService, SNRootKey } from '@standardnotes/encryption'
|
||||
import { SNRootKey } from '@standardnotes/encryption'
|
||||
import { Challenge, ChallengeService } from '../Challenge'
|
||||
import { ListedService } from '../Listed/ListedService'
|
||||
import { ActionResponse, HttpResponse } from '@standardnotes/responses'
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
ChallengeValidation,
|
||||
ChallengeReason,
|
||||
ChallengePrompt,
|
||||
EncryptionService,
|
||||
} from '@standardnotes/services'
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,9 +12,10 @@ import {
|
||||
ApiServiceEvent,
|
||||
MetaReceivedData,
|
||||
DiagnosticInfo,
|
||||
FilesApiInterface,
|
||||
KeyValueStoreInterface,
|
||||
} from '@standardnotes/services'
|
||||
import { FilesApiInterface } from '@standardnotes/files'
|
||||
|
||||
import { ServerSyncPushContextualPayload, SNFeatureRepo, FileContent } from '@standardnotes/models'
|
||||
import * as Responses from '@standardnotes/responses'
|
||||
import { API_MESSAGE_FAILED_OFFLINE_ACTIVATION } from '@Lib/Services/Api/Messages'
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { RootKeyInterface } from '@standardnotes/models'
|
||||
import { EncryptionService } from '@standardnotes/encryption'
|
||||
import { DiskStorageService } from '../Storage/DiskStorageService'
|
||||
import { removeFromArray } from '@standardnotes/utils'
|
||||
import { isValidProtectionSessionLength } from '../Protection/ProtectionService'
|
||||
@@ -14,6 +13,7 @@ import {
|
||||
ChallengeInterface,
|
||||
ChallengePromptInterface,
|
||||
ChallengePrompt,
|
||||
EncryptionService,
|
||||
} from '@standardnotes/services'
|
||||
import { ChallengeResponse } from './ChallengeResponse'
|
||||
import { ChallengeOperation } from './ChallengeOperation'
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ContentType, Uuid } from '@standardnotes/common'
|
||||
import { EncryptionService } from '@standardnotes/encryption'
|
||||
import { isNullOrUndefined, removeFromArray } from '@standardnotes/utils'
|
||||
import { ItemManager } from '@Lib/Services/Items/ItemManager'
|
||||
import { SNApiService } from '@Lib/Services/Api/ApiService'
|
||||
@@ -7,8 +6,8 @@ import { DiskStorageService } from '@Lib/Services/Storage/DiskStorageService'
|
||||
import { UuidString } from '../../Types/UuidString'
|
||||
import * as Models from '@standardnotes/models'
|
||||
import * as Responses from '@standardnotes/responses'
|
||||
import * as Services from '@standardnotes/services'
|
||||
import { isErrorDecryptingPayload, PayloadTimestampDefaults, SNNote } from '@standardnotes/models'
|
||||
import { AbstractService, EncryptionService, DeviceInterface, InternalEventBusInterface } from '@standardnotes/services'
|
||||
|
||||
/** The amount of revisions per item above which should call for an optimization. */
|
||||
const DefaultItemRevisionsThreshold = 20
|
||||
@@ -28,7 +27,7 @@ const LargeEntryDeltaThreshold = 25
|
||||
* 2. Remote server history. Entries are automatically added by the server and must be
|
||||
* retrieved per item via an API call.
|
||||
*/
|
||||
export class SNHistoryManager extends Services.AbstractService {
|
||||
export class SNHistoryManager extends AbstractService {
|
||||
private removeChangeObserver: () => void
|
||||
|
||||
/**
|
||||
@@ -49,8 +48,8 @@ export class SNHistoryManager extends Services.AbstractService {
|
||||
private storageService: DiskStorageService,
|
||||
private apiService: SNApiService,
|
||||
private protocolService: EncryptionService,
|
||||
public deviceInterface: Services.DeviceInterface,
|
||||
protected override internalEventBus: Services.InternalEventBusInterface,
|
||||
public deviceInterface: DeviceInterface,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
this.removeChangeObserver = this.itemManager.addObserver(ContentType.Note, ({ changed, inserted }) => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
import { ItemsKeyInterface } from '@standardnotes/models'
|
||||
import { dateSorted } from '@standardnotes/utils'
|
||||
import { SNRootKeyParams, DecryptItemsKeyByPromptingUser, EncryptionProvider } from '@standardnotes/encryption'
|
||||
import { SNRootKeyParams, EncryptionProvider } from '@standardnotes/encryption'
|
||||
import { DecryptionQueueItem, KeyRecoveryOperationResult } from './Types'
|
||||
import { serverKeyParamsAreSafe } from './Utils'
|
||||
import { ChallengeServiceInterface } from '@standardnotes/services'
|
||||
import { ChallengeServiceInterface, DecryptItemsKeyByPromptingUser } from '@standardnotes/services'
|
||||
import { ItemManager } from '../Items'
|
||||
|
||||
export class KeyRecoveryOperation {
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { KeyRecoveryOperation } from './KeyRecoveryOperation'
|
||||
import {
|
||||
SNRootKeyParams,
|
||||
EncryptionService,
|
||||
SNRootKey,
|
||||
KeyParamsFromApiResponse,
|
||||
KeyRecoveryStrings,
|
||||
} from '@standardnotes/encryption'
|
||||
import { SNRootKeyParams, SNRootKey, KeyParamsFromApiResponse, KeyRecoveryStrings } from '@standardnotes/encryption'
|
||||
import { UserService } from '../User/UserService'
|
||||
import {
|
||||
isErrorDecryptingPayload,
|
||||
@@ -37,6 +31,7 @@ import {
|
||||
ChallengeValidation,
|
||||
ChallengeReason,
|
||||
ChallengePrompt,
|
||||
EncryptionService,
|
||||
} from '@standardnotes/services'
|
||||
import {
|
||||
UndecryptableItemsStorage,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { SNHistoryManager } from './../History/HistoryManager'
|
||||
import { NoteContent, SNNote, FillItemContent, DecryptedPayload, PayloadTimestampDefaults } from '@standardnotes/models'
|
||||
import { EncryptionService } from '@standardnotes/encryption'
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
import { InternalEventBusInterface } from '@standardnotes/services'
|
||||
import { EncryptionService, InternalEventBusInterface } from '@standardnotes/services'
|
||||
import {
|
||||
ChallengeService,
|
||||
MutatorService,
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { ChallengeService } from '../Challenge'
|
||||
import { EncryptionService } from '@standardnotes/encryption'
|
||||
import { DiskStorageService } from '../Storage/DiskStorageService'
|
||||
import { SNProtectionService } from './ProtectionService'
|
||||
import { InternalEventBus, InternalEventBusInterface, ChallengeReason } from '@standardnotes/services'
|
||||
import {
|
||||
InternalEventBus,
|
||||
InternalEventBusInterface,
|
||||
ChallengeReason,
|
||||
EncryptionService,
|
||||
} from '@standardnotes/services'
|
||||
import { UuidGenerator } from '@standardnotes/utils'
|
||||
import {
|
||||
DecryptedPayload,
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Challenge } from './../Challenge/Challenge'
|
||||
import { ChallengeService } from './../Challenge/ChallengeService'
|
||||
import { SNLog } from '@Lib/Log'
|
||||
import { DecryptedItem } from '@standardnotes/models'
|
||||
import { EncryptionService } from '@standardnotes/encryption'
|
||||
import { DiskStorageService } from '@Lib/Services/Storage/DiskStorageService'
|
||||
import { isNullOrUndefined } from '@standardnotes/utils'
|
||||
import {
|
||||
@@ -15,6 +14,7 @@ import {
|
||||
ChallengeReason,
|
||||
ChallengePrompt,
|
||||
ChallengeValidation,
|
||||
EncryptionService,
|
||||
} from '@standardnotes/services'
|
||||
import { ProtectionsClientInterface } from './ClientInterface'
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
|
||||
@@ -9,19 +9,14 @@ import {
|
||||
ChallengeKeyboardType,
|
||||
ChallengeReason,
|
||||
ChallengePromptTitle,
|
||||
EncryptionService,
|
||||
} from '@standardnotes/services'
|
||||
import { Base64String } from '@standardnotes/sncrypto-common'
|
||||
import { ClientDisplayableError } from '@standardnotes/responses'
|
||||
import { CopyPayloadWithContentOverride } from '@standardnotes/models'
|
||||
import { isNullOrUndefined } from '@standardnotes/utils'
|
||||
import { JwtSession } from './Sessions/JwtSession'
|
||||
import {
|
||||
KeyParamsFromApiResponse,
|
||||
SNRootKeyParams,
|
||||
SNRootKey,
|
||||
EncryptionService,
|
||||
CreateNewRootKey,
|
||||
} from '@standardnotes/encryption'
|
||||
import { KeyParamsFromApiResponse, SNRootKeyParams, SNRootKey, CreateNewRootKey } from '@standardnotes/encryption'
|
||||
import { SessionStrings, SignInStrings } from '../Api/Messages'
|
||||
import { RemoteSession, RawStorageValue } from './Sessions/Types'
|
||||
import { Session } from './Sessions/Session'
|
||||
|
||||
@@ -26,7 +26,6 @@ import { ServerSyncResponse } from '@Lib/Services/Sync/Account/Response'
|
||||
import { ServerSyncResponseResolver } from '@Lib/Services/Sync/Account/ResponseResolver'
|
||||
import { SyncSignal, SyncStats } from '@Lib/Services/Sync/Signals'
|
||||
import { UuidString } from '../../Types/UuidString'
|
||||
import * as Encryption from '@standardnotes/encryption'
|
||||
import {
|
||||
PayloadSource,
|
||||
CreateDecryptedItemFromPayload,
|
||||
@@ -73,9 +72,15 @@ import {
|
||||
SyncQueueStrategy,
|
||||
SyncServiceInterface,
|
||||
DiagnosticInfo,
|
||||
EncryptionService,
|
||||
} from '@standardnotes/services'
|
||||
import { OfflineSyncResponse } from './Offline/Response'
|
||||
import { KeyedDecryptionSplit, SplitPayloadsByEncryptionType } from '@standardnotes/encryption'
|
||||
import {
|
||||
CreateDecryptionSplitWithKeyLookup,
|
||||
CreateEncryptionSplitWithKeyLookup,
|
||||
KeyedDecryptionSplit,
|
||||
SplitPayloadsByEncryptionType,
|
||||
} from '@standardnotes/encryption'
|
||||
import { CreatePayloadFromRawServerItem } from './Account/Utilities'
|
||||
import { ApplicationSyncOptions } from '@Lib/Application/Options/OptionalOptions'
|
||||
|
||||
@@ -131,7 +136,7 @@ export class SNSyncService
|
||||
constructor(
|
||||
private itemManager: ItemManager,
|
||||
private sessionManager: SNSessionManager,
|
||||
private protocolService: Encryption.EncryptionService,
|
||||
private protocolService: EncryptionService,
|
||||
private storageService: DiskStorageService,
|
||||
private payloadManager: PayloadManager,
|
||||
private apiService: SNApiService,
|
||||
@@ -226,7 +231,7 @@ export class SNSyncService
|
||||
isDecryptedPayload,
|
||||
) as DecryptedPayloadInterface<ItemsKeyContent>[]
|
||||
|
||||
const itemsKeysSplit: Encryption.KeyedDecryptionSplit = {
|
||||
const itemsKeysSplit: KeyedDecryptionSplit = {
|
||||
usesRootKeyWithKeyLookup: {
|
||||
items: encryptedItemsKeysPayloads,
|
||||
},
|
||||
@@ -301,7 +306,7 @@ export class SNSyncService
|
||||
}
|
||||
}
|
||||
|
||||
const split: Encryption.KeyedDecryptionSplit = {
|
||||
const split: KeyedDecryptionSplit = {
|
||||
usesItemsKeyWithKeyLookup: {
|
||||
items: encrypted,
|
||||
},
|
||||
@@ -440,9 +445,9 @@ export class SNSyncService
|
||||
): Promise<ServerSyncPushContextualPayload[]> {
|
||||
const payloadSplit = CreatePayloadSplit(payloads)
|
||||
|
||||
const encryptionSplit = Encryption.SplitPayloadsByEncryptionType(payloadSplit.decrypted)
|
||||
const encryptionSplit = SplitPayloadsByEncryptionType(payloadSplit.decrypted)
|
||||
|
||||
const keyLookupSplit = Encryption.CreateEncryptionSplitWithKeyLookup(encryptionSplit)
|
||||
const keyLookupSplit = CreateEncryptionSplitWithKeyLookup(encryptionSplit)
|
||||
|
||||
const encryptedResults = await this.protocolService.encryptSplit(keyLookupSplit)
|
||||
|
||||
@@ -973,7 +978,7 @@ export class SNSyncService
|
||||
? (CreateDecryptedItemFromPayload(previouslyProcessedItemsKey) as ItemsKeyInterface)
|
||||
: undefined
|
||||
|
||||
const keyedSplit: Encryption.KeyedDecryptionSplit = {}
|
||||
const keyedSplit: KeyedDecryptionSplit = {}
|
||||
if (itemsKey) {
|
||||
keyedSplit.usesItemsKey = {
|
||||
items: [encrypted],
|
||||
@@ -1162,9 +1167,9 @@ export class SNSyncService
|
||||
|
||||
const payloadSplit = CreateNonDecryptedPayloadSplit(receivedPayloads)
|
||||
|
||||
const encryptionSplit = Encryption.SplitPayloadsByEncryptionType(payloadSplit.encrypted)
|
||||
const encryptionSplit = SplitPayloadsByEncryptionType(payloadSplit.encrypted)
|
||||
|
||||
const keyedSplit = Encryption.CreateDecryptionSplitWithKeyLookup(encryptionSplit)
|
||||
const keyedSplit = CreateDecryptionSplitWithKeyLookup(encryptionSplit)
|
||||
|
||||
const decryptionResults = await this.protocolService.decryptSplit(keyedSplit)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Challenge } from '../Challenge'
|
||||
import { ChallengeService } from '../Challenge/ChallengeService'
|
||||
import { EncryptionService, SNRootKey, SNRootKeyParams } from '@standardnotes/encryption'
|
||||
import { SNRootKey, SNRootKeyParams } from '@standardnotes/encryption'
|
||||
import { HttpResponse, SignInResponse, User } from '@standardnotes/responses'
|
||||
import { ItemManager } from '@Lib/Services/Items/ItemManager'
|
||||
import { KeyParamsOrigination } from '@standardnotes/common'
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
InternalEventBusInterface,
|
||||
UserClientInterface,
|
||||
StoragePersistencePolicies,
|
||||
EncryptionService,
|
||||
} from '@standardnotes/services'
|
||||
import { SNApiService } from './../Api/ApiService'
|
||||
import { SNProtectionService } from '../Protection/ProtectionService'
|
||||
|
||||
@@ -8,31 +8,40 @@ import {
|
||||
SNTheme,
|
||||
} from '@standardnotes/models'
|
||||
import { removeFromArray } from '@standardnotes/utils'
|
||||
import { ApplicationEvent, ApplicationService, FeatureStatus, InternalEventBus, StorageValueModes, WebApplicationInterface } from '@standardnotes/snjs'
|
||||
import {
|
||||
AbstractService,
|
||||
WebApplicationInterface,
|
||||
InternalEventBusInterface,
|
||||
ApplicationEvent,
|
||||
StorageValueModes,
|
||||
FeatureStatus,
|
||||
} from '@standardnotes/services'
|
||||
|
||||
const CachedThemesKey = 'cachedThemes'
|
||||
const TimeBeforeApplyingColorScheme = 5
|
||||
const DefaultThemeIdentifier = 'Default'
|
||||
|
||||
export class ThemeManager extends ApplicationService {
|
||||
export class ThemeManager extends AbstractService {
|
||||
private activeThemes: Uuid[] = []
|
||||
private unregisterDesktop?: () => void
|
||||
private unregisterStream!: () => void
|
||||
private lastUseDeviceThemeSettings = false
|
||||
private unsubApp!: () => void
|
||||
|
||||
constructor(application: WebApplicationInterface) {
|
||||
super(application, new InternalEventBus())
|
||||
constructor(
|
||||
protected application: WebApplicationInterface,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
this.addAppEventObserverAfterSubclassesFinishConstructing()
|
||||
this.colorSchemeEventHandler = this.colorSchemeEventHandler.bind(this)
|
||||
}
|
||||
|
||||
override async onAppStart() {
|
||||
super.onAppStart().catch(console.error)
|
||||
async onAppStart() {
|
||||
this.registerObservers()
|
||||
}
|
||||
|
||||
override async onAppEvent(event: ApplicationEvent) {
|
||||
super.onAppEvent(event).catch(console.error)
|
||||
|
||||
async onAppEvent(event: ApplicationEvent) {
|
||||
switch (event) {
|
||||
case ApplicationEvent.SignedOut: {
|
||||
this.deactivateAllThemes()
|
||||
@@ -59,6 +68,25 @@ export class ThemeManager extends ApplicationService {
|
||||
}
|
||||
}
|
||||
|
||||
addAppEventObserverAfterSubclassesFinishConstructing() {
|
||||
setTimeout(() => {
|
||||
this.addAppEventObserver()
|
||||
}, 0)
|
||||
}
|
||||
|
||||
addAppEventObserver() {
|
||||
if (this.application.isStarted()) {
|
||||
void this.onAppStart()
|
||||
}
|
||||
|
||||
this.unsubApp = this.application.addEventObserver(async (event: ApplicationEvent) => {
|
||||
await this.onAppEvent(event)
|
||||
if (event === ApplicationEvent.Started) {
|
||||
void this.onAppStart()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private handlePreferencesChangeEvent(): void {
|
||||
const useDeviceThemeSettings = this.application.getPreference(PrefKey.UseSystemColorScheme, false)
|
||||
|
||||
@@ -86,6 +114,10 @@ export class ThemeManager extends ApplicationService {
|
||||
;(this.unregisterStream as unknown) = undefined
|
||||
|
||||
window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', this.colorSchemeEventHandler)
|
||||
;(this.application as unknown) = undefined
|
||||
|
||||
this.unsubApp()
|
||||
;(this.unsubApp as unknown) = undefined
|
||||
|
||||
super.deinit()
|
||||
}
|
||||
@@ -4,3 +4,4 @@ export * from './Archive/ArchiveManager'
|
||||
export * from './IO/IOService'
|
||||
export * from './Security/AutolockService'
|
||||
export * from './Storage/LocalStorage'
|
||||
export * from './Theme/ThemeManager'
|
||||
|
||||
@@ -22,8 +22,7 @@ import { makeObservable, observable } from 'mobx'
|
||||
import { PanelResizedData } from '@/Types/PanelResizedData'
|
||||
import { isDesktopApplication } from '@/Utils'
|
||||
import { DesktopManager } from './Device/DesktopManager'
|
||||
import { ArchiveManager, AutolockService, IOService, WebAlertService } from '@standardnotes/ui-services'
|
||||
import { ThemeManager } from '@/Theme/ThemeManager'
|
||||
import { ArchiveManager, AutolockService, IOService, WebAlertService, ThemeManager } from '@standardnotes/ui-services'
|
||||
|
||||
type WebServices = {
|
||||
viewControllerManager: ViewControllerManager
|
||||
|
||||
@@ -33,8 +33,9 @@ const createApplication = (
|
||||
const viewControllerManager = new ViewControllerManager(application, device)
|
||||
const archiveService = new ArchiveManager(application)
|
||||
const io = new IOService(platform === Platform.MacWeb || platform === Platform.MacDesktop)
|
||||
const autolockService = new AutolockService(application, new InternalEventBus())
|
||||
const themeService = new ThemeManager(application)
|
||||
const internalEventBus = new InternalEventBus()
|
||||
const autolockService = new AutolockService(application, internalEventBus)
|
||||
const themeService = new ThemeManager(application, internalEventBus)
|
||||
|
||||
application.setWebServices({
|
||||
viewControllerManager,
|
||||
|
||||
@@ -6576,7 +6576,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@standardnotes/encryption@workspace:*, @standardnotes/encryption@workspace:packages/encryption":
|
||||
"@standardnotes/encryption@workspace:*, @standardnotes/encryption@workspace:^, @standardnotes/encryption@workspace:packages/encryption":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@standardnotes/encryption@workspace:packages/encryption"
|
||||
dependencies:
|
||||
@@ -6584,7 +6584,6 @@ __metadata:
|
||||
"@standardnotes/config": 2.4.3
|
||||
"@standardnotes/models": "workspace:*"
|
||||
"@standardnotes/responses": "workspace:*"
|
||||
"@standardnotes/services": "workspace:*"
|
||||
"@standardnotes/sncrypto-common": "workspace:*"
|
||||
"@standardnotes/utils": "workspace:*"
|
||||
"@types/jest": ^28.1.5
|
||||
@@ -7179,6 +7178,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@standardnotes/auth": ^3.19.4
|
||||
"@standardnotes/common": ^1.30.0
|
||||
"@standardnotes/encryption": "workspace:^"
|
||||
"@standardnotes/files": "workspace:^"
|
||||
"@standardnotes/models": "workspace:^"
|
||||
"@standardnotes/responses": "workspace:*"
|
||||
|
||||
Reference in New Issue
Block a user