From 9bec2aa2f07088c462bb678ac12e19d5256223a7 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 6 Dec 2021 11:03:12 +0000 Subject: [PATCH] BEEEP: Refactor services DI (#180) --- jslib | 2 +- src/app/app.component.ts | 3 +- src/app/services/services.module.ts | 189 ++++++++++++++++++---------- src/app/tabs/dashboard.component.ts | 3 +- src/app/tabs/more.component.ts | 3 +- src/bwdc.ts | 10 +- src/program.ts | 2 +- src/services/auth.service.ts | 8 +- 8 files changed, 140 insertions(+), 80 deletions(-) diff --git a/jslib b/jslib index 2db9e1ce..5db94cc9 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 2db9e1ce0d7a702f07f20ecb916dd8191ff617e1 +Subproject commit 5db94cc9d06ba478a29e9b625993108dfa0d7ec8 diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 19beae68..17791d79 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -19,10 +19,9 @@ import { import { DomSanitizer } from '@angular/platform-browser'; import { Router } from '@angular/router'; -import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; - import { ApiService } from 'jslib-common/abstractions/api.service'; import { AuthService } from 'jslib-common/abstractions/auth.service'; +import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts index 200ee422..ce45a0bc 100644 --- a/src/app/services/services.module.ts +++ b/src/app/services/services.module.ts @@ -1,10 +1,9 @@ import { APP_INITIALIZER, + Injector, NgModule, } from '@angular/core'; -import { ToasterModule } from 'angular2-toaster'; - import { ElectronLogService } from 'jslib-electron/services/electronLog.service'; import { ElectronPlatformUtilsService } from 'jslib-electron/services/electronPlatformUtils.service'; import { ElectronRendererMessagingService } from 'jslib-electron/services/electronRendererMessaging.service'; @@ -19,30 +18,26 @@ import { I18nService } from '../../services/i18n.service'; import { SyncService } from '../../services/sync.service'; import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; +import { JslibServicesModule } from 'jslib-angular/services/jslib-services.module'; import { ModalService } from 'jslib-angular/services/modal.service'; import { ValidationService } from 'jslib-angular/services/validation.service'; import { ApiKeyService } from 'jslib-common/services/apiKey.service'; -import { AppIdService } from 'jslib-common/services/appId.service'; import { ConstantsService } from 'jslib-common/services/constants.service'; import { ContainerService } from 'jslib-common/services/container.service'; -import { CryptoService } from 'jslib-common/services/crypto.service'; -import { EnvironmentService } from 'jslib-common/services/environment.service'; -import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service'; -import { PolicyService } from 'jslib-common/services/policy.service'; -import { StateService } from 'jslib-common/services/state.service'; -import { TokenService } from 'jslib-common/services/token.service'; -import { UserService } from 'jslib-common/services/user.service'; import { NodeCryptoFunctionService } from 'jslib-node/services/nodeCryptoFunction.service'; import { ApiService as ApiServiceAbstraction } from 'jslib-common/abstractions/api.service'; import { ApiKeyService as ApiKeyServiceAbstraction } from 'jslib-common/abstractions/apiKey.service'; +import { AppIdService as AppIdServiceAbstraction } from 'jslib-common/abstractions/appId.service'; import { AuthService as AuthServiceAbstraction } from 'jslib-common/abstractions/auth.service'; +import { BroadcasterService as BroadcasterServiceAbstraction } from 'jslib-common/abstractions/broadcaster.service'; import { CryptoService as CryptoServiceAbstraction } from 'jslib-common/abstractions/crypto.service'; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from 'jslib-common/abstractions/cryptoFunction.service'; import { EnvironmentService as EnvironmentServiceAbstraction } from 'jslib-common/abstractions/environment.service'; import { I18nService as I18nServiceAbstraction } from 'jslib-common/abstractions/i18n.service'; +import { KeyConnectorService as KeyConnectorServiceAbstraction } from 'jslib-common/abstractions/keyConnector.service'; import { LogService as LogServiceAbstraction } from 'jslib-common/abstractions/log.service'; import { MessagingService as MessagingServiceAbstraction } from 'jslib-common/abstractions/messaging.service'; import { @@ -54,44 +49,23 @@ import { StateService as StateServiceAbstraction } from 'jslib-common/abstractio import { StorageService as StorageServiceAbstraction } from 'jslib-common/abstractions/storage.service'; import { TokenService as TokenServiceAbstraction } from 'jslib-common/abstractions/token.service'; import { UserService as UserServiceAbstraction } from 'jslib-common/abstractions/user.service'; +import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from 'jslib-common/abstractions/vaultTimeout.service'; import { ApiService, refreshToken } from '../../services/api.service'; import { AuthService } from '../../services/auth.service'; -const logService = new ElectronLogService(); -const i18nService = new I18nService(window.navigator.language, './locales'); -const stateService = new StateService(); -const broadcasterService = new BroadcasterService(); -const messagingService = new ElectronRendererMessagingService(broadcasterService); -const storageService: StorageServiceAbstraction = new ElectronRendererStorageService(); -const platformUtilsService = new ElectronPlatformUtilsService(i18nService, messagingService, false, storageService); -const secureStorageService: StorageServiceAbstraction = new ElectronRendererSecureStorageService(); -const cryptoFunctionService: CryptoFunctionServiceAbstraction = new NodeCryptoFunctionService(); -const cryptoService = new CryptoService(storageService, secureStorageService, cryptoFunctionService, - platformUtilsService, logService); -const appIdService = new AppIdService(storageService); -const tokenService = new TokenService(storageService); -const environmentService = new EnvironmentService(storageService); -const apiService = new ApiService(tokenService, platformUtilsService, environmentService, refreshTokenCallback, - async (expired: boolean) => messagingService.send('logout', { expired: expired })); -const userService = new UserService(tokenService, storageService); -const apiKeyService = new ApiKeyService(tokenService, storageService); -const containerService = new ContainerService(cryptoService); -const authService = new AuthService(cryptoService, apiService, userService, tokenService, appIdService, - i18nService, platformUtilsService, messagingService, null, logService, apiKeyService, cryptoFunctionService, false); -const configurationService = new ConfigurationService(storageService, secureStorageService); -const syncService = new SyncService(configurationService, logService, cryptoFunctionService, apiService, - messagingService, i18nService, environmentService); -const passwordGenerationService = new PasswordGenerationService(cryptoService, storageService, null); -const policyService = new PolicyService(userService, storageService, apiService); - -containerService.attachToWindow(window); - -function refreshTokenCallback(): Promise { - return refreshToken(apiKeyService, authService); +function refreshTokenCallback(injector: Injector) { + return () => { + const apiKeyService = injector.get(ApiKeyServiceAbstraction); + const authService = injector.get(AuthServiceAbstraction); + return refreshToken(apiKeyService, authService); + }; } -export function initFactory(): Function { +export function initFactory(environmentService: EnvironmentServiceAbstraction, + i18nService: I18nService, authService: AuthService, platformUtilsService: PlatformUtilsServiceAbstraction, + storageService: StorageServiceAbstraction, userService: UserServiceAbstraction, apiService: ApiServiceAbstraction, + stateService: StateServiceAbstraction, cryptoService: CryptoServiceAbstraction): Function { return async () => { await environmentService.setUrlsFromStorage(); await i18nService.init(); @@ -120,44 +94,125 @@ export function initFactory(): Function { stateService.save('profileOrganizations', profile.organizations); } }, 500); + + const containerService = new ContainerService(cryptoService); + containerService.attachToWindow(window); }; } @NgModule({ imports: [ - ToasterModule, + JslibServicesModule, ], declarations: [], providers: [ - ValidationService, - AuthGuardService, - LaunchGuardService, - ModalService, - { provide: AuthServiceAbstraction, useValue: authService }, - { provide: EnvironmentServiceAbstraction, useValue: environmentService }, - { provide: TokenServiceAbstraction, useValue: tokenService }, - { provide: I18nServiceAbstraction, useValue: i18nService }, - { provide: CryptoServiceAbstraction, useValue: cryptoService }, - { provide: PlatformUtilsServiceAbstraction, useValue: platformUtilsService }, - { provide: ApiServiceAbstraction, useValue: apiService }, - { provide: UserServiceAbstraction, useValue: userService }, - { provide: ApiKeyServiceAbstraction, useValue: apiKeyService }, - { provide: MessagingServiceAbstraction, useValue: messagingService }, - { provide: BroadcasterService, useValue: broadcasterService }, - { provide: StorageServiceAbstraction, useValue: storageService }, - { provide: StateServiceAbstraction, useValue: stateService }, - { provide: LogServiceAbstraction, useValue: logService }, - { provide: ConfigurationService, useValue: configurationService }, - { provide: SyncService, useValue: syncService }, - { provide: PasswordGenerationServiceAbstraction, useValue: passwordGenerationService }, - { provide: CryptoFunctionServiceAbstraction, useValue: cryptoFunctionService }, - { provide: PolicyServiceAbstraction, useValue: policyService }, { provide: APP_INITIALIZER, useFactory: initFactory, - deps: [], + deps: [ + EnvironmentServiceAbstraction, + I18nServiceAbstraction, + AuthServiceAbstraction, + PlatformUtilsServiceAbstraction, + StorageServiceAbstraction, + UserServiceAbstraction, + ApiServiceAbstraction, + StateServiceAbstraction, + CryptoServiceAbstraction, + ], multi: true, }, + { provide: LogServiceAbstraction, useClass: ElectronLogService, deps: [] }, + { + provide: I18nServiceAbstraction, + useFactory: (window: Window) => new I18nService(window.navigator.language, './locales'), + deps: [ 'WINDOW' ], + }, + { + provide: MessagingServiceAbstraction, + useClass: ElectronRendererMessagingService, + deps: [ BroadcasterServiceAbstraction ], + }, + { provide: StorageServiceAbstraction, useClass: ElectronRendererStorageService }, + { provide: 'SECURE_STORAGE', useClass: ElectronRendererSecureStorageService }, + { + provide: PlatformUtilsServiceAbstraction, + useFactory: (i18nService: I18nServiceAbstraction, messagingService: MessagingServiceAbstraction, + storageService: StorageServiceAbstraction) => new ElectronPlatformUtilsService(i18nService, + messagingService, true, storageService), + deps: [ + I18nServiceAbstraction, + MessagingServiceAbstraction, + StorageServiceAbstraction, + ], + }, + { provide: CryptoFunctionServiceAbstraction, useClass: NodeCryptoFunctionService, deps: [] }, + { + provide: ApiServiceAbstraction, + useFactory: (tokenService: TokenServiceAbstraction, platformUtilsService: PlatformUtilsServiceAbstraction, + environmentService: EnvironmentServiceAbstraction, messagingService: MessagingServiceAbstraction, + injector: Injector) => + new ApiService(tokenService, platformUtilsService, environmentService, refreshTokenCallback(injector), + async (expired: boolean) => messagingService.send('logout', { expired: expired })), + deps: [ + TokenServiceAbstraction, + PlatformUtilsServiceAbstraction, + EnvironmentServiceAbstraction, + MessagingServiceAbstraction, + Injector, + ], + }, + { + provide: ApiKeyServiceAbstraction, + useClass: ApiKeyService, + deps: [ + TokenServiceAbstraction, + StorageServiceAbstraction, + ], + }, + { + provide: AuthServiceAbstraction, + useClass: AuthService, + deps: [ + CryptoServiceAbstraction, + ApiServiceAbstraction, + UserServiceAbstraction, + TokenServiceAbstraction, + AppIdServiceAbstraction, + I18nServiceAbstraction, + PlatformUtilsServiceAbstraction, + MessagingServiceAbstraction, + VaultTimeoutServiceAbstraction, + LogServiceAbstraction, + ApiKeyServiceAbstraction, + CryptoFunctionServiceAbstraction, + EnvironmentServiceAbstraction, + KeyConnectorServiceAbstraction, + ], + }, + { + provide: ConfigurationService, + useClass: ConfigurationService, + deps: [ + StorageServiceAbstraction, + 'SECURE_STORAGE', + ], + }, + { + provide: SyncService, + useClass: SyncService, + deps: [ + ConfigurationService, + LogServiceAbstraction, + CryptoFunctionServiceAbstraction, + ApiServiceAbstraction, + MessagingServiceAbstraction, + I18nServiceAbstraction, + EnvironmentServiceAbstraction, + ], + }, + AuthGuardService, + LaunchGuardService, ], }) export class ServicesModule { diff --git a/src/app/tabs/dashboard.component.ts b/src/app/tabs/dashboard.component.ts index dbf4080d..de30e4db 100644 --- a/src/app/tabs/dashboard.component.ts +++ b/src/app/tabs/dashboard.component.ts @@ -8,6 +8,7 @@ import { import { ToasterService } from 'angular2-toaster'; +import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { StateService } from 'jslib-common/abstractions/state.service'; @@ -19,8 +20,6 @@ import { SimResult } from '../../models/simResult'; import { UserEntry } from '../../models/userEntry'; import { ConfigurationService } from '../../services/configuration.service'; -import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; - import { ConnectorUtils } from '../../utils'; const BroadcasterSubscriptionId = 'DashboardComponent'; diff --git a/src/app/tabs/more.component.ts b/src/app/tabs/more.component.ts index ab7dbadf..8206aa25 100644 --- a/src/app/tabs/more.component.ts +++ b/src/app/tabs/more.component.ts @@ -8,8 +8,7 @@ import { import { ToasterService } from 'angular2-toaster'; -import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; - +import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; diff --git a/src/bwdc.ts b/src/bwdc.ts index ac9e8f22..bff0f028 100644 --- a/src/bwdc.ts +++ b/src/bwdc.ts @@ -26,6 +26,7 @@ import { CryptoService } from 'jslib-common/services/crypto.service'; import { EnvironmentService } from 'jslib-common/services/environment.service'; import { FileUploadService } from 'jslib-common/services/fileUpload.service'; import { FolderService } from 'jslib-common/services/folder.service'; +import { KeyConnectorService } from 'jslib-common/services/keyConnector.service'; import { NoopMessagingService } from 'jslib-common/services/noopMessaging.service'; import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service'; import { PolicyService } from 'jslib-common/services/policy.service'; @@ -76,6 +77,7 @@ export class Main { passwordGenerationService: PasswordGenerationService; policyService: PolicyService; loginSyncService: LoginSyncService; + keyConnectorService: KeyConnectorService; program: Program; constructor() { @@ -119,9 +121,11 @@ export class Main { this.apiKeyService = new ApiKeyService(this.tokenService, this.storageService); this.userService = new UserService(this.tokenService, this.storageService); this.containerService = new ContainerService(this.cryptoService); + this.keyConnectorService = new KeyConnectorService(this.storageService, this.userService, this.cryptoService, + this.apiService, this.tokenService, this.logService); this.authService = new AuthService(this.cryptoService, this.apiService, this.userService, this.tokenService, this.appIdService, this.i18nService, this.platformUtilsService, this.messagingService, null, - this.logService, this.apiKeyService, this.cryptoFunctionService, false); + this.logService, this.apiKeyService, this.cryptoFunctionService, this.environmentService, this.keyConnectorService); this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService, process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS !== 'true'); this.syncService = new SyncService(this.configurationService, this.logService, this.cryptoFunctionService, @@ -143,8 +147,8 @@ export class Main { this.loginSyncService = new LoginSyncService(this.userService, this.apiService, this.settingsService, this.folderService, this.cipherService, this.cryptoService, this.collectionService, this.storageService, - this.messagingService, this.policyService, this.sendService, this.logService, - async (expired: boolean) => this.messagingService.send('logout', { expired: expired })); + this.messagingService, this.policyService, this.sendService, this.logService, this.tokenService, + this.keyConnectorService, async (expired: boolean) => this.messagingService.send('logout', { expired: expired })); this.program = new Program(this); } diff --git a/src/program.ts b/src/program.ts index b73ea3fa..b578658e 100644 --- a/src/program.ts +++ b/src/program.ts @@ -102,7 +102,7 @@ export class Program extends BaseProgram { const command = new LoginCommand(this.main.authService, this.main.apiService, this.main.i18nService, this.main.environmentService, this.main.passwordGenerationService, this.main.cryptoFunctionService, this.main.platformUtilsService, this.main.userService, this.main.cryptoService, - this.main.policyService, 'connector', this.main.loginSyncService); + this.main.policyService, 'connector', this.main.loginSyncService, this.main.keyConnectorService); if (!Utils.isNullOrWhitespace(clientId)) { process.env.BW_CLIENTID = clientId; diff --git a/src/services/auth.service.ts b/src/services/auth.service.ts index 73246362..43546125 100644 --- a/src/services/auth.service.ts +++ b/src/services/auth.service.ts @@ -3,7 +3,9 @@ import { ApiKeyService } from 'jslib-common/abstractions/apiKey.service'; import { AppIdService } from 'jslib-common/abstractions/appId.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service'; +import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; +import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; @@ -24,9 +26,11 @@ export class AuthService extends AuthServiceBase { tokenService: TokenService, appIdService: AppIdService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, messagingService: MessagingService, vaultTimeoutService: VaultTimeoutService, logService: LogService, private apiKeyService: ApiKeyService, - cryptoFunctionService: CryptoFunctionService, setCryptoKeys = true) { + cryptoFunctionService: CryptoFunctionService, environmentService: EnvironmentService, + keyConnectorService: KeyConnectorService) { super(cryptoService, apiService, userService, tokenService, appIdService, i18nService, platformUtilsService, - messagingService, vaultTimeoutService, logService, cryptoFunctionService, setCryptoKeys); + messagingService, vaultTimeoutService, logService, cryptoFunctionService, environmentService, + keyConnectorService, false); } async logInApiKey(clientId: string, clientSecret: string): Promise {