refactor(web): dependency management (#2386)

This commit is contained in:
Mo
2023-08-05 12:48:39 -05:00
committed by GitHub
parent b07da5b663
commit d8d4052a52
274 changed files with 4065 additions and 3873 deletions

View File

@@ -1,4 +1,4 @@
import { SNMfaService } from './../Services/Mfa/MfaService'
import { MfaService } from './../Services/Mfa/MfaService'
import { KeyRecoveryService } from './../Services/KeyRecovery/KeyRecoveryService'
import { WebSocketsService } from './../Services/Api/WebsocketsService'
import { MigrationService } from './../Services/Migration/MigrationService'
@@ -20,7 +20,6 @@ import {
ApplicationStageChangedEventPayload,
StorageValueModes,
ChallengeObserver,
SyncOptions,
ImportDataReturnType,
ImportDataUseCase,
StoragePersistencePolicies,
@@ -57,7 +56,6 @@ import {
ApplicationInterface,
EncryptionService,
EncryptionServiceEvent,
ChallengePrompt,
Challenge,
ErrorAlertStrings,
SessionsClientInterface,
@@ -75,32 +73,33 @@ import {
VaultInviteServiceInterface,
NotificationServiceEvent,
VaultLockServiceInterface,
ApplicationConstructorOptions,
FullyResolvedApplicationOptions,
ApplicationOptionsDefaults,
ChangeAndSaveItem,
ProtectionEvent,
GetHost,
SetHost,
MfaServiceInterface,
} from '@standardnotes/services'
import {
PayloadEmitSource,
SNNote,
PrefKey,
PrefValue,
DecryptedItemMutator,
BackupFile,
DecryptedItemInterface,
EncryptedItemInterface,
Environment,
ItemStream,
Platform,
MutationType,
} from '@standardnotes/models'
import {
HttpResponse,
SessionListResponse,
User,
SignInResponse,
ClientDisplayableError,
SessionListEntry,
} from '@standardnotes/responses'
import {
SyncService,
ProtectionEvent,
SettingsService,
ActionsService,
ChallengeResponse,
@@ -116,14 +115,13 @@ import {
UuidGenerator,
useBoolean,
LoggerInterface,
canBlockDeinit,
} from '@standardnotes/utils'
import { UuidString, ApplicationEventPayload } from '../Types'
import { applicationEventForSyncEvent } from '@Lib/Application/Event'
import { BackupServiceInterface, FilesClientInterface } from '@standardnotes/files'
import { ComputePrivateUsername } from '@standardnotes/encryption'
import { SNLog } from '../Log'
import { ApplicationConstructorOptions, FullyResolvedApplicationOptions } from './Options/ApplicationOptions'
import { ApplicationOptionsDefaults } from './Options/Defaults'
import { SignInWithRecoveryCodes } from '@Lib/Domain/UseCase/SignInWithRecoveryCodes/SignInWithRecoveryCodes'
import { UseCaseContainerInterface } from '@Lib/Domain/UseCase/UseCaseContainerInterface'
import { GetRecoveryCodes } from '@Lib/Domain/UseCase/GetRecoveryCodes/GetRecoveryCodes'
@@ -137,7 +135,6 @@ import { GetAuthenticatorAuthenticationResponse } from '@Lib/Domain/UseCase/GetA
import { GetAuthenticatorAuthenticationOptions } from '@Lib/Domain/UseCase/GetAuthenticatorAuthenticationOptions/GetAuthenticatorAuthenticationOptions'
import { Dependencies } from './Dependencies/Dependencies'
import { TYPES } from './Dependencies/Types'
import { canBlockDeinit } from './Dependencies/isDeinitable'
/** How often to automatically sync, in milliseconds */
const DEFAULT_AUTO_SYNC_INTERVAL = 30_000
@@ -165,7 +162,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
private eventHandlers: ApplicationObserver[] = []
private streamRemovers: ObserverRemover[] = []
private serviceObservers: ObserverRemover[] = []
private managedSubscribers: ObserverRemover[] = []
private autoSyncInterval!: ReturnType<typeof setInterval>
@@ -178,7 +174,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
private launched = false
/** Whether the application has been destroyed via .deinit() */
public dealloced = false
private isBiometricsSoftLockEngaged = false
private revokingSession = false
private handledFullSyncStage = false
@@ -561,13 +557,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
void this.migrations.handleApplicationEvent(event)
}
/**
* Whether the local database has completed loading local items.
*/
public isDatabaseLoaded(): boolean {
return this.sync.isDatabaseLoaded()
}
public getSessions(): Promise<HttpResponse<SessionListEntry[]>> {
return this.sessions.getSessionsList()
}
@@ -594,65 +583,12 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return compareVersions(userVersion, ProtocolVersion.V004) >= 0
}
/**
* Begin streaming items to display in the UI. The stream callback will be called
* immediately with the present items that match the constraint, and over time whenever
* items matching the constraint are added, changed, or deleted.
*/
public streamItems<I extends DecryptedItemInterface = DecryptedItemInterface>(
contentType: string | string[],
stream: ItemStream<I>,
): () => void {
const removeItemManagerObserver = this.items.addObserver<I>(
contentType,
({ changed, inserted, removed, source }) => {
stream({ changed, inserted, removed, source })
},
)
const matches = this.items.getItems<I>(contentType)
stream({
inserted: matches,
changed: [],
removed: [],
source: PayloadEmitSource.InitialObserverRegistrationPush,
})
this.streamRemovers.push(removeItemManagerObserver)
return () => {
removeItemManagerObserver()
removeFromArray(this.streamRemovers, removeItemManagerObserver)
}
}
/**
* Set the server's URL
*/
public async setHost(host: string): Promise<void> {
this.http.setHost(host)
await this.legacyApi.setHost(host)
}
public getHost(): string {
return this.legacyApi.getHost()
}
public async setCustomHost(host: string): Promise<void> {
await this.setHost(host)
await this.setHost.execute(host)
this.sockets.setWebSocketUrl(undefined)
}
public getUser(): User | undefined {
if (!this.launched) {
throw Error('Attempting to access user before application unlocked')
}
return this.sessions.getUser()
}
public getUserPasswordCreationDate(): Date | undefined {
return this.encryption.getPasswordCreatedDate()
}
@@ -699,10 +635,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return result
}
public noAccount(): boolean {
return !this.hasAccount()
}
public hasAccount(): boolean {
return this.encryption.hasAccount()
}
@@ -715,10 +647,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.protections.hasProtectionSources()
}
public hasUnprotectedAccessSession(): boolean {
return this.protections.hasUnprotectedAccessSession()
}
/**
* When a user specifies a non-zero remember duration on a protection
* challenge, a session will be started during which protections are disabled.
@@ -746,10 +674,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.protections.authorizeAutolockIntervalChange()
}
public authorizeSearchingProtectedNotesText(): Promise<boolean> {
return this.protections.authorizeSearchingProtectedNotesText()
}
public async createEncryptedBackupFileForAutomatedDesktopBackups(): Promise<BackupFile | undefined> {
return this.encryption.createEncryptedBackupFile()
}
@@ -852,7 +776,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
this.serviceObservers.length = 0
this.managedSubscribers.length = 0
this.streamRemovers.length = 0
this.started = false
@@ -921,39 +844,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
})
}
public async changeAndSaveItem<M extends DecryptedItemMutator = DecryptedItemMutator>(
itemToLookupUuidFor: DecryptedItemInterface,
mutate: (mutator: M) => void,
updateTimestamps = true,
emitSource?: PayloadEmitSource,
syncOptions?: SyncOptions,
): Promise<DecryptedItemInterface | undefined> {
await this.mutator.changeItems(
[itemToLookupUuidFor],
mutate,
updateTimestamps ? MutationType.UpdateUserTimestamps : MutationType.NoUpdateUserTimestamps,
emitSource,
)
await this.sync.sync(syncOptions)
return this.items.findItem(itemToLookupUuidFor.uuid)
}
public async changeAndSaveItems<M extends DecryptedItemMutator = DecryptedItemMutator>(
itemsToLookupUuidsFor: DecryptedItemInterface[],
mutate: (mutator: M) => void,
updateTimestamps = true,
emitSource?: PayloadEmitSource,
syncOptions?: SyncOptions,
): Promise<void> {
await this.mutator.changeItems(
itemsToLookupUuidsFor,
mutate,
updateTimestamps ? MutationType.UpdateUserTimestamps : MutationType.NoUpdateUserTimestamps,
emitSource,
)
await this.sync.sync(syncOptions)
}
public async importData(data: BackupFile, awaitSync = false): Promise<ImportDataReturnType> {
const usecase = this.dependencies.get<ImportDataUseCase>(TYPES.ImportDataUseCase)
return usecase.execute(data, awaitSync)
@@ -991,42 +881,18 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.encryption.hasPasscode()
}
async isLocked(): Promise<boolean> {
if (!this.started) {
return Promise.resolve(true)
}
const isPasscodeLocked = await this.challenges.isPasscodeLocked()
return isPasscodeLocked || this.isBiometricsSoftLockEngaged
}
public async lock(): Promise<void> {
/** Because locking is a critical operation, we want to try to do it safely,
* but only up to a certain limit. */
/**
* Because locking is a critical operation, we want to try to do it safely,
* but only up to a certain limit.
*/
const MaximumWaitTime = 500
await this.prepareForDeinit(MaximumWaitTime)
return this.deinit(this.getDeinitMode(), DeinitSource.Lock)
}
public softLockBiometrics(): void {
const challenge = new Challenge(
[new ChallengePrompt(ChallengeValidation.Biometric)],
ChallengeReason.ApplicationUnlock,
false,
)
void this.challenges.promptForChallengeResponse(challenge)
this.isBiometricsSoftLockEngaged = true
void this.notifyEvent(ApplicationEvent.BiometricsSoftLockEngaged)
this.addChallengeObserver(challenge, {
onComplete: () => {
this.isBiometricsSoftLockEngaged = false
void this.notifyEvent(ApplicationEvent.BiometricsSoftLockDisengaged)
},
})
}
isNativeMobileWeb() {
return this.environment === Environment.Mobile
}
@@ -1102,10 +968,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
}
}
public getNewSubscriptionToken(): Promise<string | undefined> {
return this.legacyApi.getNewSubscriptionToken()
}
public isThirdPartyHostUsed(): boolean {
return this.legacyApi.isThirdPartyHostUsed()
}
@@ -1117,7 +979,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return false
}
return this.getHost() === (await homeServerService.getHomeServerUrl())
return this.getHost.execute().getValue() === (await homeServerService.getHomeServerUrl())
}
private createBackgroundDependencies() {
@@ -1361,14 +1223,30 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.dependencies.get<SharedVaultServiceInterface>(TYPES.SharedVaultService)
}
private get migrations(): MigrationService {
return this.dependencies.get<MigrationService>(TYPES.MigrationService)
public get changeAndSaveItem(): ChangeAndSaveItem {
return this.dependencies.get<ChangeAndSaveItem>(TYPES.ChangeAndSaveItem)
}
private get legacyApi(): LegacyApiService {
public get getHost(): GetHost {
return this.dependencies.get<GetHost>(TYPES.GetHost)
}
public get setHost(): SetHost {
return this.dependencies.get<SetHost>(TYPES.SetHost)
}
public get legacyApi(): LegacyApiService {
return this.dependencies.get<LegacyApiService>(TYPES.LegacyApiService)
}
public get mfa(): MfaServiceInterface {
return this.dependencies.get<MfaService>(TYPES.MfaService)
}
private get migrations(): MigrationService {
return this.dependencies.get<MigrationService>(TYPES.MigrationService)
}
private get http(): HttpServiceInterface {
return this.dependencies.get<HttpServiceInterface>(TYPES.HttpService)
}
@@ -1376,8 +1254,4 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
private get sockets(): WebSocketsService {
return this.dependencies.get<WebSocketsService>(TYPES.WebSocketsService)
}
private get mfa(): SNMfaService {
return this.dependencies.get<SNMfaService>(TYPES.MfaService)
}
}