1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-25 12:15:18 +01:00

[AC-2329] [BEEEP] Use safeProvider in desktop services module (#8457)

This commit is contained in:
Thomas Rittson 2024-03-28 08:44:08 +10:00 committed by GitHub
parent b3b344866e
commit d10c14791d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 198 additions and 147 deletions

View File

@ -1,8 +1,8 @@
import { APP_INITIALIZER, InjectionToken, NgModule } from "@angular/core"; import { APP_INITIALIZER, NgModule } from "@angular/core";
import { SafeProvider, safeProvider } from "@bitwarden/angular/platform/utils/safe-provider";
import { import {
SECURE_STORAGE, SECURE_STORAGE,
STATE_FACTORY,
STATE_SERVICE_USE_CACHE, STATE_SERVICE_USE_CACHE,
LOCALES_DIRECTORY, LOCALES_DIRECTORY,
SYSTEM_LANGUAGE, SYSTEM_LANGUAGE,
@ -12,6 +12,8 @@ import {
WINDOW, WINDOW,
SUPPORTS_SECURE_STORAGE, SUPPORTS_SECURE_STORAGE,
SYSTEM_THEME_OBSERVABLE, SYSTEM_THEME_OBSERVABLE,
SafeInjectionToken,
STATE_FACTORY,
} from "@bitwarden/angular/services/injection-tokens"; } from "@bitwarden/angular/services/injection-tokens";
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module"; import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service"; import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
@ -77,60 +79,87 @@ import { DesktopFileDownloadService } from "./desktop-file-download.service";
import { InitService } from "./init.service"; import { InitService } from "./init.service";
import { RendererCryptoFunctionService } from "./renderer-crypto-function.service"; import { RendererCryptoFunctionService } from "./renderer-crypto-function.service";
const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK"); const RELOAD_CALLBACK = new SafeInjectionToken<() => any>("RELOAD_CALLBACK");
@NgModule({ // Desktop has its own Account definition which must be used in its StateService
imports: [JslibServicesModule], const DESKTOP_STATE_FACTORY = new SafeInjectionToken<StateFactory<GlobalState, Account>>(
declarations: [], "DESKTOP_STATE_FACTORY",
providers: [ );
InitService,
NativeMessagingService, /**
SearchBarService, * Provider definitions used in the ngModule.
LoginGuard, * Add your provider definition here using the safeProvider function as a wrapper. This will give you type safety.
DialogService, * If you need help please ask for it, do NOT change the type of this array.
{ */
provide: APP_INITIALIZER, const safeProviders: SafeProvider[] = [
safeProvider(InitService),
safeProvider(NativeMessagingService),
safeProvider(SearchBarService),
safeProvider(LoginGuard),
safeProvider(DialogService),
safeProvider({
provide: APP_INITIALIZER as SafeInjectionToken<() => void>,
useFactory: (initService: InitService) => initService.init(), useFactory: (initService: InitService) => initService.init(),
deps: [InitService], deps: [InitService],
multi: true, multi: true,
}, }),
{ safeProvider({
provide: STATE_FACTORY, provide: DESKTOP_STATE_FACTORY,
useValue: new StateFactory(GlobalState, Account), useValue: new StateFactory(GlobalState, Account),
}, }),
{ safeProvider({
provide: STATE_FACTORY,
useValue: null,
}),
safeProvider({
provide: RELOAD_CALLBACK, provide: RELOAD_CALLBACK,
useValue: null, useValue: null,
}, }),
{ provide: LogServiceAbstraction, useClass: ElectronLogRendererService, deps: [] }, safeProvider({
{ provide: LogServiceAbstraction,
useClass: ElectronLogRendererService,
deps: [],
}),
safeProvider({
provide: PlatformUtilsServiceAbstraction, provide: PlatformUtilsServiceAbstraction,
useClass: ElectronPlatformUtilsService, useClass: ElectronPlatformUtilsService,
deps: [I18nServiceAbstraction, MessagingServiceAbstraction], deps: [I18nServiceAbstraction, MessagingServiceAbstraction],
}, }),
{ safeProvider({
// We manually override the value of SUPPORTS_SECURE_STORAGE here to avoid // We manually override the value of SUPPORTS_SECURE_STORAGE here to avoid
// the TokenService having to inject the PlatformUtilsService which introduces a // the TokenService having to inject the PlatformUtilsService which introduces a
// circular dependency on Desktop only. // circular dependency on Desktop only.
provide: SUPPORTS_SECURE_STORAGE, provide: SUPPORTS_SECURE_STORAGE,
useValue: ELECTRON_SUPPORTS_SECURE_STORAGE, useValue: ELECTRON_SUPPORTS_SECURE_STORAGE,
}, }),
{ safeProvider({
provide: I18nServiceAbstraction, provide: I18nServiceAbstraction,
useClass: I18nRendererService, useClass: I18nRendererService,
deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY, GlobalStateProvider], deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY, GlobalStateProvider],
}, }),
{ safeProvider({
provide: MessagingServiceAbstraction, provide: MessagingServiceAbstraction,
useClass: ElectronRendererMessagingService, useClass: ElectronRendererMessagingService,
deps: [BroadcasterServiceAbstraction], deps: [BroadcasterServiceAbstraction],
}, }),
{ provide: AbstractStorageService, useClass: ElectronRendererStorageService }, safeProvider({
{ provide: SECURE_STORAGE, useClass: ElectronRendererSecureStorageService }, provide: AbstractStorageService,
{ provide: MEMORY_STORAGE, useClass: MemoryStorageService }, useClass: ElectronRendererStorageService,
{ provide: OBSERVABLE_MEMORY_STORAGE, useClass: MemoryStorageServiceForStateProviders }, deps: [],
{ provide: OBSERVABLE_DISK_STORAGE, useExisting: AbstractStorageService }, }),
{ safeProvider({
provide: SECURE_STORAGE,
useClass: ElectronRendererSecureStorageService,
deps: [],
}),
safeProvider({ provide: MEMORY_STORAGE, useClass: MemoryStorageService, deps: [] }),
safeProvider({
provide: OBSERVABLE_MEMORY_STORAGE,
useClass: MemoryStorageServiceForStateProviders,
deps: [],
}),
safeProvider({ provide: OBSERVABLE_DISK_STORAGE, useExisting: AbstractStorageService }),
safeProvider({
provide: SystemServiceAbstraction, provide: SystemServiceAbstraction,
useClass: SystemService, useClass: SystemService,
deps: [ deps: [
@ -142,8 +171,8 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
VaultTimeoutSettingsService, VaultTimeoutSettingsService,
BiometricStateService, BiometricStateService,
], ],
}, }),
{ safeProvider({
provide: StateServiceAbstraction, provide: StateServiceAbstraction,
useClass: ElectronStateService, useClass: ElectronStateService,
deps: [ deps: [
@ -151,23 +180,25 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
SECURE_STORAGE, SECURE_STORAGE,
MEMORY_STORAGE, MEMORY_STORAGE,
LogService, LogService,
STATE_FACTORY, DESKTOP_STATE_FACTORY,
AccountServiceAbstraction, AccountServiceAbstraction,
EnvironmentService, EnvironmentService,
TokenService, TokenService,
MigrationRunner, MigrationRunner,
STATE_SERVICE_USE_CACHE, STATE_SERVICE_USE_CACHE,
], ],
}, }),
{ safeProvider({
provide: FileDownloadService, provide: FileDownloadService,
useClass: DesktopFileDownloadService, useClass: DesktopFileDownloadService,
}, deps: [],
{ }),
safeProvider({
provide: SYSTEM_THEME_OBSERVABLE, provide: SYSTEM_THEME_OBSERVABLE,
useFactory: () => fromIpcSystemTheme(), useFactory: () => fromIpcSystemTheme(),
}, deps: [],
{ }),
safeProvider({
provide: EncryptedMessageHandlerService, provide: EncryptedMessageHandlerService,
deps: [ deps: [
StateServiceAbstraction, StateServiceAbstraction,
@ -177,8 +208,8 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
MessagingServiceAbstraction, MessagingServiceAbstraction,
PasswordGenerationServiceAbstraction, PasswordGenerationServiceAbstraction,
], ],
}, }),
{ safeProvider({
provide: NativeMessageHandlerService, provide: NativeMessageHandlerService,
deps: [ deps: [
StateServiceAbstraction, StateServiceAbstraction,
@ -187,19 +218,20 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
MessagingServiceAbstraction, MessagingServiceAbstraction,
EncryptedMessageHandlerService, EncryptedMessageHandlerService,
DialogService, DialogService,
DesktopAutofillSettingsService,
], ],
}, }),
{ safeProvider({
provide: LoginServiceAbstraction, provide: LoginServiceAbstraction,
useClass: LoginService, useClass: LoginService,
deps: [StateServiceAbstraction], deps: [StateServiceAbstraction],
}, }),
{ safeProvider({
provide: CryptoFunctionServiceAbstraction, provide: CryptoFunctionServiceAbstraction,
useClass: RendererCryptoFunctionService, useClass: RendererCryptoFunctionService,
deps: [WINDOW], deps: [WINDOW],
}, }),
{ safeProvider({
provide: CryptoServiceAbstraction, provide: CryptoServiceAbstraction,
useClass: ElectronCryptoService, useClass: ElectronCryptoService,
deps: [ deps: [
@ -213,17 +245,21 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
StateProvider, StateProvider,
BiometricStateService, BiometricStateService,
], ],
}, }),
{ safeProvider({
provide: DesktopSettingsService, provide: DesktopSettingsService,
useClass: DesktopSettingsService,
deps: [StateProvider], deps: [StateProvider],
}, }),
{ safeProvider({
provide: DesktopAutofillSettingsService, provide: DesktopAutofillSettingsService,
useClass: DesktopAutofillSettingsService,
deps: [StateProvider], deps: [StateProvider],
}, }),
], ];
@NgModule({
imports: [JslibServicesModule],
declarations: [],
// Do not register your dependency here! Add it to the typesafeProviders array using the helper function
providers: safeProviders,
}) })
export class ServicesModule {} export class ServicesModule {}

View File

@ -5,10 +5,10 @@ import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string"; import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { StateService } from "@bitwarden/common/platform/services/state.service";
import { DialogService } from "@bitwarden/components"; import { DialogService } from "@bitwarden/components";
import { VerifyNativeMessagingDialogComponent } from "../app/components/verify-native-messaging-dialog.component"; import { VerifyNativeMessagingDialogComponent } from "../app/components/verify-native-messaging-dialog.component";

View File

@ -74,6 +74,17 @@ type SafeExistingProvider<
useExisting: I; useExisting: I;
}; };
/**
* Represents a dependency where there is no abstract token, the token is the implementation
*/
type SafeConcreteProvider<
I extends Constructor<any>,
D extends MapParametersToDeps<ConstructorParameters<I>>,
> = {
provide: I;
deps: D;
};
/** /**
* A factory function that creates a provider for the ngModule providers array. * A factory function that creates a provider for the ngModule providers array.
* This guarantees type safety for your provider definition. It does nothing at runtime. * This guarantees type safety for your provider definition. It does nothing at runtime.
@ -97,11 +108,15 @@ export const safeProvider = <
IExisting extends IExisting extends
| Constructor<ProviderInstanceType<AExisting>> | Constructor<ProviderInstanceType<AExisting>>
| AbstractConstructor<ProviderInstanceType<AExisting>>, | AbstractConstructor<ProviderInstanceType<AExisting>>,
// types for no token
IConcrete extends Constructor<any>,
DConcrete extends MapParametersToDeps<ConstructorParameters<IConcrete>>,
>( >(
provider: provider:
| SafeClassProvider<AClass, IClass, DClass> | SafeClassProvider<AClass, IClass, DClass>
| SafeValueProvider<AValue, VValue> | SafeValueProvider<AValue, VValue>
| SafeFactoryProvider<AFactory, IFactory, DFactory> | SafeFactoryProvider<AFactory, IFactory, DFactory>
| SafeExistingProvider<AExisting, IExisting> | SafeExistingProvider<AExisting, IExisting>
| SafeConcreteProvider<IConcrete, DConcrete>
| Constructor<unknown>, | Constructor<unknown>,
): SafeProvider => provider as SafeProvider; ): SafeProvider => provider as SafeProvider;