From 55b301c267896b716788480ccece2e3a59e9fa06 Mon Sep 17 00:00:00 2001 From: Nils Fahldieck Date: Wed, 27 Apr 2022 22:10:11 +0200 Subject: [PATCH 1/2] Widen the sidebar to 600px max (#1503) This implements the suggestion by MrBlack of the community forums in: https://community.bitwarden.com/t/manually-resizable-sidebar-columns-in-bitwarden-desktop-app/31909/3 --- src/scss/vault.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scss/vault.scss b/src/scss/vault.scss index 168a23e9..11623cd2 100644 --- a/src/scss/vault.scss +++ b/src/scss/vault.scss @@ -43,7 +43,7 @@ app-root { order: 1; width: 22%; min-width: 175px; - max-width: 250px; + max-width: 600px; border-right: 1px solid #000000; @include themify($themes) { From b46720644839b246a5c6587f17e3df0f49f54b51 Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Fri, 29 Apr 2022 17:48:44 +1000 Subject: [PATCH 2/2] [EC-156] [BEEEP] Remove factory providers in Angular DI (#1496) * Use tokens * Use initService Co-authored-by: Oscar Hinton --- jslib | 2 +- src/app/accounts/two-factor.component.ts | 7 +- src/app/app.module.ts | 2 +- src/app/services.module.ts | 211 ----------------------- src/app/services/init.service.ts | 81 +++++++++ src/app/services/services.module.ts | 135 +++++++++++++++ src/app/vault/generator.component.ts | 5 +- 7 files changed, 227 insertions(+), 216 deletions(-) delete mode 100644 src/app/services.module.ts create mode 100644 src/app/services/init.service.ts create mode 100644 src/app/services/services.module.ts diff --git a/jslib b/jslib index 6bcadc4f..d7e55465 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 6bcadc4f408db2c150753f53a07d6f8888b6e9ff +Subproject commit d7e554653a7e593f8cdaf7e2fe926eb04fb5d5c5 diff --git a/src/app/accounts/two-factor.component.ts b/src/app/accounts/two-factor.component.ts index db482230..acf8919f 100644 --- a/src/app/accounts/two-factor.component.ts +++ b/src/app/accounts/two-factor.component.ts @@ -4,6 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router"; import { TwoFactorComponent as BaseTwoFactorComponent } from "jslib-angular/components/two-factor.component"; import { ModalService } from "jslib-angular/services/modal.service"; import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; import { AuthService } from "jslib-common/abstractions/auth.service"; import { EnvironmentService } from "jslib-common/abstractions/environment.service"; import { I18nService } from "jslib-common/abstractions/i18n.service"; @@ -38,7 +39,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { stateService: StateService, route: ActivatedRoute, logService: LogService, - twoFactorService: TwoFactorService + twoFactorService: TwoFactorService, + appIdService: AppIdService ) { super( authService, @@ -51,7 +53,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { stateService, route, logService, - twoFactorService + twoFactorService, + appIdService ); super.onSuccessfulLogin = () => { return syncService.fullSync(true); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3cd8197d..29e324cf 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -91,7 +91,7 @@ import { SearchComponent } from "./layout/search/search.component"; import { AddEditComponent as SendAddEditComponent } from "./send/add-edit.component"; import { EffluxDatesComponent as SendEffluxDatesComponent } from "./send/efflux-dates.component"; import { SendComponent } from "./send/send.component"; -import { ServicesModule } from "./services.module"; +import { ServicesModule } from "./services/services.module"; import { AddEditCustomFieldsComponent } from "./vault/add-edit-custom-fields.component"; import { AddEditComponent } from "./vault/add-edit.component"; import { AttachmentsComponent } from "./vault/attachments.component"; diff --git a/src/app/services.module.ts b/src/app/services.module.ts deleted file mode 100644 index 74acaabc..00000000 --- a/src/app/services.module.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { APP_INITIALIZER, NgModule } from "@angular/core"; - -import { JslibServicesModule } from "jslib-angular/services/jslib-services.module"; -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 { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service"; -import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; -import { LogService as LogServiceAbstraction } from "jslib-common/abstractions/log.service"; -import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service"; -import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service"; -import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service"; -import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; -import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; -import { StateMigrationService as StateMigrationServiceAbstraction } from "jslib-common/abstractions/stateMigration.service"; -import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service"; -import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service"; -import { SystemService as SystemServiceAbstraction } from "jslib-common/abstractions/system.service"; -import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service"; -import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service"; -import { ThemeType } from "jslib-common/enums/themeType"; -import { StateFactory } from "jslib-common/factories/stateFactory"; -import { GlobalState } from "jslib-common/models/domain/globalState"; -import { ContainerService } from "jslib-common/services/container.service"; -import { EventService } from "jslib-common/services/event.service"; -import { StateMigrationService } from "jslib-common/services/stateMigration.service"; -import { SystemService } from "jslib-common/services/system.service"; -import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; -import { ElectronCryptoService } from "jslib-electron/services/electronCrypto.service"; -import { ElectronLogService } from "jslib-electron/services/electronLog.service"; -import { ElectronPlatformUtilsService } from "jslib-electron/services/electronPlatformUtils.service"; -import { ElectronRendererMessagingService } from "jslib-electron/services/electronRendererMessaging.service"; -import { ElectronRendererSecureStorageService } from "jslib-electron/services/electronRendererSecureStorage.service"; -import { ElectronRendererStorageService } from "jslib-electron/services/electronRendererStorage.service"; - -import { Account } from "../models/account"; -import { I18nService } from "../services/i18n.service"; -import { LoginGuardService } from "../services/loginGuard.service"; -import { NativeMessagingService } from "../services/nativeMessaging.service"; -import { PasswordRepromptService } from "../services/passwordReprompt.service"; -import { StateService } from "../services/state.service"; - -import { SearchBarService } from "./layout/search/search-bar.service"; - -export function initFactory( - window: Window, - environmentService: EnvironmentServiceAbstraction, - syncService: SyncServiceAbstraction, - vaultTimeoutService: VaultTimeoutService, - i18nService: I18nService, - eventService: EventService, - twoFactorService: TwoFactorServiceAbstraction, - notificationsService: NotificationsServiceAbstraction, - platformUtilsService: PlatformUtilsServiceAbstraction, - stateService: StateServiceAbstraction, - cryptoService: CryptoServiceAbstraction, - nativeMessagingService: NativeMessagingService -): () => Promise { - return async () => { - nativeMessagingService.init(); - await stateService.init(); - await environmentService.setUrlsFromStorage(); - syncService.fullSync(true); - await vaultTimeoutService.init(true); - const locale = await stateService.getLocale(); - await i18nService.init(locale); - eventService.init(true); - twoFactorService.init(); - setTimeout(() => notificationsService.init(), 3000); - const htmlEl = window.document.documentElement; - htmlEl.classList.add("os_" + platformUtilsService.getDeviceString()); - htmlEl.classList.add("locale_" + i18nService.translationLocale); - const theme = await platformUtilsService.getEffectiveTheme(); - htmlEl.classList.add("theme_" + theme); - platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => { - const bwTheme = await stateService.getTheme(); - if (bwTheme == null || bwTheme === ThemeType.System) { - htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark); - htmlEl.classList.add("theme_" + sysTheme); - } - }); - - let installAction = null; - const installedVersion = await stateService.getInstalledVersion(); - const currentVersion = await platformUtilsService.getApplicationVersion(); - if (installedVersion == null) { - installAction = "install"; - } else if (installedVersion !== currentVersion) { - installAction = "update"; - } - - if (installAction != null) { - await stateService.setInstalledVersion(currentVersion); - } - - const containerService = new ContainerService(cryptoService); - containerService.attachToGlobal(window); - }; -} - -@NgModule({ - imports: [JslibServicesModule], - declarations: [], - providers: [ - { - provide: APP_INITIALIZER, - useFactory: initFactory, - deps: [ - "WINDOW", - EnvironmentServiceAbstraction, - SyncServiceAbstraction, - VaultTimeoutServiceAbstraction, - I18nServiceAbstraction, - EventServiceAbstraction, - TwoFactorServiceAbstraction, - NotificationsServiceAbstraction, - PlatformUtilsServiceAbstraction, - StateServiceAbstraction, - CryptoServiceAbstraction, - NativeMessagingService, - ], - multi: true, - }, - { provide: LogServiceAbstraction, useClass: ElectronLogService, deps: [] }, - { - provide: PlatformUtilsServiceAbstraction, - useFactory: ( - i18nService: I18nServiceAbstraction, - messagingService: MessagingServiceAbstraction, - stateService: StateServiceAbstraction - ) => new ElectronPlatformUtilsService(i18nService, messagingService, true, stateService), - deps: [I18nServiceAbstraction, MessagingServiceAbstraction, StateServiceAbstraction], - }, - { - 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: CryptoServiceAbstraction, - useClass: ElectronCryptoService, - deps: [ - CryptoFunctionServiceAbstraction, - PlatformUtilsServiceAbstraction, - LogServiceAbstraction, - StateServiceAbstraction, - ], - }, - { - provide: SystemServiceAbstraction, - useFactory: ( - messagingService: MessagingServiceAbstraction, - platformUtilsService: PlatformUtilsServiceAbstraction, - stateService: StateServiceAbstraction - ) => new SystemService(messagingService, platformUtilsService, null, stateService), - deps: [MessagingServiceAbstraction, PlatformUtilsServiceAbstraction, StateServiceAbstraction], - }, - { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, - NativeMessagingService, - SearchBarService, - { - provide: LoginGuardService, - useClass: LoginGuardService, - deps: [StateServiceAbstraction, PlatformUtilsServiceAbstraction, I18nServiceAbstraction], - }, - { - provide: StateServiceAbstraction, - useFactory: ( - storageService: StorageServiceAbstraction, - secureStorageService: StorageServiceAbstraction, - logService: LogServiceAbstraction, - stateMigrationService: StateMigrationServiceAbstraction - ) => - new StateService( - storageService, - secureStorageService, - logService, - stateMigrationService, - new StateFactory(GlobalState, Account) - ), - deps: [ - StorageServiceAbstraction, - "SECURE_STORAGE", - LogServiceAbstraction, - StateMigrationServiceAbstraction, - ], - }, - { - provide: StateMigrationServiceAbstraction, - useFactory: ( - storageService: StorageServiceAbstraction, - secureStorageService: StorageServiceAbstraction - ) => - new StateMigrationService( - storageService, - secureStorageService, - new StateFactory(GlobalState, Account) - ), - deps: [StorageServiceAbstraction, "SECURE_STORAGE"], - }, - ], -}) -export class ServicesModule {} diff --git a/src/app/services/init.service.ts b/src/app/services/init.service.ts new file mode 100644 index 00000000..3bc3d49a --- /dev/null +++ b/src/app/services/init.service.ts @@ -0,0 +1,81 @@ +import { Inject, Injectable } from "@angular/core"; + +import { WINDOW } from "jslib-angular/services/jslib-services.module"; +import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService as EnvironmentServiceAbstraction } from "jslib-common/abstractions/environment.service"; +import { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service"; +import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; +import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service"; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; +import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service"; +import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service"; +import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service"; +import { ThemeType } from "jslib-common/enums/themeType"; +import { ContainerService } from "jslib-common/services/container.service"; +import { EventService } from "jslib-common/services/event.service"; +import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; + +import { I18nService } from "../../services/i18n.service"; +import { NativeMessagingService } from "../../services/nativeMessaging.service"; + +@Injectable() +export class InitService { + constructor( + @Inject(WINDOW) private win: Window, + private environmentService: EnvironmentServiceAbstraction, + private syncService: SyncServiceAbstraction, + private vaultTimeoutService: VaultTimeoutServiceAbstraction, + private i18nService: I18nServiceAbstraction, + private eventService: EventServiceAbstraction, + private twoFactorService: TwoFactorServiceAbstraction, + private notificationsService: NotificationsServiceAbstraction, + private platformUtilsService: PlatformUtilsServiceAbstraction, + private stateService: StateServiceAbstraction, + private cryptoService: CryptoServiceAbstraction, + private nativeMessagingService: NativeMessagingService + ) {} + + init() { + return async () => { + this.nativeMessagingService.init(); + await this.stateService.init(); + await this.environmentService.setUrlsFromStorage(); + this.syncService.fullSync(true); + (this.vaultTimeoutService as VaultTimeoutService).init(true); + const locale = await this.stateService.getLocale(); + await (this.i18nService as I18nService).init(locale); + (this.eventService as EventService).init(true); + this.twoFactorService.init(); + setTimeout(() => this.notificationsService.init(), 3000); + const htmlEl = this.win.document.documentElement; + htmlEl.classList.add("os_" + this.platformUtilsService.getDeviceString()); + + const theme = await this.platformUtilsService.getEffectiveTheme(); + htmlEl.classList.add("theme_" + theme); + this.platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => { + const bwTheme = await this.stateService.getTheme(); + if (bwTheme == null || bwTheme === ThemeType.System) { + htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark); + htmlEl.classList.add("theme_" + sysTheme); + } + }); + + let installAction = null; + const installedVersion = await this.stateService.getInstalledVersion(); + const currentVersion = await this.platformUtilsService.getApplicationVersion(); + if (installedVersion == null) { + installAction = "install"; + } else if (installedVersion !== currentVersion) { + installAction = "update"; + } + + if (installAction != null) { + await this.stateService.setInstalledVersion(currentVersion); + } + + const containerService = new ContainerService(this.cryptoService); + containerService.attachToGlobal(this.win); + }; + } +} diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts new file mode 100644 index 00000000..694cc6de --- /dev/null +++ b/src/app/services/services.module.ts @@ -0,0 +1,135 @@ +import { APP_INITIALIZER, InjectionToken, NgModule } from "@angular/core"; + +import { + JslibServicesModule, + SECURE_STORAGE, + STATE_FACTORY, + STATE_SERVICE_USE_CACHE, + WINDOW, + CLIENT_TYPE, + LOCALES_DIRECTORY, + SYSTEM_LANGUAGE, +} from "jslib-angular/services/jslib-services.module"; +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 { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; +import { + LogService, + LogService as LogServiceAbstraction, +} from "jslib-common/abstractions/log.service"; +import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service"; +import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; +import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { StateMigrationService as StateMigrationServiceAbstraction } from "jslib-common/abstractions/stateMigration.service"; +import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service"; +import { SystemService as SystemServiceAbstraction } from "jslib-common/abstractions/system.service"; +import { ClientType } from "jslib-common/enums/clientType"; +import { StateFactory } from "jslib-common/factories/stateFactory"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { SystemService } from "jslib-common/services/system.service"; +import { ElectronCryptoService } from "jslib-electron/services/electronCrypto.service"; +import { ElectronLogService } from "jslib-electron/services/electronLog.service"; +import { ElectronPlatformUtilsService } from "jslib-electron/services/electronPlatformUtils.service"; +import { ElectronRendererMessagingService } from "jslib-electron/services/electronRendererMessaging.service"; +import { ElectronRendererSecureStorageService } from "jslib-electron/services/electronRendererSecureStorage.service"; +import { ElectronRendererStorageService } from "jslib-electron/services/electronRendererStorage.service"; + +import { Account } from "../../models/account"; +import { I18nService } from "../../services/i18n.service"; +import { LoginGuardService } from "../../services/loginGuard.service"; +import { NativeMessagingService } from "../../services/nativeMessaging.service"; +import { PasswordRepromptService } from "../../services/passwordReprompt.service"; +import { StateService } from "../../services/state.service"; +import { SearchBarService } from "../layout/search/search-bar.service"; + +import { InitService } from "./init.service"; + +const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK"); + +@NgModule({ + imports: [JslibServicesModule], + declarations: [], + providers: [ + InitService, + NativeMessagingService, + SearchBarService, + LoginGuardService, + { + provide: APP_INITIALIZER, + useFactory: (initService: InitService) => initService.init(), + deps: [InitService], + multi: true, + }, + { + provide: STATE_FACTORY, + useValue: new StateFactory(GlobalState, Account), + }, + { + provide: CLIENT_TYPE, + useValue: ClientType.Desktop, + }, + { + provide: RELOAD_CALLBACK, + useValue: null, + }, + { provide: LogServiceAbstraction, useClass: ElectronLogService, deps: [] }, + { + provide: PlatformUtilsServiceAbstraction, + useClass: ElectronPlatformUtilsService, + deps: [ + I18nServiceAbstraction, + MessagingServiceAbstraction, + CLIENT_TYPE, + StateServiceAbstraction, + ], + }, + { + provide: I18nServiceAbstraction, + useClass: I18nService, + deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY], + }, + { + provide: MessagingServiceAbstraction, + useClass: ElectronRendererMessagingService, + deps: [BroadcasterServiceAbstraction], + }, + { provide: StorageServiceAbstraction, useClass: ElectronRendererStorageService }, + { provide: SECURE_STORAGE, useClass: ElectronRendererSecureStorageService }, + { + provide: CryptoServiceAbstraction, + useClass: ElectronCryptoService, + deps: [ + CryptoFunctionServiceAbstraction, + PlatformUtilsServiceAbstraction, + LogServiceAbstraction, + StateServiceAbstraction, + ], + }, + { + provide: SystemServiceAbstraction, + useClass: SystemService, + deps: [ + MessagingServiceAbstraction, + PlatformUtilsServiceAbstraction, + RELOAD_CALLBACK, + StateServiceAbstraction, + ], + }, + { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, + { + provide: StateServiceAbstraction, + useClass: StateService, + deps: [ + StorageServiceAbstraction, + SECURE_STORAGE, + LogService, + StateMigrationServiceAbstraction, + STATE_FACTORY, + STATE_SERVICE_USE_CACHE, + ], + }, + ], +}) +export class ServicesModule {} diff --git a/src/app/vault/generator.component.ts b/src/app/vault/generator.component.ts index 553f53b2..471fd971 100644 --- a/src/app/vault/generator.component.ts +++ b/src/app/vault/generator.component.ts @@ -3,6 +3,7 @@ import { ActivatedRoute } from "@angular/router"; import { GeneratorComponent as BaseGeneratorComponent } from "jslib-angular/components/generator.component"; import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; import { StateService } from "jslib-common/abstractions/state.service"; @@ -19,7 +20,8 @@ export class GeneratorComponent extends BaseGeneratorComponent { stateService: StateService, platformUtilsService: PlatformUtilsService, i18nService: I18nService, - route: ActivatedRoute + route: ActivatedRoute, + logService: LogService ) { super( passwordGenerationService, @@ -27,6 +29,7 @@ export class GeneratorComponent extends BaseGeneratorComponent { platformUtilsService, stateService, i18nService, + logService, route, window );