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