[EC-154] [BEEEP] Remove factory providers in Angular DI (#1609)

* use InjectionTokens

* Use InitService
This commit is contained in:
Thomas Rittson 2022-04-29 17:45:47 +10:00 committed by GitHub
parent f586359610
commit 2b03162bfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 115 additions and 128 deletions

2
jslib

@ -1 +1 @@
Subproject commit f6e3481fe96690a3c52f7701d92b4e57f69f976a
Subproject commit d7e554653a7e593f8cdaf7e2fe926eb04fb5d5c5

View File

@ -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";
@ -37,7 +38,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
route: ActivatedRoute,
logService: LogService,
twoFactorService: TwoFactorService,
private routerService: RouterService
private routerService: RouterService,
appIdService: AppIdService
) {
super(
authService,
@ -50,7 +52,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
stateService,
route,
logService,
twoFactorService
twoFactorService,
appIdService
);
this.onSuccessfulLoginNavigate = this.goAfterLogIn;
}

View File

@ -0,0 +1,69 @@
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,
Urls,
} from "jslib-common/abstractions/environment.service";
import { EventService as EventLoggingServiceAbstraction } 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 { 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 as EventLoggingService } from "jslib-common/services/event.service";
import { VaultTimeoutService as VaultTimeoutService } from "jslib-common/services/vaultTimeout.service";
import { I18nService as I18nService } from "../../services/i18n.service";
@Injectable()
export class InitService {
constructor(
@Inject(WINDOW) private win: Window,
private environmentService: EnvironmentServiceAbstraction,
private notificationsService: NotificationsServiceAbstraction,
private vaultTimeoutService: VaultTimeoutServiceAbstraction,
private i18nService: I18nServiceAbstraction,
private eventLoggingService: EventLoggingServiceAbstraction,
private twoFactorService: TwoFactorServiceAbstraction,
private stateService: StateServiceAbstraction,
private platformUtilsService: PlatformUtilsServiceAbstraction,
private cryptoService: CryptoServiceAbstraction
) {}
init() {
return async () => {
await this.stateService.init();
const urls = process.env.URLS as Urls;
urls.base ??= this.win.location.origin;
this.environmentService.setUrls(urls);
setTimeout(() => this.notificationsService.init(), 3000);
(this.vaultTimeoutService as VaultTimeoutService).init(true);
const locale = await this.stateService.getLocale();
await (this.i18nService as I18nService).init(locale);
(this.eventLoggingService as EventLoggingService).init(true);
this.twoFactorService.init();
const htmlEl = this.win.document.documentElement;
htmlEl.classList.add("locale_" + this.i18nService.translationLocale);
// Initial theme is set in index.html which must be updated if there are any changes to theming logic
this.platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => {
const bwTheme = await this.stateService.getTheme();
if (bwTheme === ThemeType.System) {
htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark);
htmlEl.classList.add("theme_" + sysTheme);
}
});
const containerService = new ContainerService(this.cryptoService);
containerService.attachToWindow(this.win);
};
}
}

View File

@ -1,38 +1,32 @@
import { APP_INITIALIZER, NgModule } from "@angular/core";
import { ToastrModule } from "ngx-toastr";
import { JslibServicesModule } from "jslib-angular/services/jslib-services.module";
import {
JslibServicesModule,
WINDOW,
SECURE_STORAGE,
STATE_FACTORY,
STATE_SERVICE_USE_CACHE,
LOCALES_DIRECTORY,
SYSTEM_LANGUAGE,
} from "jslib-angular/services/jslib-services.module";
import { ModalService as ModalServiceAbstraction } from "jslib-angular/services/modal.service";
import { ApiService as ApiServiceAbstraction } from "jslib-common/abstractions/api.service";
import { CipherService as CipherServiceAbstraction } from "jslib-common/abstractions/cipher.service";
import { CollectionService as CollectionServiceAbstraction } from "jslib-common/abstractions/collection.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,
Urls,
} from "jslib-common/abstractions/environment.service";
import { EventService as EventLoggingServiceAbstraction } from "jslib-common/abstractions/event.service";
import { FolderService as FolderServiceAbstraction } from "jslib-common/abstractions/folder.service";
import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service";
import { ImportService as ImportServiceAbstraction } from "jslib-common/abstractions/import.service";
import { LogService } 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 BaseStateServiceAbstraction } 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 { 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 { ContainerService } from "jslib-common/services/container.service";
import { CryptoService } from "jslib-common/services/crypto.service";
import { EventService as EventLoggingService } from "jslib-common/services/event.service";
import { ImportService } from "jslib-common/services/import.service";
import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service";
import { StateService as StateServiceAbstraction } from "../../abstractions/state.service";
import { Account } from "../../models/account";
@ -48,107 +42,52 @@ import { WebPlatformUtilsService } from "../../services/webPlatformUtils.service
import { HomeGuard } from "../guards/home.guard";
import { EventService } from "./event.service";
import { InitService } from "./init.service";
import { ModalService } from "./modal.service";
import { OrganizationGuardService } from "./organization-guard.service";
import { OrganizationTypeGuardService } from "./organization-type-guard.service";
import { PolicyListService } from "./policy-list.service";
import { RouterService } from "./router.service";
export function initFactory(
window: Window,
environmentService: EnvironmentServiceAbstraction,
notificationsService: NotificationsServiceAbstraction,
vaultTimeoutService: VaultTimeoutService,
i18nService: I18nService,
eventLoggingService: EventLoggingService,
twoFactorService: TwoFactorServiceAbstraction,
stateService: StateServiceAbstraction,
platformUtilsService: PlatformUtilsServiceAbstraction,
cryptoService: CryptoServiceAbstraction
): () => void {
return async () => {
await stateService.init();
const urls = process.env.URLS as Urls;
urls.base ??= window.location.origin;
environmentService.setUrls(urls);
setTimeout(() => notificationsService.init(), 3000);
vaultTimeoutService.init(true);
const locale = await stateService.getLocale();
await i18nService.init(locale);
eventLoggingService.init(true);
twoFactorService.init();
const htmlEl = window.document.documentElement;
htmlEl.classList.add("locale_" + i18nService.translationLocale);
// Initial theme is set in index.html which must be updated if there are any changes to theming logic
platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => {
const bwTheme = await stateService.getTheme();
if (bwTheme === ThemeType.System) {
htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark);
htmlEl.classList.add("theme_" + sysTheme);
}
});
const containerService = new ContainerService(cryptoService);
containerService.attachToWindow(window);
};
}
@NgModule({
imports: [ToastrModule, JslibServicesModule],
declarations: [],
providers: [
{
provide: APP_INITIALIZER,
useFactory: initFactory,
deps: [
"WINDOW",
EnvironmentServiceAbstraction,
NotificationsServiceAbstraction,
VaultTimeoutServiceAbstraction,
I18nServiceAbstraction,
EventLoggingServiceAbstraction,
TwoFactorServiceAbstraction,
StateServiceAbstraction,
PlatformUtilsServiceAbstraction,
CryptoServiceAbstraction,
],
multi: true,
},
InitService,
OrganizationGuardService,
OrganizationTypeGuardService,
RouterService,
EventService,
PolicyListService,
{
provide: APP_INITIALIZER,
useFactory: (initService: InitService) => initService.init(),
deps: [InitService],
multi: true,
},
{
provide: STATE_FACTORY,
useValue: new StateFactory(GlobalState, Account),
},
{
provide: STATE_SERVICE_USE_CACHE,
useValue: false,
},
{
provide: I18nServiceAbstraction,
useFactory: (window: Window) => new I18nService(window.navigator.language, "locales"),
deps: ["WINDOW"],
useClass: I18nService,
deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY],
},
{ provide: StorageServiceAbstraction, useClass: HtmlStorageService },
{
provide: "SECURE_STORAGE",
provide: SECURE_STORAGE,
// TODO: platformUtilsService.isDev has a helper for this, but using that service here results in a circular dependency.
// We have a tech debt item in the backlog to break up platformUtilsService, but in the meantime simply checking the environement here is less cumbersome.
useClass: process.env.NODE_ENV === "development" ? HtmlStorageService : MemoryStorageService,
},
{
provide: PlatformUtilsServiceAbstraction,
useFactory: (
i18nService: I18nServiceAbstraction,
messagingService: MessagingServiceAbstraction,
logService: LogService,
stateService: StateServiceAbstraction
) => new WebPlatformUtilsService(i18nService, messagingService, logService, stateService),
deps: [
I18nServiceAbstraction,
MessagingServiceAbstraction,
LogService,
StateServiceAbstraction,
],
useClass: WebPlatformUtilsService,
},
{ provide: MessagingServiceAbstraction, useClass: BroadcasterMessagingService },
{ provide: ModalServiceAbstraction, useClass: ModalService },
@ -165,50 +104,21 @@ export function initFactory(
CryptoServiceAbstraction,
],
},
{
provide: CryptoServiceAbstraction,
useClass: CryptoService,
deps: [
CryptoFunctionServiceAbstraction,
PlatformUtilsServiceAbstraction,
LogService,
StateServiceAbstraction,
],
},
{
provide: StateMigrationServiceAbstraction,
useFactory: (
storageService: StorageServiceAbstraction,
secureStorageService: StorageServiceAbstraction
) =>
new StateMigrationService(
storageService,
secureStorageService,
new StateFactory(GlobalState, Account)
),
deps: [StorageServiceAbstraction, "SECURE_STORAGE"],
useClass: StateMigrationService,
deps: [StorageServiceAbstraction, SECURE_STORAGE, STATE_FACTORY],
},
{
provide: StateServiceAbstraction,
useFactory: (
storageService: StorageServiceAbstraction,
secureStorageService: StorageServiceAbstraction,
logService: LogService,
stateMigrationService: StateMigrationServiceAbstraction
) =>
new StateService(
storageService,
secureStorageService,
logService,
stateMigrationService,
new StateFactory(GlobalState, Account),
false
),
useClass: StateService,
deps: [
StorageServiceAbstraction,
"SECURE_STORAGE",
SECURE_STORAGE,
LogService,
StateMigrationServiceAbstraction,
STATE_FACTORY,
STATE_SERVICE_USE_CACHE,
],
},
{

View File

@ -4,6 +4,7 @@ import { ActivatedRoute } from "@angular/router";
import { GeneratorComponent as BaseGeneratorComponent } from "jslib-angular/components/generator.component";
import { ModalService } from "jslib-angular/services/modal.service";
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";
@ -26,6 +27,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
platformUtilsService: PlatformUtilsService,
i18nService: I18nService,
route: ActivatedRoute,
logService: LogService,
private modalService: ModalService
) {
super(
@ -34,6 +36,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
platformUtilsService,
stateService,
i18nService,
logService,
route,
window
);

View File

@ -1,3 +1,4 @@
import { Injectable } from "@angular/core";
import Swal, { SweetAlertIcon } from "sweetalert2";
import { I18nService } from "jslib-common/abstractions/i18n.service";
@ -9,6 +10,7 @@ import { ClientType } from "jslib-common/enums/clientType";
import { DeviceType } from "jslib-common/enums/deviceType";
import { ThemeType } from "jslib-common/enums/themeType";
@Injectable()
export class WebPlatformUtilsService implements PlatformUtilsService {
private browserCache: DeviceType = null;
private prefersColorSchemeDark = window.matchMedia("(prefers-color-scheme: dark)");