Ps/pm 5965/better config polling (#8325)

* Create tracker that can await until expected observables are received.

* Test dates are almost equal

* Remove unused class method

* Allow for updating active account in accout service fake

* Correct observable tracker behavior

Clarify documentation

* Transition config service to state provider

Updates the config fetching behavior to be lazy and ensure that any emitted value has been updated if older than a configurable value (statically compiled).

If desired, config fetching can be ensured fresh through an async.

* Update calls to config service in DI and bootstrapping

* Migrate account server configs

* Fix global config fetching

* Test migration rollback

* Adhere to implementation naming convention

* Adhere to abstract class naming convention

* Complete config abstraction rename

* Remove unnecessary cli config service

* Fix builds

* Validate observable does not complete

* Use token service to determine authed or unauthed config pull

* Remove superfluous factory config

* Name describe blocks after the thing they test

* Remove implementation documentation

Unfortunately the experience when linking to external documentation is quite poor. Instead of following the link and retrieving docs, you get a link that can be clicked to take you out of context to the docs. No link _does_ retrieve docs, but lacks indication in the implementation that documentation exists at all.

On the balance, removing the link is the better experience.

* Fix storybook
This commit is contained in:
Matt Gibson 2024-03-27 12:03:09 -05:00 committed by GitHub
parent 64d6f6fef3
commit 62ad39e697
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
79 changed files with 946 additions and 609 deletions

View File

@ -12,7 +12,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@ -44,7 +44,7 @@ export class SsoComponent extends BaseSsoComponent {
environmentService: EnvironmentService, environmentService: EnvironmentService,
logService: LogService, logService: LogService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
configService: ConfigServiceAbstraction, configService: ConfigService,
protected authService: AuthService, protected authService: AuthService,
@Inject(WINDOW) private win: Window, @Inject(WINDOW) private win: Window,
) { ) {

View File

@ -16,7 +16,7 @@ import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -59,7 +59,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
appIdService: AppIdService, appIdService: AppIdService,
loginService: LoginService, loginService: LoginService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
configService: ConfigServiceAbstraction, configService: ConfigService,
ssoLoginService: SsoLoginServiceAbstraction, ssoLoginService: SsoLoginServiceAbstraction,
private dialogService: DialogService, private dialogService: DialogService,
@Inject(WINDOW) protected win: Window, @Inject(WINDOW) protected win: Window,

View File

@ -70,6 +70,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service"; import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service";
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
@ -93,6 +94,7 @@ import { StateFactory } from "@bitwarden/common/platform/factories/state-factory
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
import { AppIdService } from "@bitwarden/common/platform/services/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/services/app-id.service";
import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service";
import { DefaultConfigService } from "@bitwarden/common/platform/services/config/default-config.service";
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service"; import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
import { ContainerService } from "@bitwarden/common/platform/services/container.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service";
import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation"; import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation";
@ -201,7 +203,6 @@ import { BrowserApi } from "../platform/browser/browser-api";
import { flagEnabled } from "../platform/flags"; import { flagEnabled } from "../platform/flags";
import { UpdateBadge } from "../platform/listeners/update-badge"; import { UpdateBadge } from "../platform/listeners/update-badge";
import { BrowserStateService as StateServiceAbstraction } from "../platform/services/abstractions/browser-state.service"; import { BrowserStateService as StateServiceAbstraction } from "../platform/services/abstractions/browser-state.service";
import { BrowserConfigService } from "../platform/services/browser-config.service";
import { BrowserCryptoService } from "../platform/services/browser-crypto.service"; import { BrowserCryptoService } from "../platform/services/browser-crypto.service";
import { BrowserEnvironmentService } from "../platform/services/browser-environment.service"; import { BrowserEnvironmentService } from "../platform/services/browser-environment.service";
import BrowserLocalStorageService from "../platform/services/browser-local-storage.service"; import BrowserLocalStorageService from "../platform/services/browser-local-storage.service";
@ -293,7 +294,7 @@ export default class MainBackground {
avatarService: AvatarServiceAbstraction; avatarService: AvatarServiceAbstraction;
mainContextMenuHandler: MainContextMenuHandler; mainContextMenuHandler: MainContextMenuHandler;
cipherContextMenuHandler: CipherContextMenuHandler; cipherContextMenuHandler: CipherContextMenuHandler;
configService: BrowserConfigService; configService: ConfigService;
configApiService: ConfigApiServiceAbstraction; configApiService: ConfigApiServiceAbstraction;
devicesApiService: DevicesApiServiceAbstraction; devicesApiService: DevicesApiServiceAbstraction;
devicesService: DevicesServiceAbstraction; devicesService: DevicesServiceAbstraction;
@ -609,16 +610,13 @@ export default class MainBackground {
this.userVerificationApiService = new UserVerificationApiService(this.apiService); this.userVerificationApiService = new UserVerificationApiService(this.apiService);
this.configApiService = new ConfigApiService(this.apiService, this.authService); this.configApiService = new ConfigApiService(this.apiService, this.tokenService);
this.configService = new BrowserConfigService( this.configService = new DefaultConfigService(
this.stateService,
this.configApiService, this.configApiService,
this.authService,
this.environmentService, this.environmentService,
this.logService, this.logService,
this.stateProvider, this.stateProvider,
true,
); );
this.cipherService = new CipherService( this.cipherService = new CipherService(
@ -1005,7 +1003,6 @@ export default class MainBackground {
this.filelessImporterBackground.init(); this.filelessImporterBackground.init();
await this.commandsBackground.init(); await this.commandsBackground.init();
this.configService.init();
this.twoFactorService.init(); this.twoFactorService.init();
await this.overlayBackground.init(); await this.overlayBackground.init();

View File

@ -3,7 +3,7 @@ import { firstValueFrom } from "rxjs";
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service"; import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
import { AutofillOverlayVisibility } from "@bitwarden/common/autofill/constants"; import { AutofillOverlayVisibility } from "@bitwarden/common/autofill/constants";
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service"; import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -46,7 +46,7 @@ export default class RuntimeBackground {
private environmentService: BrowserEnvironmentService, private environmentService: BrowserEnvironmentService,
private messagingService: MessagingService, private messagingService: MessagingService,
private logService: LogService, private logService: LogService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private fido2Service: Fido2Service, private fido2Service: Fido2Service,
) { ) {
// onInstalled listener must be wired up before anything else, so we do it in the ctor // onInstalled listener must be wired up before anything else, so we do it in the ctor
@ -136,7 +136,7 @@ export default class RuntimeBackground {
await this.main.refreshBadge(); await this.main.refreshBadge();
await this.main.refreshMenu(); await this.main.refreshMenu();
}, 2000); }, 2000);
this.configService.triggerServerConfigFetch(); await this.configService.ensureConfigFetched();
} }
break; break;
case "openPopup": case "openPopup":

View File

@ -2,9 +2,9 @@ import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstract
import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service";
import { import {
authServiceFactory, tokenServiceFactory,
AuthServiceInitOptions, TokenServiceInitOptions,
} from "../../../auth/background/service-factories/auth-service.factory"; } from "../../../auth/background/service-factories/token-service.factory";
import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory"; import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory";
import { FactoryOptions, CachedServices, factory } from "./factory-options"; import { FactoryOptions, CachedServices, factory } from "./factory-options";
@ -13,7 +13,7 @@ type ConfigApiServiceFactoyOptions = FactoryOptions;
export type ConfigApiServiceInitOptions = ConfigApiServiceFactoyOptions & export type ConfigApiServiceInitOptions = ConfigApiServiceFactoyOptions &
ApiServiceInitOptions & ApiServiceInitOptions &
AuthServiceInitOptions; TokenServiceInitOptions;
export function configApiServiceFactory( export function configApiServiceFactory(
cache: { configApiService?: ConfigApiServiceAbstraction } & CachedServices, cache: { configApiService?: ConfigApiServiceAbstraction } & CachedServices,
@ -26,7 +26,7 @@ export function configApiServiceFactory(
async () => async () =>
new ConfigApiService( new ConfigApiService(
await apiServiceFactory(cache, opts), await apiServiceFactory(cache, opts),
await authServiceFactory(cache, opts), await tokenServiceFactory(cache, opts),
), ),
); );
} }

View File

@ -1,10 +1,5 @@
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service"; import { DefaultConfigService } from "@bitwarden/common/platform/services/config/default-config.service";
import {
authServiceFactory,
AuthServiceInitOptions,
} from "../../../auth/background/service-factories/auth-service.factory";
import { configApiServiceFactory, ConfigApiServiceInitOptions } from "./config-api.service.factory"; import { configApiServiceFactory, ConfigApiServiceInitOptions } from "./config-api.service.factory";
import { import {
@ -13,39 +8,30 @@ import {
} from "./environment-service.factory"; } from "./environment-service.factory";
import { FactoryOptions, CachedServices, factory } from "./factory-options"; import { FactoryOptions, CachedServices, factory } from "./factory-options";
import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory"; import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory";
import { stateProviderFactory } from "./state-provider.factory"; import { stateProviderFactory, StateProviderInitOptions } from "./state-provider.factory";
import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory";
type ConfigServiceFactoryOptions = FactoryOptions & { type ConfigServiceFactoryOptions = FactoryOptions;
configServiceOptions?: {
subscribe?: boolean;
};
};
export type ConfigServiceInitOptions = ConfigServiceFactoryOptions & export type ConfigServiceInitOptions = ConfigServiceFactoryOptions &
StateServiceInitOptions &
ConfigApiServiceInitOptions & ConfigApiServiceInitOptions &
AuthServiceInitOptions &
EnvironmentServiceInitOptions & EnvironmentServiceInitOptions &
LogServiceInitOptions; LogServiceInitOptions &
StateProviderInitOptions;
export function configServiceFactory( export function configServiceFactory(
cache: { configService?: ConfigServiceAbstraction } & CachedServices, cache: { configService?: ConfigService } & CachedServices,
opts: ConfigServiceInitOptions, opts: ConfigServiceInitOptions,
): Promise<ConfigServiceAbstraction> { ): Promise<ConfigService> {
return factory( return factory(
cache, cache,
"configService", "configService",
opts, opts,
async () => async () =>
new ConfigService( new DefaultConfigService(
await stateServiceFactory(cache, opts),
await configApiServiceFactory(cache, opts), await configApiServiceFactory(cache, opts),
await authServiceFactory(cache, opts),
await environmentServiceFactory(cache, opts), await environmentServiceFactory(cache, opts),
await logServiceFactory(cache, opts), await logServiceFactory(cache, opts),
await stateProviderFactory(cache, opts), await stateProviderFactory(cache, opts),
opts.configServiceOptions?.subscribe ?? true,
), ),
); );
} }

View File

@ -1,38 +0,0 @@
import { ReplaySubject } from "rxjs";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
import { ServerConfig } from "@bitwarden/common/platform/abstractions/config/server-config";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
import { StateProvider } from "@bitwarden/common/platform/state";
import { browserSession, sessionSync } from "../decorators/session-sync-observable";
@browserSession
export class BrowserConfigService extends ConfigService {
@sessionSync<ServerConfig>({ initializer: ServerConfig.fromJSON })
protected _serverConfig: ReplaySubject<ServerConfig | null>;
constructor(
stateService: StateService,
configApiService: ConfigApiServiceAbstraction,
authService: AuthService,
environmentService: EnvironmentService,
logService: LogService,
stateProvider: StateProvider,
subscribe = false,
) {
super(
stateService,
configApiService,
authService,
environmentService,
logService,
stateProvider,
subscribe,
);
}
}

View File

@ -5,7 +5,6 @@ import { AbstractThemingService } from "@bitwarden/angular/platform/services/the
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService as LogServiceAbstraction } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService as LogServiceAbstraction } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
import { BrowserApi } from "../../platform/browser/browser-api"; import { BrowserApi } from "../../platform/browser/browser-api";
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils"; import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
@ -19,7 +18,6 @@ export class InitService {
private stateService: StateServiceAbstraction, private stateService: StateServiceAbstraction,
private logService: LogServiceAbstraction, private logService: LogServiceAbstraction,
private themingService: AbstractThemingService, private themingService: AbstractThemingService,
private configService: ConfigService,
@Inject(DOCUMENT) private document: Document, @Inject(DOCUMENT) private document: Document,
) {} ) {}
@ -55,7 +53,6 @@ export class InitService {
this.logService.info("Force redraw is on"); this.logService.info("Force redraw is on");
} }
this.configService.init();
this.setupVaultPopupHeartbeat(); this.setupVaultPopupHeartbeat();
}; };
} }

View File

@ -46,17 +46,13 @@ import {
UserNotificationSettingsService, UserNotificationSettingsService,
UserNotificationSettingsServiceAbstraction, UserNotificationSettingsServiceAbstraction,
} from "@bitwarden/common/autofill/services/user-notification-settings.service"; } from "@bitwarden/common/autofill/services/user-notification-settings.service";
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
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 { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
import { import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
LogService,
LogService as LogServiceAbstraction,
} from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService as BaseStateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService as BaseStateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
@ -66,7 +62,6 @@ import {
} from "@bitwarden/common/platform/abstractions/storage.service"; } from "@bitwarden/common/platform/abstractions/storage.service";
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory"; import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service"; import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
import { ContainerService } from "@bitwarden/common/platform/services/container.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner"; import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
@ -95,7 +90,6 @@ import { Account } from "../../models/account";
import { BrowserApi } from "../../platform/browser/browser-api"; import { BrowserApi } from "../../platform/browser/browser-api";
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils"; import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
import { BrowserStateService as StateServiceAbstraction } from "../../platform/services/abstractions/browser-state.service"; import { BrowserStateService as StateServiceAbstraction } from "../../platform/services/abstractions/browser-state.service";
import { BrowserConfigService } from "../../platform/services/browser-config.service";
import { BrowserEnvironmentService } from "../../platform/services/browser-environment.service"; import { BrowserEnvironmentService } from "../../platform/services/browser-environment.service";
import { BrowserFileDownloadService } from "../../platform/services/browser-file-download.service"; import { BrowserFileDownloadService } from "../../platform/services/browser-file-download.service";
import BrowserLocalStorageService from "../../platform/services/browser-local-storage.service"; import BrowserLocalStorageService from "../../platform/services/browser-local-storage.service";
@ -186,7 +180,7 @@ function getBgService<T>(service: keyof MainBackground) {
i18nService, i18nService,
); );
}, },
deps: [LogServiceAbstraction, I18nServiceAbstraction], deps: [LogService, I18nServiceAbstraction],
}, },
{ {
provide: CipherFileUploadService, provide: CipherFileUploadService,
@ -205,7 +199,7 @@ function getBgService<T>(service: keyof MainBackground) {
deps: [], deps: [],
}, },
{ {
provide: LogServiceAbstraction, provide: LogService,
useFactory: (platformUtilsService: PlatformUtilsService) => useFactory: (platformUtilsService: PlatformUtilsService) =>
new ConsoleLogService(platformUtilsService.isDev()), new ConsoleLogService(platformUtilsService.isDev()),
deps: [PlatformUtilsService], deps: [PlatformUtilsService],
@ -367,7 +361,7 @@ function getBgService<T>(service: keyof MainBackground) {
storageService: AbstractStorageService, storageService: AbstractStorageService,
secureStorageService: AbstractStorageService, secureStorageService: AbstractStorageService,
memoryStorageService: AbstractMemoryStorageService, memoryStorageService: AbstractMemoryStorageService,
logService: LogServiceAbstraction, logService: LogService,
accountService: AccountServiceAbstraction, accountService: AccountServiceAbstraction,
environmentService: EnvironmentService, environmentService: EnvironmentService,
tokenService: TokenService, tokenService: TokenService,
@ -389,7 +383,7 @@ function getBgService<T>(service: keyof MainBackground) {
AbstractStorageService, AbstractStorageService,
SECURE_STORAGE, SECURE_STORAGE,
MEMORY_STORAGE, MEMORY_STORAGE,
LogServiceAbstraction, LogService,
AccountServiceAbstraction, AccountServiceAbstraction,
EnvironmentService, EnvironmentService,
TokenService, TokenService,
@ -430,18 +424,6 @@ function getBgService<T>(service: keyof MainBackground) {
}, },
deps: [PlatformUtilsService], deps: [PlatformUtilsService],
}, },
{
provide: ConfigService,
useClass: BrowserConfigService,
deps: [
StateServiceAbstraction,
ConfigApiServiceAbstraction,
AuthServiceAbstraction,
EnvironmentService,
StateProvider,
LogService,
],
},
{ {
provide: FilePopoutUtilsService, provide: FilePopoutUtilsService,
useFactory: (platformUtilsService: PlatformUtilsService) => { useFactory: (platformUtilsService: PlatformUtilsService) => {

View File

@ -3,7 +3,7 @@ import { Component } from "@angular/core";
import { combineLatest, map } from "rxjs"; import { combineLatest, map } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module"; import { JslibModule } from "@bitwarden/angular/jslib.module";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { ButtonModule, DialogModule } from "@bitwarden/components"; import { ButtonModule, DialogModule } from "@bitwarden/components";
@ -24,7 +24,7 @@ export class AboutComponent {
]).pipe(map(([serverConfig, isCloud]) => ({ serverConfig, isCloud }))); ]).pipe(map(([serverConfig, isCloud]) => ({ serverConfig, isCloud })));
constructor( constructor(
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private environmentService: EnvironmentService, private environmentService: EnvironmentService,
) {} ) {}
} }

View File

@ -4,7 +4,7 @@ import { firstValueFrom } from "rxjs";
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service"; import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { AuthService } from "@bitwarden/common/auth/services/auth.service"; import { AuthService } from "@bitwarden/common/auth/services/auth.service";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { Importer, ImportResult, ImportServiceAbstraction } from "@bitwarden/importer/core"; import { Importer, ImportResult, ImportServiceAbstraction } from "@bitwarden/importer/core";

View File

@ -5,7 +5,7 @@ import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { ImportServiceAbstraction } from "@bitwarden/importer/core"; import { ImportServiceAbstraction } from "@bitwarden/importer/core";
@ -55,7 +55,7 @@ class FilelessImporterBackground implements FilelessImporterBackgroundInterface
* @param syncService - Used to trigger a full sync after the import is completed. * @param syncService - Used to trigger a full sync after the import is completed.
*/ */
constructor( constructor(
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private authService: AuthService, private authService: AuthService,
private policyService: PolicyService, private policyService: PolicyService,
private notificationBackground: NotificationBackground, private notificationBackground: NotificationBackground,

View File

@ -11,7 +11,7 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service"; import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -68,7 +68,7 @@ export class AddEditComponent extends BaseAddEditComponent {
sendApiService: SendApiService, sendApiService: SendApiService,
dialogService: DialogService, dialogService: DialogService,
datePipe: DatePipe, datePipe: DatePipe,
configService: ConfigServiceAbstraction, configService: ConfigService,
) { ) {
super( super(
cipherService, cipherService,

View File

@ -47,6 +47,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service"; import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
import { ClientType } from "@bitwarden/common/enums"; import { ClientType } from "@bitwarden/common/enums";
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service"; import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service";
import { import {
@ -60,6 +61,7 @@ import { GlobalState } from "@bitwarden/common/platform/models/domain/global-sta
import { AppIdService } from "@bitwarden/common/platform/services/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/services/app-id.service";
import { BroadcasterService } from "@bitwarden/common/platform/services/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/services/broadcaster.service";
import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service";
import { DefaultConfigService } from "@bitwarden/common/platform/services/config/default-config.service";
import { ContainerService } from "@bitwarden/common/platform/services/container.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service";
import { CryptoService } from "@bitwarden/common/platform/services/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/services/crypto.service";
import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation"; import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation";
@ -131,7 +133,6 @@ import {
VaultExportServiceAbstraction, VaultExportServiceAbstraction,
} from "@bitwarden/vault-export-core"; } from "@bitwarden/vault-export-core";
import { CliConfigService } from "./platform/services/cli-config.service";
import { CliPlatformUtilsService } from "./platform/services/cli-platform-utils.service"; import { CliPlatformUtilsService } from "./platform/services/cli-platform-utils.service";
import { ConsoleLogService } from "./platform/services/console-log.service"; import { ConsoleLogService } from "./platform/services/console-log.service";
import { I18nService } from "./platform/services/i18n.service"; import { I18nService } from "./platform/services/i18n.service";
@ -214,7 +215,7 @@ export class Main {
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction; deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction;
authRequestService: AuthRequestService; authRequestService: AuthRequestService;
configApiService: ConfigApiServiceAbstraction; configApiService: ConfigApiServiceAbstraction;
configService: CliConfigService; configService: ConfigService;
accountService: AccountService; accountService: AccountService;
globalStateProvider: GlobalStateProvider; globalStateProvider: GlobalStateProvider;
singleUserStateProvider: SingleUserStateProvider; singleUserStateProvider: SingleUserStateProvider;
@ -504,16 +505,13 @@ export class Main {
this.stateService, this.stateService,
); );
this.configApiService = new ConfigApiService(this.apiService, this.authService); this.configApiService = new ConfigApiService(this.apiService, this.tokenService);
this.configService = new CliConfigService( this.configService = new DefaultConfigService(
this.stateService,
this.configApiService, this.configApiService,
this.authService,
this.environmentService, this.environmentService,
this.logService, this.logService,
this.stateProvider, this.stateProvider,
true,
); );
this.cipherService = new CipherService( this.cipherService = new CipherService(
@ -714,7 +712,6 @@ export class Main {
this.containerService.attachToGlobal(global); this.containerService.attachToGlobal(global);
await this.i18nService.init(); await this.i18nService.init();
this.twoFactorService.init(); this.twoFactorService.init();
this.configService.init();
const installedVersion = await this.stateService.getInstalledVersion(); const installedVersion = await this.stateService.getInstalledVersion();
const currentVersion = await this.platformUtilsService.getApplicationVersion(); const currentVersion = await this.platformUtilsService.getApplicationVersion();

View File

@ -1,9 +0,0 @@
import { NEVER } from "rxjs";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
export class CliConfigService extends ConfigService {
// The rxjs timer uses setTimeout/setInterval under the hood, which prevents the node process from exiting
// when the command is finished. Cli should never be alive long enough to use the timer, so we disable it.
protected refreshTimer$ = NEVER;
}

View File

@ -31,7 +31,7 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -147,7 +147,7 @@ export class AppComponent implements OnInit, OnDestroy {
private modalService: ModalService, private modalService: ModalService,
private keyConnectorService: KeyConnectorService, private keyConnectorService: KeyConnectorService,
private userVerificationService: UserVerificationService, private userVerificationService: UserVerificationService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private dialogService: DialogService, private dialogService: DialogService,
private biometricStateService: BiometricStateService, private biometricStateService: BiometricStateService,
private stateEventRunnerService: StateEventRunnerService, private stateEventRunnerService: StateEventRunnerService,
@ -265,7 +265,7 @@ export class AppComponent implements OnInit, OnDestroy {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises // eslint-disable-next-line @typescript-eslint/no-floating-promises
this.updateAppMenu(); this.updateAppMenu();
this.configService.triggerServerConfigFetch(); await this.configService.ensureConfigFetched();
} }
break; break;
case "openSettings": case "openSettings":

View File

@ -11,7 +11,6 @@ import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
import { ContainerService } from "@bitwarden/common/platform/services/container.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service";
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service"; import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service"; import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
@ -36,7 +35,6 @@ export class InitService {
private nativeMessagingService: NativeMessagingService, private nativeMessagingService: NativeMessagingService,
private themingService: AbstractThemingService, private themingService: AbstractThemingService,
private encryptService: EncryptService, private encryptService: EncryptService,
private configService: ConfigService,
@Inject(DOCUMENT) private document: Document, @Inject(DOCUMENT) private document: Document,
) {} ) {}
@ -70,8 +68,6 @@ export class InitService {
const containerService = new ContainerService(this.cryptoService, this.encryptService); const containerService = new ContainerService(this.cryptoService, this.encryptService);
containerService.attachToGlobal(this.win); containerService.attachToGlobal(this.win);
this.configService.init();
}; };
} }
} }

View File

@ -8,7 +8,7 @@ import {
} from "@bitwarden/auth/common"; } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@ -38,7 +38,7 @@ export class SsoComponent extends BaseSsoComponent {
passwordGenerationService: PasswordGenerationServiceAbstraction, passwordGenerationService: PasswordGenerationServiceAbstraction,
logService: LogService, logService: LogService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
configService: ConfigServiceAbstraction, configService: ConfigService,
) { ) {
super( super(
ssoLoginService, ssoLoginService,

View File

@ -16,7 +16,7 @@ import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -59,7 +59,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
loginService: LoginService, loginService: LoginService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
ssoLoginService: SsoLoginServiceAbstraction, ssoLoginService: SsoLoginServiceAbstraction,
configService: ConfigServiceAbstraction, configService: ConfigService,
@Inject(WINDOW) protected win: Window, @Inject(WINDOW) protected win: Window,
) { ) {
super( super(

View File

@ -8,7 +8,7 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -49,7 +49,7 @@ export class AddEditComponent extends BaseAddEditComponent implements OnChanges,
sendApiService: SendApiService, sendApiService: SendApiService,
dialogService: DialogService, dialogService: DialogService,
datePipe: DatePipe, datePipe: DatePipe,
configService: ConfigServiceAbstraction, configService: ConfigService,
) { ) {
super( super(
cipherService, cipherService,

View File

@ -3,7 +3,7 @@ import { Injectable } from "@angular/core";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request"; import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CoreOrganizationModule } from "../../core-organization.module"; import { CoreOrganizationModule } from "../../core-organization.module";
import { GroupView } from "../../views/group.view"; import { GroupView } from "../../views/group.view";
@ -18,7 +18,7 @@ import { GroupDetailsResponse, GroupResponse } from "./responses/group.response"
export class GroupService { export class GroupService {
constructor( constructor(
protected apiService: ApiService, protected apiService: ApiService,
protected configService: ConfigServiceAbstraction, protected configService: ConfigService,
) {} ) {}
async get(orgId: string, groupId: string): Promise<GroupView> { async get(orgId: string, groupId: string): Promise<GroupView> {
@ -52,7 +52,7 @@ export class GroupService {
export class InternalGroupService extends GroupService { export class InternalGroupService extends GroupService {
constructor( constructor(
protected apiService: ApiService, protected apiService: ApiService,
protected configService: ConfigServiceAbstraction, protected configService: ConfigService,
) { ) {
super(apiService, configService); super(apiService, configService);
} }

View File

@ -6,7 +6,7 @@ import {
OrganizationUserUpdateRequest, OrganizationUserUpdateRequest,
} from "@bitwarden/common/admin-console/abstractions/organization-user/requests"; } from "@bitwarden/common/admin-console/abstractions/organization-user/requests";
import { OrganizationUserDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-user/responses"; import { OrganizationUserDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-user/responses";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CoreOrganizationModule } from "../core-organization.module"; import { CoreOrganizationModule } from "../core-organization.module";
import { OrganizationUserAdminView } from "../views/organization-user-admin-view"; import { OrganizationUserAdminView } from "../views/organization-user-admin-view";
@ -14,7 +14,7 @@ import { OrganizationUserAdminView } from "../views/organization-user-admin-view
@Injectable({ providedIn: CoreOrganizationModule }) @Injectable({ providedIn: CoreOrganizationModule })
export class UserAdminService { export class UserAdminService {
constructor( constructor(
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private organizationUserService: OrganizationUserService, private organizationUserService: OrganizationUserService,
) {} ) {}

View File

@ -17,7 +17,7 @@ import {
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction as ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { BannerModule, IconModule, LayoutComponent, NavigationModule } from "@bitwarden/components"; import { BannerModule, IconModule, LayoutComponent, NavigationModule } from "@bitwarden/components";

View File

@ -24,7 +24,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { ProductType } from "@bitwarden/common/enums"; import { ProductType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view"; import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
@ -148,7 +148,7 @@ export class MemberDialogComponent implements OnDestroy {
private userService: UserAdminService, private userService: UserAdminService,
private organizationUserService: OrganizationUserService, private organizationUserService: OrganizationUserService,
private dialogService: DialogService, private dialogService: DialogService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private accountService: AccountService, private accountService: AccountService,
organizationService: OrganizationService, organizationService: OrganizationService,
) { ) {

View File

@ -11,7 +11,7 @@ import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/
import { OrganizationUpdateRequest } from "@bitwarden/common/admin-console/models/request/organization-update.request"; import { OrganizationUpdateRequest } from "@bitwarden/common/admin-console/models/request/organization-update.request";
import { OrganizationResponse } from "@bitwarden/common/admin-console/models/response/organization.response"; import { OrganizationResponse } from "@bitwarden/common/admin-console/models/response/organization.response";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -95,7 +95,7 @@ export class AccountComponent {
private organizationApiService: OrganizationApiServiceAbstraction, private organizationApiService: OrganizationApiServiceAbstraction,
private dialogService: DialogService, private dialogService: DialogService,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
) {} ) {}
async ngOnInit() { async ngOnInit() {

View File

@ -16,7 +16,7 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service"; import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { PaymentMethodWarningsServiceAbstraction as PaymentMethodWarningService } from "@bitwarden/common/billing/abstractions/payment-method-warnings-service.abstraction"; import { PaymentMethodWarningsServiceAbstraction as PaymentMethodWarningService } from "@bitwarden/common/billing/abstractions/payment-method-warnings-service.abstraction";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -83,7 +83,7 @@ export class AppComponent implements OnDestroy, OnInit {
private policyService: InternalPolicyService, private policyService: InternalPolicyService,
protected policyListService: PolicyListService, protected policyListService: PolicyListService,
private keyConnectorService: KeyConnectorService, private keyConnectorService: KeyConnectorService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private dialogService: DialogService, private dialogService: DialogService,
private biometricStateService: BiometricStateService, private biometricStateService: BiometricStateService,
private stateEventRunnerService: StateEventRunnerService, private stateEventRunnerService: StateEventRunnerService,
@ -158,7 +158,7 @@ export class AppComponent implements OnDestroy, OnInit {
break; break;
case "syncCompleted": case "syncCompleted":
if (message.successfully) { if (message.successfully) {
this.configService.triggerServerConfigFetch(); await this.configService.ensureConfigFetched();
} }
break; break;
case "upgradeOrganization": { case "upgradeOrganization": {

View File

@ -2,7 +2,7 @@ import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs"; import { BehaviorSubject } from "rxjs";
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction"; import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { EncryptionType } from "@bitwarden/common/platform/enums"; import { EncryptionType } from "@bitwarden/common/platform/enums";
@ -39,7 +39,7 @@ describe("KeyRotationService", () => {
let mockCryptoService: MockProxy<CryptoService>; let mockCryptoService: MockProxy<CryptoService>;
let mockEncryptService: MockProxy<EncryptService>; let mockEncryptService: MockProxy<EncryptService>;
let mockStateService: MockProxy<StateService>; let mockStateService: MockProxy<StateService>;
let mockConfigService: MockProxy<ConfigServiceAbstraction>; let mockConfigService: MockProxy<ConfigService>;
beforeAll(() => { beforeAll(() => {
mockApiService = mock<UserKeyRotationApiService>(); mockApiService = mock<UserKeyRotationApiService>();
@ -52,7 +52,7 @@ describe("KeyRotationService", () => {
mockCryptoService = mock<CryptoService>(); mockCryptoService = mock<CryptoService>();
mockEncryptService = mock<EncryptService>(); mockEncryptService = mock<EncryptService>();
mockStateService = mock<StateService>(); mockStateService = mock<StateService>();
mockConfigService = mock<ConfigServiceAbstraction>(); mockConfigService = mock<ConfigService>();
keyRotationService = new UserKeyRotationService( keyRotationService = new UserKeyRotationService(
mockApiService, mockApiService,

View File

@ -3,7 +3,7 @@ import { firstValueFrom } from "rxjs";
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction"; import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
@ -34,7 +34,7 @@ export class UserKeyRotationService {
private cryptoService: CryptoService, private cryptoService: CryptoService,
private encryptService: EncryptService, private encryptService: EncryptService,
private stateService: StateService, private stateService: StateService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
) {} ) {}
/** /**

View File

@ -6,7 +6,7 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -52,7 +52,7 @@ export class EmergencyAddEditCipherComponent extends BaseAddEditComponent {
sendApiService: SendApiService, sendApiService: SendApiService,
dialogService: DialogService, dialogService: DialogService,
datePipe: DatePipe, datePipe: DatePipe,
configService: ConfigServiceAbstraction, configService: ConfigService,
billingAccountProfileStateService: BillingAccountProfileStateService, billingAccountProfileStateService: BillingAccountProfileStateService,
) { ) {
super( super(

View File

@ -13,7 +13,7 @@ import { OrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-co
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { HttpStatusCode } from "@bitwarden/common/enums"; import { HttpStatusCode } from "@bitwarden/common/enums";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@ -45,7 +45,7 @@ export class SsoComponent extends BaseSsoComponent {
private orgDomainApiService: OrgDomainApiServiceAbstraction, private orgDomainApiService: OrgDomainApiServiceAbstraction,
private validationService: ValidationService, private validationService: ValidationService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
configService: ConfigServiceAbstraction, configService: ConfigService,
) { ) {
super( super(
ssoLoginService, ssoLoginService,

View File

@ -15,7 +15,7 @@ import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -49,7 +49,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
loginService: LoginService, loginService: LoginService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
ssoLoginService: SsoLoginServiceAbstraction, ssoLoginService: SsoLoginServiceAbstraction,
configService: ConfigServiceAbstraction, configService: ConfigService,
@Inject(WINDOW) protected win: Window, @Inject(WINDOW) protected win: Window,
) { ) {
super( super(

View File

@ -13,7 +13,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PaymentMethodType } from "@bitwarden/common/billing/enums"; import { PaymentMethodType } from "@bitwarden/common/billing/enums";
import { BitPayInvoiceRequest } from "@bitwarden/common/billing/models/request/bit-pay-invoice.request"; import { BitPayInvoiceRequest } from "@bitwarden/common/billing/models/request/bit-pay-invoice.request";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
@ -57,7 +57,7 @@ export class AddCreditComponent implements OnInit {
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private organizationService: OrganizationService, private organizationService: OrganizationService,
private logService: LogService, private logService: LogService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
) { ) {
const payPalConfig = process.env.PAYPAL_CONFIG as PayPalConfig; const payPalConfig = process.env.PAYPAL_CONFIG as PayPalConfig;
this.ppButtonFormAction = payPalConfig.buttonAction; this.ppButtonFormAction = payPalConfig.buttonAction;

View File

@ -10,7 +10,6 @@ import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/pla
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
import { ContainerService } from "@bitwarden/common/platform/services/container.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service";
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service"; import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service"; import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
@ -28,7 +27,6 @@ export class InitService {
private cryptoService: CryptoServiceAbstraction, private cryptoService: CryptoServiceAbstraction,
private themingService: AbstractThemingService, private themingService: AbstractThemingService,
private encryptService: EncryptService, private encryptService: EncryptService,
private configService: ConfigService,
@Inject(DOCUMENT) private document: Document, @Inject(DOCUMENT) private document: Document,
) {} ) {}
@ -46,8 +44,6 @@ export class InitService {
this.themingService.applyThemeChangesTo(this.document); this.themingService.applyThemeChangesTo(this.document);
const containerService = new ContainerService(this.cryptoService, this.encryptService); const containerService = new ContainerService(this.cryptoService, this.encryptService);
containerService.attachToGlobal(this.win); containerService.attachToGlobal(this.win);
this.configService.init();
}; };
} }
} }

View File

@ -9,7 +9,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigServiceAbstraction as ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { IconModule, LayoutComponent, NavigationModule } from "@bitwarden/components"; import { IconModule, LayoutComponent, NavigationModule } from "@bitwarden/components";

View File

@ -18,7 +18,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service"; import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
@ -107,7 +107,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
private i18nService: I18nService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private organizationUserService: OrganizationUserService, private organizationUserService: OrganizationUserService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private dialogService: DialogService, private dialogService: DialogService,
private changeDetectorRef: ChangeDetectorRef, private changeDetectorRef: ChangeDetectorRef,
) { ) {

View File

@ -8,7 +8,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service"; import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
@ -92,7 +92,7 @@ export default {
} as Partial<TokenService>, } as Partial<TokenService>,
}, },
{ {
provide: ConfigServiceAbstraction, provide: ConfigService,
useValue: { useValue: {
getFeatureFlag() { getFeatureFlag() {
// does not currently affect any display logic, default all to OFF // does not currently affect any display logic, default all to OFF

View File

@ -9,7 +9,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { EventType, ProductType } from "@bitwarden/common/enums"; import { EventType, ProductType } from "@bitwarden/common/enums";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -65,7 +65,7 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit, On
sendApiService: SendApiService, sendApiService: SendApiService,
dialogService: DialogService, dialogService: DialogService,
datePipe: DatePipe, datePipe: DatePipe,
configService: ConfigServiceAbstraction, configService: ConfigService,
private billingAccountProfileStateService: BillingAccountProfileStateService, private billingAccountProfileStateService: BillingAccountProfileStateService,
) { ) {
super( super(

View File

@ -5,7 +5,7 @@ import { Subject, of } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateProvider } from "@bitwarden/common/platform/state"; import { StateProvider } from "@bitwarden/common/platform/state";
@ -21,7 +21,7 @@ describe("VaultOnboardingComponent", () => {
let mockApiService: Partial<ApiService>; let mockApiService: Partial<ApiService>;
let mockPolicyService: MockProxy<PolicyService>; let mockPolicyService: MockProxy<PolicyService>;
let mockI18nService: MockProxy<I18nService>; let mockI18nService: MockProxy<I18nService>;
let mockConfigService: MockProxy<ConfigServiceAbstraction>; let mockConfigService: MockProxy<ConfigService>;
let mockVaultOnboardingService: MockProxy<VaultOnboardingServiceAbstraction>; let mockVaultOnboardingService: MockProxy<VaultOnboardingServiceAbstraction>;
let mockStateProvider: Partial<StateProvider>; let mockStateProvider: Partial<StateProvider>;
let setInstallExtLinkSpy: any; let setInstallExtLinkSpy: any;
@ -34,7 +34,7 @@ describe("VaultOnboardingComponent", () => {
mockApiService = { mockApiService = {
getProfile: jest.fn(), getProfile: jest.fn(),
}; };
mockConfigService = mock<ConfigServiceAbstraction>(); mockConfigService = mock<ConfigService>();
mockVaultOnboardingService = mock<VaultOnboardingServiceAbstraction>(); mockVaultOnboardingService = mock<VaultOnboardingServiceAbstraction>();
mockStateProvider = { mockStateProvider = {
getActive: jest.fn().mockReturnValue( getActive: jest.fn().mockReturnValue(
@ -56,7 +56,7 @@ describe("VaultOnboardingComponent", () => {
{ provide: VaultOnboardingServiceAbstraction, useValue: mockVaultOnboardingService }, { provide: VaultOnboardingServiceAbstraction, useValue: mockVaultOnboardingService },
{ provide: I18nService, useValue: mockI18nService }, { provide: I18nService, useValue: mockI18nService },
{ provide: ApiService, useValue: mockApiService }, { provide: ApiService, useValue: mockApiService },
{ provide: ConfigServiceAbstraction, useValue: mockConfigService }, { provide: ConfigService, useValue: mockConfigService },
{ provide: StateProvider, useValue: mockStateProvider }, { provide: StateProvider, useValue: mockStateProvider },
], ],
}).compileComponents(); }).compileComponents();

View File

@ -17,7 +17,7 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { VaultOnboardingMessages } from "@bitwarden/common/vault/enums/vault-onboarding.enum"; import { VaultOnboardingMessages } from "@bitwarden/common/vault/enums/vault-onboarding.enum";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@ -55,7 +55,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy {
protected platformUtilsService: PlatformUtilsService, protected platformUtilsService: PlatformUtilsService,
protected policyService: PolicyService, protected policyService: PolicyService,
private apiService: ApiService, private apiService: ApiService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private vaultOnboardingService: VaultOnboardingServiceAbstraction, private vaultOnboardingService: VaultOnboardingServiceAbstraction,
) {} ) {}

View File

@ -41,7 +41,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
import { EventType } from "@bitwarden/common/enums"; import { EventType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -180,7 +180,7 @@ export class VaultComponent implements OnInit, OnDestroy {
private eventCollectionService: EventCollectionService, private eventCollectionService: EventCollectionService,
private searchService: SearchService, private searchService: SearchService,
private searchPipe: SearchPipe, private searchPipe: SearchPipe,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private apiService: ApiService, private apiService: ApiService,
private userVerificationService: UserVerificationService, private userVerificationService: UserVerificationService,
private billingAccountProfileStateService: BillingAccountProfileStateService, private billingAccountProfileStateService: BillingAccountProfileStateService,

View File

@ -7,7 +7,7 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -54,7 +54,7 @@ export class AddEditComponent extends BaseAddEditComponent {
sendApiService: SendApiService, sendApiService: SendApiService,
dialogService: DialogService, dialogService: DialogService,
datePipe: DatePipe, datePipe: DatePipe,
configService: ConfigServiceAbstraction, configService: ConfigService,
billingAccountProfileStateService: BillingAccountProfileStateService, billingAccountProfileStateService: BillingAccountProfileStateService,
) { ) {
super( super(

View File

@ -4,7 +4,7 @@ import { Subject } from "rxjs";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CipherId, CollectionId, OrganizationId } from "@bitwarden/common/types/guid"; import { CipherId, CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
@ -65,7 +65,7 @@ export class BulkCollectionAssignmentDialogComponent implements OnDestroy, OnIni
private cipherService: CipherService, private cipherService: CipherService,
private i18nService: I18nService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private organizationService: OrganizationService, private organizationService: OrganizationService,
) {} ) {}

View File

@ -40,7 +40,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { EventType } from "@bitwarden/common/enums"; import { EventType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -184,7 +184,7 @@ export class VaultComponent implements OnInit, OnDestroy {
private totpService: TotpService, private totpService: TotpService,
private apiService: ApiService, private apiService: ApiService,
private collectionService: CollectionService, private collectionService: CollectionService,
protected configService: ConfigServiceAbstraction, protected configService: ConfigService,
) {} ) {}
async ngOnInit() { async ngOnInit() {

View File

@ -6,7 +6,7 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service"; import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider"; import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction as ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { IconModule, LayoutComponent, NavigationModule } from "@bitwarden/components"; import { IconModule, LayoutComponent, NavigationModule } from "@bitwarden/components";
import { ProviderPortalLogo } from "@bitwarden/web-vault/app/admin-console/icons/provider-portal-logo"; import { ProviderPortalLogo } from "@bitwarden/web-vault/app/admin-console/icons/provider-portal-logo";
import { PaymentMethodWarningsModule } from "@bitwarden/web-vault/app/billing/shared"; import { PaymentMethodWarningsModule } from "@bitwarden/web-vault/app/billing/shared";

View File

@ -5,7 +5,7 @@ import { first } from "rxjs/operators";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { ProviderSetupRequest } from "@bitwarden/common/admin-console/models/request/provider/provider-setup.request"; import { ProviderSetupRequest } from "@bitwarden/common/admin-console/models/request/provider/provider-setup.request";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction as ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";

View File

@ -26,7 +26,7 @@ import { SsoConfigApi } from "@bitwarden/common/auth/models/api/sso-config.api";
import { OrganizationSsoRequest } from "@bitwarden/common/auth/models/request/organization-sso.request"; import { OrganizationSsoRequest } from "@bitwarden/common/auth/models/request/organization-sso.request";
import { OrganizationSsoResponse } from "@bitwarden/common/auth/models/response/organization-sso.response"; import { OrganizationSsoResponse } from "@bitwarden/common/auth/models/response/organization-sso.response";
import { SsoConfigView } from "@bitwarden/common/auth/models/view/sso-config.view"; import { SsoConfigView } from "@bitwarden/common/auth/models/view/sso-config.view";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
@ -186,7 +186,7 @@ export class SsoComponent implements OnInit, OnDestroy {
private i18nService: I18nService, private i18nService: I18nService,
private organizationService: OrganizationService, private organizationService: OrganizationService,
private organizationApiService: OrganizationApiServiceAbstraction, private organizationApiService: OrganizationApiServiceAbstraction,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
) {} ) {}
async ngOnInit() { async ngOnInit() {

View File

@ -16,7 +16,7 @@ import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@ -66,7 +66,7 @@ describe("SsoComponent", () => {
let mockPasswordGenerationService: MockProxy<PasswordGenerationServiceAbstraction>; let mockPasswordGenerationService: MockProxy<PasswordGenerationServiceAbstraction>;
let mockLogService: MockProxy<LogService>; let mockLogService: MockProxy<LogService>;
let mockUserDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>; let mockUserDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>;
let mockConfigService: MockProxy<ConfigServiceAbstraction>; let mockConfigService: MockProxy<ConfigService>;
// Mock authService.logIn params // Mock authService.logIn params
let code: string; let code: string;
@ -107,16 +107,16 @@ describe("SsoComponent", () => {
queryParams: mockQueryParams, queryParams: mockQueryParams,
} as any as ActivatedRoute; } as any as ActivatedRoute;
mockSsoLoginService = mock<SsoLoginServiceAbstraction>(); mockSsoLoginService = mock();
mockStateService = mock<StateService>(); mockStateService = mock();
mockPlatformUtilsService = mock<PlatformUtilsService>(); mockPlatformUtilsService = mock();
mockApiService = mock<ApiService>(); mockApiService = mock();
mockCryptoFunctionService = mock<CryptoFunctionService>(); mockCryptoFunctionService = mock();
mockEnvironmentService = mock<EnvironmentService>(); mockEnvironmentService = mock();
mockPasswordGenerationService = mock<PasswordGenerationServiceAbstraction>(); mockPasswordGenerationService = mock();
mockLogService = mock<LogService>(); mockLogService = mock();
mockUserDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>(); mockUserDecryptionOptionsService = mock();
mockConfigService = mock<ConfigServiceAbstraction>(); mockConfigService = mock();
// Mock loginStrategyService.logIn params // Mock loginStrategyService.logIn params
code = "code"; code = "code";
@ -198,7 +198,7 @@ describe("SsoComponent", () => {
useValue: mockUserDecryptionOptionsService, useValue: mockUserDecryptionOptionsService,
}, },
{ provide: LogService, useValue: mockLogService }, { provide: LogService, useValue: mockLogService },
{ provide: ConfigServiceAbstraction, useValue: mockConfigService }, { provide: ConfigService, useValue: mockConfigService },
], ],
}); });

View File

@ -15,7 +15,7 @@ import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { SsoPreValidateResponse } from "@bitwarden/common/auth/models/response/sso-pre-validate.response"; import { SsoPreValidateResponse } from "@bitwarden/common/auth/models/response/sso-pre-validate.response";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@ -65,7 +65,7 @@ export class SsoComponent {
protected passwordGenerationService: PasswordGenerationServiceAbstraction, protected passwordGenerationService: PasswordGenerationServiceAbstraction,
protected logService: LogService, protected logService: LogService,
protected userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, protected userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
protected configService: ConfigServiceAbstraction, protected configService: ConfigService,
) {} ) {}
async ngOnInit() { async ngOnInit() {

View File

@ -21,7 +21,7 @@ import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request"; import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -62,7 +62,7 @@ describe("TwoFactorComponent", () => {
let mockLoginService: MockProxy<LoginService>; let mockLoginService: MockProxy<LoginService>;
let mockUserDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>; let mockUserDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>;
let mockSsoLoginService: MockProxy<SsoLoginServiceAbstraction>; let mockSsoLoginService: MockProxy<SsoLoginServiceAbstraction>;
let mockConfigService: MockProxy<ConfigServiceAbstraction>; let mockConfigService: MockProxy<ConfigService>;
let mockUserDecryptionOpts: { let mockUserDecryptionOpts: {
noMasterPassword: UserDecryptionOptions; noMasterPassword: UserDecryptionOptions;
@ -92,7 +92,7 @@ describe("TwoFactorComponent", () => {
mockLoginService = mock<LoginService>(); mockLoginService = mock<LoginService>();
mockUserDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>(); mockUserDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>();
mockSsoLoginService = mock<SsoLoginServiceAbstraction>(); mockSsoLoginService = mock<SsoLoginServiceAbstraction>();
mockConfigService = mock<ConfigServiceAbstraction>(); mockConfigService = mock<ConfigService>();
mockUserDecryptionOpts = { mockUserDecryptionOpts = {
noMasterPassword: new UserDecryptionOptions({ noMasterPassword: new UserDecryptionOptions({
@ -169,7 +169,7 @@ describe("TwoFactorComponent", () => {
useValue: mockUserDecryptionOptionsService, useValue: mockUserDecryptionOptionsService,
}, },
{ provide: SsoLoginServiceAbstraction, useValue: mockSsoLoginService }, { provide: SsoLoginServiceAbstraction, useValue: mockSsoLoginService },
{ provide: ConfigServiceAbstraction, useValue: mockConfigService }, { provide: ConfigService, useValue: mockConfigService },
], ],
}); });

View File

@ -25,7 +25,7 @@ import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two
import { TwoFactorProviders } from "@bitwarden/common/auth/services/two-factor.service"; import { TwoFactorProviders } from "@bitwarden/common/auth/services/two-factor.service";
import { WebAuthnIFrame } from "@bitwarden/common/auth/webauthn-iframe"; import { WebAuthnIFrame } from "@bitwarden/common/auth/webauthn-iframe";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -91,7 +91,7 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
protected loginService: LoginService, protected loginService: LoginService,
protected userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction, protected userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
protected ssoLoginService: SsoLoginServiceAbstraction, protected ssoLoginService: SsoLoginServiceAbstraction,
protected configService: ConfigServiceAbstraction, protected configService: ConfigService,
) { ) {
super(environmentService, i18nService, platformUtilsService); super(environmentService, i18nService, platformUtilsService);
this.webAuthnSupported = this.platformUtilsService.supportsWebAuthn(win); this.webAuthnSupported = this.platformUtilsService.supportsWebAuthn(win);

View File

@ -4,7 +4,7 @@ import { By } from "@angular/platform-browser";
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { FeatureFlag, FeatureFlagValue } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag, FeatureFlagValue } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { IfFeatureDirective } from "./if-feature.directive"; import { IfFeatureDirective } from "./if-feature.directive";
@ -39,7 +39,7 @@ class TestComponent {
describe("IfFeatureDirective", () => { describe("IfFeatureDirective", () => {
let fixture: ComponentFixture<TestComponent>; let fixture: ComponentFixture<TestComponent>;
let content: HTMLElement; let content: HTMLElement;
let mockConfigService: MockProxy<ConfigServiceAbstraction>; let mockConfigService: MockProxy<ConfigService>;
const mockConfigFlagValue = (flag: FeatureFlag, flagValue: FeatureFlagValue) => { const mockConfigFlagValue = (flag: FeatureFlag, flagValue: FeatureFlagValue) => {
mockConfigService.getFeatureFlag.mockImplementation((f, defaultValue) => mockConfigService.getFeatureFlag.mockImplementation((f, defaultValue) =>
@ -51,14 +51,14 @@ describe("IfFeatureDirective", () => {
fixture.debugElement.query(By.css(`[data-testid="${testId}"]`))?.nativeElement; fixture.debugElement.query(By.css(`[data-testid="${testId}"]`))?.nativeElement;
beforeEach(async () => { beforeEach(async () => {
mockConfigService = mock<ConfigServiceAbstraction>(); mockConfigService = mock<ConfigService>();
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [IfFeatureDirective, TestComponent], declarations: [IfFeatureDirective, TestComponent],
providers: [ providers: [
{ provide: LogService, useValue: mock<LogService>() }, { provide: LogService, useValue: mock<LogService>() },
{ {
provide: ConfigServiceAbstraction, provide: ConfigService,
useValue: mockConfigService, useValue: mockConfigService,
}, },
], ],

View File

@ -1,7 +1,7 @@
import { Directive, Input, OnInit, TemplateRef, ViewContainerRef } from "@angular/core"; import { Directive, Input, OnInit, TemplateRef, ViewContainerRef } from "@angular/core";
import { FeatureFlag, FeatureFlagValue } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag, FeatureFlagValue } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
/** /**
@ -30,7 +30,7 @@ export class IfFeatureDirective implements OnInit {
constructor( constructor(
private templateRef: TemplateRef<any>, private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef, private viewContainer: ViewContainerRef,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private logService: LogService, private logService: LogService,
) {} ) {}

View File

@ -5,7 +5,7 @@ import { RouterTestingModule } from "@angular/router/testing";
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -21,11 +21,11 @@ describe("canAccessFeature", () => {
const featureRoute = "enabled-feature"; const featureRoute = "enabled-feature";
const redirectRoute = "redirect"; const redirectRoute = "redirect";
let mockConfigService: MockProxy<ConfigServiceAbstraction>; let mockConfigService: MockProxy<ConfigService>;
let mockPlatformUtilsService: MockProxy<PlatformUtilsService>; let mockPlatformUtilsService: MockProxy<PlatformUtilsService>;
const setup = (featureGuard: CanActivateFn, flagValue: any) => { const setup = (featureGuard: CanActivateFn, flagValue: any) => {
mockConfigService = mock<ConfigServiceAbstraction>(); mockConfigService = mock<ConfigService>();
mockPlatformUtilsService = mock<PlatformUtilsService>(); mockPlatformUtilsService = mock<PlatformUtilsService>();
// Mock the correct getter based on the type of flagValue; also mock default values if one is not provided // Mock the correct getter based on the type of flagValue; also mock default values if one is not provided
@ -56,7 +56,7 @@ describe("canAccessFeature", () => {
]), ]),
], ],
providers: [ providers: [
{ provide: ConfigServiceAbstraction, useValue: mockConfigService }, { provide: ConfigService, useValue: mockConfigService },
{ provide: PlatformUtilsService, useValue: mockPlatformUtilsService }, { provide: PlatformUtilsService, useValue: mockPlatformUtilsService },
{ provide: LogService, useValue: mock<LogService>() }, { provide: LogService, useValue: mock<LogService>() },
{ {

View File

@ -2,7 +2,7 @@ import { inject } from "@angular/core";
import { CanActivateFn, Router } from "@angular/router"; import { CanActivateFn, Router } from "@angular/router";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -23,7 +23,7 @@ export const canAccessFeature = (
redirectUrlOnDisabled?: string, redirectUrlOnDisabled?: string,
): CanActivateFn => { ): CanActivateFn => {
return async () => { return async () => {
const configService = inject(ConfigServiceAbstraction); const configService = inject(ConfigService);
const platformUtilsService = inject(PlatformUtilsService); const platformUtilsService = inject(PlatformUtilsService);
const router = inject(Router); const router = inject(Router);
const i18nService = inject(I18nService); const i18nService = inject(I18nService);

View File

@ -111,7 +111,7 @@ import { PaymentMethodWarningsService } from "@bitwarden/common/billing/services
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service";
import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
@ -135,7 +135,7 @@ import { Account } from "@bitwarden/common/platform/models/domain/account";
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
import { AppIdService } from "@bitwarden/common/platform/services/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/services/app-id.service";
import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service";
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service"; import { DefaultConfigService } from "@bitwarden/common/platform/services/config/default-config.service";
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service"; import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
import { CryptoService } from "@bitwarden/common/platform/services/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/services/crypto.service";
import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation"; import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation";
@ -400,7 +400,7 @@ const typesafeProviders: Array<SafeProvider> = [
autofillSettingsService: AutofillSettingsServiceAbstraction, autofillSettingsService: AutofillSettingsServiceAbstraction,
encryptService: EncryptService, encryptService: EncryptService,
fileUploadService: CipherFileUploadServiceAbstraction, fileUploadService: CipherFileUploadServiceAbstraction,
configService: ConfigServiceAbstraction, configService: ConfigService,
) => ) =>
new CipherService( new CipherService(
cryptoService, cryptoService,
@ -424,7 +424,7 @@ const typesafeProviders: Array<SafeProvider> = [
AutofillSettingsServiceAbstraction, AutofillSettingsServiceAbstraction,
EncryptService, EncryptService,
CipherFileUploadServiceAbstraction, CipherFileUploadServiceAbstraction,
ConfigServiceAbstraction, ConfigService,
], ],
}), }),
safeProvider({ safeProvider({
@ -851,25 +851,18 @@ const typesafeProviders: Array<SafeProvider> = [
deps: [], deps: [],
}), }),
safeProvider({ safeProvider({
provide: ConfigService, provide: DefaultConfigService,
useClass: ConfigService, useClass: DefaultConfigService,
deps: [ deps: [ConfigApiServiceAbstraction, EnvironmentService, LogService, StateProvider],
StateServiceAbstraction,
ConfigApiServiceAbstraction,
AuthServiceAbstraction,
EnvironmentService,
LogService,
StateProvider,
],
}), }),
safeProvider({ safeProvider({
provide: ConfigServiceAbstraction, provide: ConfigService,
useExisting: ConfigService, useExisting: DefaultConfigService,
}), }),
safeProvider({ safeProvider({
provide: ConfigApiServiceAbstraction, provide: ConfigApiServiceAbstraction,
useClass: ConfigApiService, useClass: ConfigApiService,
deps: [ApiServiceAbstraction, AuthServiceAbstraction], deps: [ApiServiceAbstraction, TokenServiceAbstraction],
}), }),
safeProvider({ safeProvider({
provide: AnonymousHubServiceAbstraction, provide: AnonymousHubServiceAbstraction,

View File

@ -14,7 +14,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { EventType } from "@bitwarden/common/enums"; import { EventType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { UriMatchStrategy } from "@bitwarden/common/models/domain/domain-service"; import { UriMatchStrategy } from "@bitwarden/common/models/domain/domain-service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -119,7 +119,7 @@ export class AddEditComponent implements OnInit, OnDestroy {
protected dialogService: DialogService, protected dialogService: DialogService,
protected win: Window, protected win: Window,
protected datePipe: DatePipe, protected datePipe: DatePipe,
protected configService: ConfigServiceAbstraction, protected configService: ConfigService,
) { ) {
this.typeOptions = [ this.typeOptions = [
{ name: i18nService.t("typeLogin"), value: CipherType.Login }, { name: i18nService.t("typeLogin"), value: CipherType.Login },

View File

@ -0,0 +1,54 @@
describe("toAlmostEqual custom matcher", () => {
it("matches identical Dates", () => {
const date = new Date();
expect(date).toAlmostEqual(date);
});
it("matches when older but within default ms", () => {
const date = new Date();
const olderDate = new Date(date.getTime() - 5);
expect(date).toAlmostEqual(olderDate);
});
it("matches when newer but within default ms", () => {
const date = new Date();
const olderDate = new Date(date.getTime() + 5);
expect(date).toAlmostEqual(olderDate);
});
it("doesn't match if older than default ms", () => {
const date = new Date();
const olderDate = new Date(date.getTime() - 11);
expect(date).not.toAlmostEqual(olderDate);
});
it("doesn't match if newer than default ms", () => {
const date = new Date();
const olderDate = new Date(date.getTime() + 11);
expect(date).not.toAlmostEqual(olderDate);
});
it("matches when older but within custom ms", () => {
const date = new Date();
const olderDate = new Date(date.getTime() - 15);
expect(date).toAlmostEqual(olderDate, 20);
});
it("matches when newer but within custom ms", () => {
const date = new Date();
const olderDate = new Date(date.getTime() + 15);
expect(date).toAlmostEqual(olderDate, 20);
});
it("doesn't match if older than custom ms", () => {
const date = new Date();
const olderDate = new Date(date.getTime() - 21);
expect(date).not.toAlmostEqual(olderDate, 20);
});
it("doesn't match if newer than custom ms", () => {
const date = new Date();
const olderDate = new Date(date.getTime() + 21);
expect(date).not.toAlmostEqual(olderDate, 20);
});
});

View File

@ -0,0 +1,20 @@
/**
* Matches the expected date within an optional ms precision
* @param received The received date
* @param expected The expected date
* @param msPrecision The optional precision in milliseconds
*/
export const toAlmostEqual: jest.CustomMatcher = function (
received: Date,
expected: Date,
msPrecision: number = 10,
) {
const receivedTime = received.getTime();
const expectedTime = expected.getTime();
const difference = Math.abs(receivedTime - expectedTime);
return {
pass: difference <= msPrecision,
message: () =>
`expected ${received} to be within ${msPrecision}ms of ${expected} (actual difference: ${difference}ms)`,
};
};

View File

@ -0,0 +1,86 @@
import { Observable, Subscription, firstValueFrom, throwError, timeout } from "rxjs";
/** Test class to enable async awaiting of observable emissions */
export class ObservableTracker<T> {
private subscription: Subscription;
emissions: T[] = [];
constructor(private observable: Observable<T>) {
this.emissions = this.trackEmissions(observable);
}
/** Unsubscribes from the observable */
unsubscribe() {
this.subscription.unsubscribe();
}
/**
* Awaits the next emission from the observable, or throws if the timeout is exceeded
* @param msTimeout The maximum time to wait for another emission before throwing
*/
async expectEmission(msTimeout = 50) {
await firstValueFrom(
this.observable.pipe(
timeout({
first: msTimeout,
with: () => throwError(() => new Error("Timeout exceeded waiting for another emission.")),
}),
),
);
}
/** Awaits until the the total number of emissions observed by this tracker equals or exceeds {@link count}
* @param count The number of emissions to wait for
*/
async pauseUntilReceived(count: number, msTimeout = 50): Promise<T[]> {
for (let i = 0; i < count - this.emissions.length; i++) {
await this.expectEmission(msTimeout);
}
return this.emissions;
}
private trackEmissions<T>(observable: Observable<T>): T[] {
const emissions: T[] = [];
this.subscription = observable.subscribe((value) => {
switch (value) {
case undefined:
case null:
emissions.push(value);
return;
default:
// process by type
break;
}
switch (typeof value) {
case "string":
case "number":
case "boolean":
emissions.push(value);
break;
case "symbol":
// Cheating types to make symbols work at all
emissions.push(value.toString() as T);
break;
default: {
emissions.push(clone(value));
}
}
});
return emissions;
}
}
function clone(value: any): any {
if (global.structuredClone != undefined) {
return structuredClone(value);
} else {
return JSON.parse(JSON.stringify(value));
}
}
/** A test helper that builds an @see{@link ObservableTracker}, which can be used to assert things about the
* emissions of the given observable
* @param observable The observable to track
*/
export function subscribeTo<T>(observable: Observable<T>) {
return new ObservableTracker(observable);
}

View File

@ -1,5 +1,9 @@
import { UserId } from "../../../types/guid";
import { ServerConfigResponse } from "../../models/response/server-config.response"; import { ServerConfigResponse } from "../../models/response/server-config.response";
export abstract class ConfigApiServiceAbstraction { export abstract class ConfigApiServiceAbstraction {
get: () => Promise<ServerConfigResponse>; /**
* Fetches the server configuration for the given user. If no user is provided, the configuration will not contain user-specific context.
*/
get: (userId: UserId | undefined) => Promise<ServerConfigResponse>;
} }

View File

@ -1,30 +0,0 @@
import { Observable } from "rxjs";
import { SemVer } from "semver";
import { FeatureFlag } from "../../../enums/feature-flag.enum";
import { Region } from "../environment.service";
import { ServerConfig } from "./server-config";
export abstract class ConfigServiceAbstraction {
serverConfig$: Observable<ServerConfig | null>;
cloudRegion$: Observable<Region>;
getFeatureFlag$: <T extends boolean | number | string>(
key: FeatureFlag,
defaultValue?: T,
) => Observable<T>;
getFeatureFlag: <T extends boolean | number | string>(
key: FeatureFlag,
defaultValue?: T,
) => Promise<T>;
checkServerMeetsVersionRequirement$: (
minimumRequiredServerVersion: SemVer,
) => Observable<boolean>;
/**
* Force ConfigService to fetch an updated config from the server and emit it from serverConfig$
* @deprecated The service implementation should subscribe to an observable and use that to trigger a new fetch from
* server instead
*/
triggerServerConfigFetch: () => void;
}

View File

@ -0,0 +1,47 @@
import { Observable } from "rxjs";
import { SemVer } from "semver";
import { FeatureFlag } from "../../../enums/feature-flag.enum";
import { Region } from "../environment.service";
import { ServerConfig } from "./server-config";
export abstract class ConfigService {
/** The server config of the currently active user */
serverConfig$: Observable<ServerConfig | null>;
/** The cloud region of the currently active user */
cloudRegion$: Observable<Region>;
/**
* Retrieves the value of a feature flag for the currently active user
* @param key The feature flag to retrieve
* @param defaultValue The default value to return if the feature flag is not set or the server's config is irretrievable
* @returns An observable that emits the value of the feature flag, updates as the server config changes
*/
getFeatureFlag$: <T extends boolean | number | string>(
key: FeatureFlag,
defaultValue?: T,
) => Observable<T>;
/**
* Retrieves the value of a feature flag for the currently active user
* @param key The feature flag to retrieve
* @param defaultValue The default value to return if the feature flag is not set or the server's config is irretrievable
* @returns The value of the feature flag
*/
getFeatureFlag: <T extends boolean | number | string>(
key: FeatureFlag,
defaultValue?: T,
) => Promise<T>;
/**
* Verifies whether the server version meets the minimum required version
* @param minimumRequiredServerVersion The minimum version required
* @returns True if the server version is greater than or equal to the minimum required version
*/
checkServerMeetsVersionRequirement$: (
minimumRequiredServerVersion: SemVer,
) => Observable<boolean>;
/**
* Triggers a check that the config for the currently active user is up-to-date. If it is not, it will be fetched from the server and stored.
*/
abstract ensureConfigFetched(): Promise<void>;
}

View File

@ -7,7 +7,6 @@ import {
} from "../../models/data/server-config.data"; } from "../../models/data/server-config.data";
const dayInMilliseconds = 24 * 3600 * 1000; const dayInMilliseconds = 24 * 3600 * 1000;
const eighteenHoursInMilliseconds = 18 * 3600 * 1000;
export class ServerConfig { export class ServerConfig {
version: string; version: string;
@ -38,10 +37,6 @@ export class ServerConfig {
return this.getAgeInMilliseconds() <= dayInMilliseconds; return this.getAgeInMilliseconds() <= dayInMilliseconds;
} }
expiresSoon(): boolean {
return this.getAgeInMilliseconds() >= eighteenHoursInMilliseconds;
}
static fromJSON(obj: Jsonify<ServerConfig>): ServerConfig { static fromJSON(obj: Jsonify<ServerConfig>): ServerConfig {
if (obj == null) { if (obj == null) {
return null; return null;

View File

@ -16,7 +16,6 @@ import { LocalData } from "../../vault/models/data/local.data";
import { CipherView } from "../../vault/models/view/cipher.view"; import { CipherView } from "../../vault/models/view/cipher.view";
import { AddEditCipherInfo } from "../../vault/types/add-edit-cipher-info"; import { AddEditCipherInfo } from "../../vault/types/add-edit-cipher-info";
import { KdfType } from "../enums"; import { KdfType } from "../enums";
import { ServerConfigData } from "../models/data/server-config.data";
import { Account } from "../models/domain/account"; import { Account } from "../models/domain/account";
import { EncString } from "../models/domain/enc-string"; import { EncString } from "../models/domain/enc-string";
import { StorageOptions } from "../models/domain/storage-options"; import { StorageOptions } from "../models/domain/storage-options";
@ -278,14 +277,6 @@ export abstract class StateService<T extends Account = Account> {
setVaultTimeoutAction: (value: string, options?: StorageOptions) => Promise<void>; setVaultTimeoutAction: (value: string, options?: StorageOptions) => Promise<void>;
getApproveLoginRequests: (options?: StorageOptions) => Promise<boolean>; getApproveLoginRequests: (options?: StorageOptions) => Promise<boolean>;
setApproveLoginRequests: (value: boolean, options?: StorageOptions) => Promise<void>; setApproveLoginRequests: (value: boolean, options?: StorageOptions) => Promise<void>;
/**
* @deprecated Do not call this directly, use ConfigService
*/
getServerConfig: (options?: StorageOptions) => Promise<ServerConfigData>;
/**
* @deprecated Do not call this directly, use ConfigService
*/
setServerConfig: (value: ServerConfigData, options?: StorageOptions) => Promise<void>;
/** /**
* fetches string value of URL user tried to navigate to while unauthenticated. * fetches string value of URL user tried to navigate to while unauthenticated.
* @param options Defines the storage options for the URL; Defaults to session Storage. * @param options Defines the storage options for the URL; Defaults to session Storage.

View File

@ -18,7 +18,6 @@ import { CipherView } from "../../../vault/models/view/cipher.view";
import { AddEditCipherInfo } from "../../../vault/types/add-edit-cipher-info"; import { AddEditCipherInfo } from "../../../vault/types/add-edit-cipher-info";
import { KdfType } from "../../enums"; import { KdfType } from "../../enums";
import { Utils } from "../../misc/utils"; import { Utils } from "../../misc/utils";
import { ServerConfigData } from "../../models/data/server-config.data";
import { EncryptedString, EncString } from "./enc-string"; import { EncryptedString, EncString } from "./enc-string";
import { SymmetricCryptoKey } from "./symmetric-crypto-key"; import { SymmetricCryptoKey } from "./symmetric-crypto-key";
@ -196,7 +195,6 @@ export class AccountSettings {
protectedPin?: string; protectedPin?: string;
vaultTimeout?: number; vaultTimeout?: number;
vaultTimeoutAction?: string = "lock"; vaultTimeoutAction?: string = "lock";
serverConfig?: ServerConfigData;
approveLoginRequests?: boolean; approveLoginRequests?: boolean;
avatarColor?: string; avatarColor?: string;
trustDeviceChoiceForDecryption?: boolean; trustDeviceChoiceForDecryption?: boolean;
@ -214,7 +212,6 @@ export class AccountSettings {
obj?.pinProtected, obj?.pinProtected,
EncString.fromJSON, EncString.fromJSON,
), ),
serverConfig: ServerConfigData.fromJSON(obj?.serverConfig),
}); });
} }
} }

View File

@ -1,18 +1,20 @@
import { ApiService } from "../../../abstractions/api.service"; import { ApiService } from "../../../abstractions/api.service";
import { AuthService } from "../../../auth/abstractions/auth.service"; import { TokenService } from "../../../auth/abstractions/token.service";
import { AuthenticationStatus } from "../../../auth/enums/authentication-status"; import { UserId } from "../../../types/guid";
import { ConfigApiServiceAbstraction } from "../../abstractions/config/config-api.service.abstraction"; import { ConfigApiServiceAbstraction } from "../../abstractions/config/config-api.service.abstraction";
import { ServerConfigResponse } from "../../models/response/server-config.response"; import { ServerConfigResponse } from "../../models/response/server-config.response";
export class ConfigApiService implements ConfigApiServiceAbstraction { export class ConfigApiService implements ConfigApiServiceAbstraction {
constructor( constructor(
private apiService: ApiService, private apiService: ApiService,
private authService: AuthService, private tokenService: TokenService,
) {} ) {}
async get(): Promise<ServerConfigResponse> { async get(userId: UserId | undefined): Promise<ServerConfigResponse> {
// Authentication adds extra context to config responses, if the user has an access token, we want to use it
// We don't particularly care about ensuring the token is valid and not expired, just that it exists
const authed: boolean = const authed: boolean =
(await this.authService.getAuthStatus()) !== AuthenticationStatus.LoggedOut; userId == null ? false : (await this.tokenService.getAccessToken(userId)) != null;
const r = await this.apiService.send("GET", "/config", null, authed, true); const r = await this.apiService.send("GET", "/config", null, authed, true);
return new ServerConfigResponse(r); return new ServerConfigResponse(r);

View File

@ -1,200 +1,264 @@
import { MockProxy, mock } from "jest-mock-extended"; /**
import { ReplaySubject, skip, take } from "rxjs"; * need to update test environment so structuredClone works appropriately
* @jest-environment ../../libs/shared/test.environment.ts
*/
import { FakeStateProvider, mockAccountServiceWith } from "../../../../spec"; import { mock } from "jest-mock-extended";
import { AuthService } from "../../../auth/abstractions/auth.service"; import { Subject, firstValueFrom, of } from "rxjs";
import { AuthenticationStatus } from "../../../auth/enums/authentication-status";
import {
FakeGlobalState,
FakeSingleUserState,
FakeStateProvider,
awaitAsync,
mockAccountServiceWith,
} from "../../../../spec";
import { subscribeTo } from "../../../../spec/observable-tracker";
import { UserId } from "../../../types/guid"; import { UserId } from "../../../types/guid";
import { ConfigApiServiceAbstraction } from "../../abstractions/config/config-api.service.abstraction"; import { ConfigApiServiceAbstraction } from "../../abstractions/config/config-api.service.abstraction";
import { ServerConfig } from "../../abstractions/config/server-config"; import { ServerConfig } from "../../abstractions/config/server-config";
import { Environment, EnvironmentService } from "../../abstractions/environment.service"; import { Environment, EnvironmentService } from "../../abstractions/environment.service";
import { LogService } from "../../abstractions/log.service"; import { LogService } from "../../abstractions/log.service";
import { StateService } from "../../abstractions/state.service"; import { Utils } from "../../misc/utils";
import { ServerConfigData } from "../../models/data/server-config.data"; import { ServerConfigData } from "../../models/data/server-config.data";
import { import {
EnvironmentServerConfigResponse, EnvironmentServerConfigResponse,
ServerConfigResponse, ServerConfigResponse,
ThirdPartyServerConfigResponse, ThirdPartyServerConfigResponse,
} from "../../models/response/server-config.response"; } from "../../models/response/server-config.response";
import { StateProvider } from "../../state";
import { ConfigService } from "./config.service"; import {
ApiUrl,
DefaultConfigService,
RETRIEVAL_INTERVAL,
GLOBAL_SERVER_CONFIGURATIONS,
USER_SERVER_CONFIG,
} from "./default-config.service";
describe("ConfigService", () => { describe("ConfigService", () => {
let stateService: MockProxy<StateService>; const configApiService = mock<ConfigApiServiceAbstraction>();
let configApiService: MockProxy<ConfigApiServiceAbstraction>; const environmentService = mock<EnvironmentService>();
let authService: MockProxy<AuthService>; const logService = mock<LogService>();
let environmentService: MockProxy<EnvironmentService>; let stateProvider: FakeStateProvider;
let logService: MockProxy<LogService>; let globalState: FakeGlobalState<Record<ApiUrl, ServerConfig>>;
let replaySubject: ReplaySubject<Environment>; let userState: FakeSingleUserState<ServerConfig>;
let stateProvider: StateProvider; const activeApiUrl = apiUrl(0);
const userId = "userId" as UserId;
let serverResponseCount: number; // increments to track distinct responses received from server const accountService = mockAccountServiceWith(userId);
const tooOld = new Date(Date.now() - 1.1 * RETRIEVAL_INTERVAL);
// Observables will start emitting as soon as this is created, so only create it
// after everything is mocked
const configServiceFactory = () => {
const configService = new ConfigService(
stateService,
configApiService,
authService,
environmentService,
logService,
stateProvider,
);
configService.init();
return configService;
};
beforeEach(() => { beforeEach(() => {
stateService = mock();
configApiService = mock();
authService = mock();
environmentService = mock();
logService = mock();
replaySubject = new ReplaySubject<Environment>(1);
const accountService = mockAccountServiceWith("0" as UserId);
stateProvider = new FakeStateProvider(accountService); stateProvider = new FakeStateProvider(accountService);
globalState = stateProvider.global.getFake(GLOBAL_SERVER_CONFIGURATIONS);
environmentService.environment$ = replaySubject.asObservable(); userState = stateProvider.singleUser.getFake(userId, USER_SERVER_CONFIG);
serverResponseCount = 1;
configApiService.get.mockImplementation(() =>
Promise.resolve(serverConfigResponseFactory("server" + serverResponseCount++)),
);
jest.useFakeTimers();
}); });
afterEach(() => { afterEach(() => {
jest.useRealTimers(); jest.resetAllMocks();
}); });
it("Uses storage as fallback", (done) => { describe.each([null, userId])("active user: %s", (activeUserId) => {
const storedConfigData = serverConfigDataFactory("storedConfig"); let sut: DefaultConfigService;
stateService.getServerConfig.mockResolvedValueOnce(storedConfigData);
configApiService.get.mockRejectedValueOnce(new Error("Unable to fetch")); beforeAll(async () => {
await accountService.switchAccount(activeUserId);
const configService = configServiceFactory();
configService.serverConfig$.pipe(take(1)).subscribe((config) => {
expect(config).toEqual(new ServerConfig(storedConfigData));
expect(stateService.getServerConfig).toHaveBeenCalledTimes(1);
expect(stateService.setServerConfig).not.toHaveBeenCalled();
done();
}); });
configService.triggerServerConfigFetch();
});
it("Stream does not error out if fetch fails", (done) => {
const storedConfigData = serverConfigDataFactory("storedConfig");
stateService.getServerConfig.mockResolvedValueOnce(storedConfigData);
const configService = configServiceFactory();
configService.serverConfig$.pipe(skip(1), take(1)).subscribe((config) => {
try {
expect(config.gitHash).toEqual("server1");
done();
} catch (e) {
done(e);
}
});
configApiService.get.mockRejectedValueOnce(new Error("Unable to fetch"));
configService.triggerServerConfigFetch();
configApiService.get.mockResolvedValueOnce(serverConfigResponseFactory("server1"));
configService.triggerServerConfigFetch();
});
describe("Fetches config from server", () => {
beforeEach(() => { beforeEach(() => {
stateService.getServerConfig.mockResolvedValueOnce(null); environmentService.environment$ = of(environmentFactory(activeApiUrl));
sut = new DefaultConfigService(
configApiService,
environmentService,
logService,
stateProvider,
);
}); });
it.each<number | jest.DoneCallback>([1, 2, 3])( describe("serverConfig$", () => {
"after %p hour/s", it.each([{}, null])("handles null stored state", async (globalTestState) => {
(hours: number, done: jest.DoneCallback) => { globalState.stateSubject.next(globalTestState);
const configService = configServiceFactory(); userState.nextState(null);
await expect(firstValueFrom(sut.serverConfig$)).resolves.not.toThrow();
});
// skip previous hours (if any) describe.each(["stale", "missing"])("%s config", (configStateDescription) => {
configService.serverConfig$.pipe(skip(hours - 1), take(1)).subscribe((config) => { const userStored =
try { configStateDescription === "missing"
expect(config.gitHash).toEqual("server" + hours); ? null
expect(configApiService.get).toHaveBeenCalledTimes(hours); : serverConfigFactory(activeApiUrl + userId, tooOld);
done(); const globalStored =
} catch (e) { configStateDescription === "missing"
done(e); ? {}
} : {
[activeApiUrl]: serverConfigFactory(activeApiUrl, tooOld),
};
beforeEach(() => {
globalState.stateSubject.next(globalStored);
userState.nextState(userStored);
}); });
const oneHourInMs = 1000 * 3600; // sanity check
jest.advanceTimersByTime(oneHourInMs * hours + 1); test("authed and unauthorized state are different", () => {
}, expect(globalStored[activeApiUrl]).not.toEqual(userStored);
); });
it("when environment URLs change", (done) => { describe("fail to fetch", () => {
const configService = configServiceFactory(); beforeEach(() => {
configApiService.get.mockRejectedValue(new Error("Unable to fetch"));
});
configService.serverConfig$.pipe(take(1)).subscribe((config) => { it("uses storage as fallback", async () => {
try { const actual = await firstValueFrom(sut.serverConfig$);
expect(config.gitHash).toEqual("server1"); expect(actual).toEqual(activeUserId ? userStored : globalStored[activeApiUrl]);
done(); expect(configApiService.get).toHaveBeenCalledTimes(1);
} catch (e) { });
done(e);
} it("does not error out when fetch fails", async () => {
await expect(firstValueFrom(sut.serverConfig$)).resolves.not.toThrow();
expect(configApiService.get).toHaveBeenCalledTimes(1);
});
it("logs an error when unable to fetch", async () => {
await firstValueFrom(sut.serverConfig$);
expect(logService.error).toHaveBeenCalledWith(
`Unable to fetch ServerConfig from ${activeApiUrl}: Unable to fetch`,
);
});
});
describe("fetch success", () => {
const response = serverConfigResponseFactory();
const newConfig = new ServerConfig(new ServerConfigData(response));
it("should be a new config", async () => {
expect(newConfig).not.toEqual(activeUserId ? userStored : globalStored[activeApiUrl]);
});
it("fetches config from server when it's older than an hour", async () => {
await firstValueFrom(sut.serverConfig$);
expect(configApiService.get).toHaveBeenCalledTimes(1);
});
it("returns the updated config", async () => {
configApiService.get.mockResolvedValue(response);
const actual = await firstValueFrom(sut.serverConfig$);
// This is the time the response is converted to a config
expect(actual.utcDate).toAlmostEqual(newConfig.utcDate, 1000);
delete actual.utcDate;
delete newConfig.utcDate;
expect(actual).toEqual(newConfig);
});
});
}); });
replaySubject.next(null); describe("fresh configuration", () => {
}); const userStored = serverConfigFactory(activeApiUrl + userId);
const globalStored = {
[activeApiUrl]: serverConfigFactory(activeApiUrl),
};
beforeEach(() => {
globalState.stateSubject.next(globalStored);
userState.nextState(userStored);
});
it("does not fetch from server", async () => {
await firstValueFrom(sut.serverConfig$);
it("when triggerServerConfigFetch() is called", (done) => { expect(configApiService.get).not.toHaveBeenCalled();
const configService = configServiceFactory(); });
configService.serverConfig$.pipe(take(1)).subscribe((config) => { it("uses stored value", async () => {
try { const actual = await firstValueFrom(sut.serverConfig$);
expect(config.gitHash).toEqual("server1"); expect(actual).toEqual(activeUserId ? userStored : globalStored[activeApiUrl]);
done(); });
} catch (e) {
done(e); it("does not complete after emit", async () => {
} const emissions = [];
const subscription = sut.serverConfig$.subscribe((v) => emissions.push(v));
await awaitAsync();
expect(emissions.length).toBe(1);
expect(subscription.closed).toBe(false);
});
}); });
configService.triggerServerConfigFetch();
}); });
}); });
it("Saves server config to storage when the user is logged in", (done) => { describe("environment change", () => {
stateService.getServerConfig.mockResolvedValueOnce(null); let sut: DefaultConfigService;
authService.getAuthStatus.mockResolvedValue(AuthenticationStatus.Locked); let environmentSubject: Subject<Environment>;
const configService = configServiceFactory();
configService.serverConfig$.pipe(take(1)).subscribe(() => { beforeAll(async () => {
try { // updating environment with an active account is undefined behavior
expect(stateService.setServerConfig).toHaveBeenCalledWith( await accountService.switchAccount(null);
expect.objectContaining({ gitHash: "server1" }),
);
done();
} catch (e) {
done(e);
}
}); });
configService.triggerServerConfigFetch(); beforeEach(() => {
environmentSubject = new Subject<Environment>();
environmentService.environment$ = environmentSubject;
sut = new DefaultConfigService(
configApiService,
environmentService,
logService,
stateProvider,
);
});
describe("serverConfig$", () => {
it("emits a new config when the environment changes", async () => {
const globalStored = {
[apiUrl(0)]: serverConfigFactory(apiUrl(0)),
[apiUrl(1)]: serverConfigFactory(apiUrl(1)),
};
globalState.stateSubject.next(globalStored);
const spy = subscribeTo(sut.serverConfig$);
environmentSubject.next(environmentFactory(apiUrl(0)));
environmentSubject.next(environmentFactory(apiUrl(1)));
const expected = [globalStored[apiUrl(0)], globalStored[apiUrl(1)]];
const actual = await spy.pauseUntilReceived(2);
expect(actual.length).toBe(2);
// validate dates this is done separately because the dates are created when ServerConfig is initialized
expect(actual[0].utcDate).toAlmostEqual(expected[0].utcDate, 1000);
expect(actual[1].utcDate).toAlmostEqual(expected[1].utcDate, 1000);
delete actual[0].utcDate;
delete actual[1].utcDate;
delete expected[0].utcDate;
delete expected[1].utcDate;
expect(actual).toEqual(expected);
spy.unsubscribe();
});
});
}); });
}); });
function serverConfigDataFactory(gitHash: string) { function apiUrl(count: number) {
return new ServerConfigData(serverConfigResponseFactory(gitHash)); return `https://api${count}.test.com`;
} }
function serverConfigResponseFactory(gitHash: string) { function serverConfigFactory(hash: string, date: Date = new Date()) {
const config = new ServerConfig(serverConfigDataFactory(hash));
config.utcDate = date;
return config;
}
function serverConfigDataFactory(hash?: string) {
return new ServerConfigData(serverConfigResponseFactory(hash));
}
function serverConfigResponseFactory(hash?: string) {
return new ServerConfigResponse({ return new ServerConfigResponse({
version: "myConfigVersion", version: "myConfigVersion",
gitHash: gitHash, gitHash: hash ?? Utils.newGuid(), // Use optional git hash to store uniqueness value
server: new ThirdPartyServerConfigResponse({ server: new ThirdPartyServerConfigResponse({
name: "myThirdPartyServer", name: "myThirdPartyServer",
url: "www.example.com", url: "www.example.com",
@ -209,3 +273,9 @@ function serverConfigResponseFactory(gitHash: string) {
}, },
}); });
} }
function environmentFactory(apiUrl: string) {
return {
getApiUrl: () => apiUrl,
} as Environment;
}

View File

@ -1,130 +0,0 @@
import {
ReplaySubject,
Subject,
catchError,
concatMap,
defer,
delayWhen,
firstValueFrom,
map,
merge,
timer,
} from "rxjs";
import { SemVer } from "semver";
import { AuthService } from "../../../auth/abstractions/auth.service";
import { AuthenticationStatus } from "../../../auth/enums/authentication-status";
import { FeatureFlag, FeatureFlagValue } from "../../../enums/feature-flag.enum";
import { ConfigApiServiceAbstraction } from "../../abstractions/config/config-api.service.abstraction";
import { ConfigServiceAbstraction } from "../../abstractions/config/config.service.abstraction";
import { ServerConfig } from "../../abstractions/config/server-config";
import { EnvironmentService, Region } from "../../abstractions/environment.service";
import { LogService } from "../../abstractions/log.service";
import { StateService } from "../../abstractions/state.service";
import { ServerConfigData } from "../../models/data/server-config.data";
import { StateProvider } from "../../state";
const ONE_HOUR_IN_MILLISECONDS = 1000 * 3600;
export class ConfigService implements ConfigServiceAbstraction {
private inited = false;
protected _serverConfig = new ReplaySubject<ServerConfig | null>(1);
serverConfig$ = this._serverConfig.asObservable();
private _forceFetchConfig = new Subject<void>();
protected refreshTimer$ = timer(ONE_HOUR_IN_MILLISECONDS, ONE_HOUR_IN_MILLISECONDS); // after 1 hour, then every hour
cloudRegion$ = this.serverConfig$.pipe(
map((config) => config?.environment?.cloudRegion ?? Region.US),
);
constructor(
private stateService: StateService,
private configApiService: ConfigApiServiceAbstraction,
private authService: AuthService,
private environmentService: EnvironmentService,
private logService: LogService,
private stateProvider: StateProvider,
// Used to avoid duplicate subscriptions, e.g. in browser between the background and popup
private subscribe = true,
) {}
init() {
if (!this.subscribe || this.inited) {
return;
}
const latestServerConfig$ = defer(() => this.configApiService.get()).pipe(
map((response) => new ServerConfigData(response)),
delayWhen((data) => this.saveConfig(data)),
catchError((e: unknown) => {
// fall back to stored ServerConfig (if any)
this.logService.error("Unable to fetch ServerConfig: " + (e as Error)?.message);
return this.stateService.getServerConfig();
}),
);
// If you need to fetch a new config when an event occurs, add an observable that emits on that event here
merge(
this.refreshTimer$, // an overridable interval
this.environmentService.environment$, // when environment URLs change (including when app is started)
this._forceFetchConfig, // manual
)
.pipe(
concatMap(() => latestServerConfig$),
map((data) => (data == null ? null : new ServerConfig(data))),
)
.subscribe((config) => this._serverConfig.next(config));
this.inited = true;
}
getFeatureFlag$<T extends FeatureFlagValue>(key: FeatureFlag, defaultValue?: T) {
return this.serverConfig$.pipe(
map((serverConfig) => {
if (serverConfig?.featureStates == null || serverConfig.featureStates[key] == null) {
return defaultValue;
}
return serverConfig.featureStates[key] as T;
}),
);
}
async getFeatureFlag<T extends FeatureFlagValue>(key: FeatureFlag, defaultValue?: T) {
return await firstValueFrom(this.getFeatureFlag$(key, defaultValue));
}
triggerServerConfigFetch() {
this._forceFetchConfig.next();
}
private async saveConfig(data: ServerConfigData) {
if ((await this.authService.getAuthStatus()) === AuthenticationStatus.LoggedOut) {
return;
}
const userId = await firstValueFrom(this.stateProvider.activeUserId$);
await this.stateService.setServerConfig(data);
await this.environmentService.setCloudRegion(userId, data.environment?.cloudRegion);
}
/**
* Verifies whether the server version meets the minimum required version
* @param minimumRequiredServerVersion The minimum version required
* @returns True if the server version is greater than or equal to the minimum required version
*/
checkServerMeetsVersionRequirement$(minimumRequiredServerVersion: SemVer) {
return this.serverConfig$.pipe(
map((serverConfig) => {
if (serverConfig == null) {
return false;
}
const serverVersion = new SemVer(serverConfig.version);
return serverVersion.compare(minimumRequiredServerVersion) >= 0;
}),
);
}
}

View File

@ -0,0 +1,177 @@
import {
NEVER,
Observable,
Subject,
combineLatest,
firstValueFrom,
map,
mergeWith,
of,
shareReplay,
switchMap,
tap,
} from "rxjs";
import { SemVer } from "semver";
import { FeatureFlag, FeatureFlagValue } from "../../../enums/feature-flag.enum";
import { UserId } from "../../../types/guid";
import { ConfigApiServiceAbstraction } from "../../abstractions/config/config-api.service.abstraction";
import { ConfigService } from "../../abstractions/config/config.service";
import { ServerConfig } from "../../abstractions/config/server-config";
import { EnvironmentService, Region } from "../../abstractions/environment.service";
import { LogService } from "../../abstractions/log.service";
import { ServerConfigData } from "../../models/data/server-config.data";
import { CONFIG_DISK, KeyDefinition, StateProvider, UserKeyDefinition } from "../../state";
export const RETRIEVAL_INTERVAL = 3_600_000; // 1 hour
export type ApiUrl = string;
export const USER_SERVER_CONFIG = new UserKeyDefinition<ServerConfig>(CONFIG_DISK, "serverConfig", {
deserializer: (data) => (data == null ? null : ServerConfig.fromJSON(data)),
clearOn: ["logout"],
});
// TODO MDG: When to clean these up?
export const GLOBAL_SERVER_CONFIGURATIONS = KeyDefinition.record<ServerConfig, ApiUrl>(
CONFIG_DISK,
"byServer",
{
deserializer: (data) => (data == null ? null : ServerConfig.fromJSON(data)),
},
);
// FIXME: currently we are limited to api requests for active users. Update to accept a UserId and APIUrl once ApiService supports it.
export class DefaultConfigService implements ConfigService {
private failedFetchFallbackSubject = new Subject<ServerConfig>();
serverConfig$: Observable<ServerConfig>;
cloudRegion$: Observable<Region>;
constructor(
private configApiService: ConfigApiServiceAbstraction,
private environmentService: EnvironmentService,
private logService: LogService,
private stateProvider: StateProvider,
) {
const apiUrl$ = this.environmentService.environment$.pipe(
map((environment) => environment.getApiUrl()),
);
this.serverConfig$ = combineLatest([this.stateProvider.activeUserId$, apiUrl$]).pipe(
switchMap(([userId, apiUrl]) => {
const config$ =
userId == null ? this.globalConfigFor$(apiUrl) : this.userConfigFor$(userId);
return config$.pipe(map((config) => [config, userId, apiUrl] as const));
}),
tap(async (rec) => {
const [existingConfig, userId, apiUrl] = rec;
// Grab new config if older retrieval interval
if (!existingConfig || this.olderThanRetrievalInterval(existingConfig.utcDate)) {
await this.renewConfig(existingConfig, userId, apiUrl);
}
}),
switchMap(([existingConfig]) => {
// If we needed to fetch, stop this emit, we'll get a new one after update
// This is split up with the above tap because we need to return an observable from a failed promise,
// which isn't very doable since promises are converted to observables in switchMap
if (!existingConfig || this.olderThanRetrievalInterval(existingConfig.utcDate)) {
return NEVER;
}
return of(existingConfig);
}),
// If fetch fails, we'll emit on this subject to fallback to the existing config
mergeWith(this.failedFetchFallbackSubject),
shareReplay({ refCount: true, bufferSize: 1 }),
);
this.cloudRegion$ = this.serverConfig$.pipe(
map((config) => config?.environment?.cloudRegion ?? Region.US),
);
}
getFeatureFlag$<T extends FeatureFlagValue>(key: FeatureFlag, defaultValue?: T) {
return this.serverConfig$.pipe(
map((serverConfig) => {
if (serverConfig?.featureStates == null || serverConfig.featureStates[key] == null) {
return defaultValue;
}
return serverConfig.featureStates[key] as T;
}),
);
}
async getFeatureFlag<T extends FeatureFlagValue>(key: FeatureFlag, defaultValue?: T) {
return await firstValueFrom(this.getFeatureFlag$(key, defaultValue));
}
checkServerMeetsVersionRequirement$(minimumRequiredServerVersion: SemVer) {
return this.serverConfig$.pipe(
map((serverConfig) => {
if (serverConfig == null) {
return false;
}
const serverVersion = new SemVer(serverConfig.version);
return serverVersion.compare(minimumRequiredServerVersion) >= 0;
}),
);
}
async ensureConfigFetched() {
// Triggering a retrieval for the given user ensures that the config is less than RETRIEVAL_INTERVAL old
await firstValueFrom(this.serverConfig$);
}
private olderThanRetrievalInterval(date: Date) {
return new Date().getTime() - date.getTime() > RETRIEVAL_INTERVAL;
}
// Updates the on-disk configuration with a newly retrieved configuration
private async renewConfig(
existingConfig: ServerConfig,
userId: UserId,
apiUrl: string,
): Promise<void> {
try {
const response = await this.configApiService.get(userId);
const newConfig = new ServerConfig(new ServerConfigData(response));
// Update the environment region
if (
newConfig?.environment?.cloudRegion != null &&
existingConfig?.environment?.cloudRegion != newConfig.environment.cloudRegion
) {
// Null userId sets global, otherwise sets to the given user
await this.environmentService.setCloudRegion(userId, newConfig?.environment?.cloudRegion);
}
if (userId == null) {
// update global state with new pulled config
await this.stateProvider.getGlobal(GLOBAL_SERVER_CONFIGURATIONS).update((configs) => {
return { ...configs, [apiUrl]: newConfig };
});
} else {
// update state with new pulled config
await this.stateProvider.setUserState(USER_SERVER_CONFIG, newConfig, userId);
}
} catch (e) {
// mutate error to be handled by catchError
this.logService.error(
`Unable to fetch ServerConfig from ${apiUrl}: ${(e as Error)?.message}`,
);
// Emit the existing config
this.failedFetchFallbackSubject.next(existingConfig);
}
}
private globalConfigFor$(apiUrl: string): Observable<ServerConfig> {
return this.stateProvider
.getGlobal(GLOBAL_SERVER_CONFIGURATIONS)
.state$.pipe(map((configs) => configs?.[apiUrl]));
}
private userConfigFor$(userId: UserId): Observable<ServerConfig> {
return this.stateProvider.getUser(userId, USER_SERVER_CONFIG).state$;
}
}

View File

@ -32,7 +32,6 @@ import {
import { HtmlStorageLocation, KdfType, StorageLocation } from "../enums"; import { HtmlStorageLocation, KdfType, StorageLocation } from "../enums";
import { StateFactory } from "../factories/state-factory"; import { StateFactory } from "../factories/state-factory";
import { Utils } from "../misc/utils"; import { Utils } from "../misc/utils";
import { ServerConfigData } from "../models/data/server-config.data";
import { Account, AccountData, AccountSettings } from "../models/domain/account"; import { Account, AccountData, AccountSettings } from "../models/domain/account";
import { EncString } from "../models/domain/enc-string"; import { EncString } from "../models/domain/enc-string";
import { GlobalState } from "../models/domain/global-state"; import { GlobalState } from "../models/domain/global-state";
@ -1377,23 +1376,6 @@ export class StateService<
); );
} }
async setServerConfig(value: ServerConfigData, options?: StorageOptions): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()),
);
account.settings.serverConfig = value;
return await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()),
);
}
async getServerConfig(options: StorageOptions): Promise<ServerConfigData> {
return (
await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()))
)?.settings?.serverConfig;
}
async getDeepLinkRedirectUrl(options?: StorageOptions): Promise<string> { async getDeepLinkRedirectUrl(options?: StorageOptions): Promise<string> {
return ( return (
await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions())) await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))

View File

@ -73,6 +73,9 @@ export const APPLICATION_ID_DISK = new StateDefinition("applicationId", "disk",
}); });
export const BIOMETRIC_SETTINGS_DISK = new StateDefinition("biometricSettings", "disk"); export const BIOMETRIC_SETTINGS_DISK = new StateDefinition("biometricSettings", "disk");
export const CLEAR_EVENT_DISK = new StateDefinition("clearEvent", "disk"); export const CLEAR_EVENT_DISK = new StateDefinition("clearEvent", "disk");
export const CONFIG_DISK = new StateDefinition("config", "disk", {
web: "disk-local",
});
export const CRYPTO_DISK = new StateDefinition("crypto", "disk"); export const CRYPTO_DISK = new StateDefinition("crypto", "disk");
export const CRYPTO_MEMORY = new StateDefinition("crypto", "memory"); export const CRYPTO_MEMORY = new StateDefinition("crypto", "memory");
export const DESKTOP_SETTINGS_DISK = new StateDefinition("desktopSettings", "disk"); export const DESKTOP_SETTINGS_DISK = new StateDefinition("desktopSettings", "disk");

View File

@ -44,6 +44,7 @@ import { MergeEnvironmentState } from "./migrations/45-merge-environment-state";
import { DeleteBiometricPromptCancelledData } from "./migrations/46-delete-orphaned-biometric-prompt-data"; import { DeleteBiometricPromptCancelledData } from "./migrations/46-delete-orphaned-biometric-prompt-data";
import { MoveDesktopSettingsMigrator } from "./migrations/47-move-desktop-settings"; import { MoveDesktopSettingsMigrator } from "./migrations/47-move-desktop-settings";
import { MoveDdgToStateProviderMigrator } from "./migrations/48-move-ddg-to-state-provider"; import { MoveDdgToStateProviderMigrator } from "./migrations/48-move-ddg-to-state-provider";
import { AccountServerConfigMigrator } from "./migrations/49-move-account-server-configs";
import { AddKeyTypeToOrgKeysMigrator } from "./migrations/5-add-key-type-to-org-keys"; import { AddKeyTypeToOrgKeysMigrator } from "./migrations/5-add-key-type-to-org-keys";
import { RemoveLegacyEtmKeyMigrator } from "./migrations/6-remove-legacy-etm-key"; import { RemoveLegacyEtmKeyMigrator } from "./migrations/6-remove-legacy-etm-key";
import { MoveBiometricAutoPromptToAccount } from "./migrations/7-move-biometric-auto-prompt-to-account"; import { MoveBiometricAutoPromptToAccount } from "./migrations/7-move-biometric-auto-prompt-to-account";
@ -52,8 +53,7 @@ import { MoveBrowserSettingsToGlobal } from "./migrations/9-move-browser-setting
import { MinVersionMigrator } from "./migrations/min-version"; import { MinVersionMigrator } from "./migrations/min-version";
export const MIN_VERSION = 3; export const MIN_VERSION = 3;
export const CURRENT_VERSION = 48; export const CURRENT_VERSION = 49;
export type MinVersion = typeof MIN_VERSION; export type MinVersion = typeof MIN_VERSION;
export function createMigrationBuilder() { export function createMigrationBuilder() {
@ -103,7 +103,8 @@ export function createMigrationBuilder() {
.with(MergeEnvironmentState, 44, 45) .with(MergeEnvironmentState, 44, 45)
.with(DeleteBiometricPromptCancelledData, 45, 46) .with(DeleteBiometricPromptCancelledData, 45, 46)
.with(MoveDesktopSettingsMigrator, 46, 47) .with(MoveDesktopSettingsMigrator, 46, 47)
.with(MoveDdgToStateProviderMigrator, 47, CURRENT_VERSION); .with(MoveDdgToStateProviderMigrator, 47, 48)
.with(AccountServerConfigMigrator, 48, CURRENT_VERSION);
} }
export async function currentVersion( export async function currentVersion(

View File

@ -0,0 +1,112 @@
import { runMigrator } from "../migration-helper.spec";
import { AccountServerConfigMigrator } from "./49-move-account-server-configs";
describe("AccountServerConfigMigrator", () => {
const migrator = new AccountServerConfigMigrator(48, 49);
describe("all data", () => {
function toMigrate() {
return {
authenticatedAccounts: ["user1", "user2"],
user1: {
settings: {
serverConfig: {
config: "user1 server config",
},
},
},
user2: {
settings: {
serverConfig: {
config: "user2 server config",
},
},
},
};
}
function migrated() {
return {
authenticatedAccounts: ["user1", "user2"],
user1: {
settings: {},
},
user2: {
settings: {},
},
user_user1_config_serverConfig: {
config: "user1 server config",
},
user_user2_config_serverConfig: {
config: "user2 server config",
},
};
}
function rolledBack(previous: object) {
return {
...previous,
user_user1_config_serverConfig: null as unknown,
user_user2_config_serverConfig: null as unknown,
};
}
it("migrates", async () => {
const output = await runMigrator(migrator, toMigrate(), "migrate");
expect(output).toEqual(migrated());
});
it("rolls back", async () => {
const output = await runMigrator(migrator, migrated(), "rollback");
expect(output).toEqual(rolledBack(toMigrate()));
});
});
describe("missing parts", () => {
function toMigrate() {
return {
authenticatedAccounts: ["user1", "user2"],
user1: {
settings: {
serverConfig: {
config: "user1 server config",
},
},
},
user2: null as unknown,
};
}
function migrated() {
return {
authenticatedAccounts: ["user1", "user2"],
user1: {
settings: {},
},
user2: null as unknown,
user_user1_config_serverConfig: {
config: "user1 server config",
},
};
}
function rollback(previous: object) {
return {
...previous,
user_user1_config_serverConfig: null as unknown,
};
}
it("migrates", async () => {
const output = await runMigrator(migrator, toMigrate(), "migrate");
expect(output).toEqual(migrated());
});
it("rolls back", async () => {
const output = await runMigrator(migrator, migrated(), "rollback");
expect(output).toEqual(rollback(toMigrate()));
});
});
});

View File

@ -0,0 +1,51 @@
import { KeyDefinitionLike, MigrationHelper, StateDefinitionLike } from "../migration-helper";
import { Migrator } from "../migrator";
const CONFIG_DISK: StateDefinitionLike = { name: "config" };
export const USER_SERVER_CONFIG: KeyDefinitionLike = {
stateDefinition: CONFIG_DISK,
key: "serverConfig",
};
// Note: no need to migrate global configs, they don't currently exist
type ExpectedAccountType = {
settings?: {
serverConfig?: unknown;
};
};
export class AccountServerConfigMigrator extends Migrator<48, 49> {
async migrate(helper: MigrationHelper): Promise<void> {
const accounts = await helper.getAccounts<ExpectedAccountType>();
async function migrateAccount(userId: string, account: ExpectedAccountType): Promise<void> {
if (account?.settings?.serverConfig != null) {
await helper.setToUser(userId, USER_SERVER_CONFIG, account.settings.serverConfig);
delete account.settings.serverConfig;
await helper.set(userId, account);
}
}
await Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
}
async rollback(helper: MigrationHelper): Promise<void> {
const accounts = await helper.getAccounts<ExpectedAccountType>();
async function rollbackAccount(userId: string, account: ExpectedAccountType): Promise<void> {
const serverConfig = await helper.getFromUser(userId, USER_SERVER_CONFIG);
if (serverConfig) {
account ??= {};
account.settings ??= {};
account.settings.serverConfig = serverConfig;
await helper.setToUser(userId, USER_SERVER_CONFIG, null);
await helper.set(userId, account);
}
}
await Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
}
}

View File

@ -7,7 +7,7 @@ import { SearchService } from "../../abstractions/search.service";
import { AutofillSettingsService } from "../../autofill/services/autofill-settings.service"; import { AutofillSettingsService } from "../../autofill/services/autofill-settings.service";
import { DomainSettingsService } from "../../autofill/services/domain-settings.service"; import { DomainSettingsService } from "../../autofill/services/domain-settings.service";
import { UriMatchStrategy } from "../../models/domain/domain-service"; import { UriMatchStrategy } from "../../models/domain/domain-service";
import { ConfigServiceAbstraction } from "../../platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "../../platform/abstractions/config/config.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { CryptoService } from "../../platform/abstractions/crypto.service";
import { EncryptService } from "../../platform/abstractions/encrypt.service"; import { EncryptService } from "../../platform/abstractions/encrypt.service";
import { I18nService } from "../../platform/abstractions/i18n.service"; import { I18nService } from "../../platform/abstractions/i18n.service";
@ -108,7 +108,7 @@ describe("Cipher Service", () => {
const i18nService = mock<I18nService>(); const i18nService = mock<I18nService>();
const searchService = mock<SearchService>(); const searchService = mock<SearchService>();
const encryptService = mock<EncryptService>(); const encryptService = mock<EncryptService>();
const configService = mock<ConfigServiceAbstraction>(); const configService = mock<ConfigService>();
let cipherService: CipherService; let cipherService: CipherService;
let cipherObj: Cipher; let cipherObj: Cipher;

View File

@ -9,7 +9,7 @@ import { UriMatchStrategySetting } from "../../models/domain/domain-service";
import { ErrorResponse } from "../../models/response/error.response"; import { ErrorResponse } from "../../models/response/error.response";
import { ListResponse } from "../../models/response/list.response"; import { ListResponse } from "../../models/response/list.response";
import { View } from "../../models/view/view"; import { View } from "../../models/view/view";
import { ConfigServiceAbstraction } from "../../platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "../../platform/abstractions/config/config.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { CryptoService } from "../../platform/abstractions/crypto.service";
import { EncryptService } from "../../platform/abstractions/encrypt.service"; import { EncryptService } from "../../platform/abstractions/encrypt.service";
import { I18nService } from "../../platform/abstractions/i18n.service"; import { I18nService } from "../../platform/abstractions/i18n.service";
@ -72,7 +72,7 @@ export class CipherService implements CipherServiceAbstraction {
private autofillSettingsService: AutofillSettingsServiceAbstraction, private autofillSettingsService: AutofillSettingsServiceAbstraction,
private encryptService: EncryptService, private encryptService: EncryptService,
private cipherFileUploadService: CipherFileUploadService, private cipherFileUploadService: CipherFileUploadService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
) {} ) {}
async getDecryptedCipherCache(): Promise<CipherView[]> { async getDecryptedCipherCache(): Promise<CipherView[]> {

View File

@ -4,7 +4,7 @@ import { of } from "rxjs";
import { AuthService } from "../../../auth/abstractions/auth.service"; import { AuthService } from "../../../auth/abstractions/auth.service";
import { AuthenticationStatus } from "../../../auth/enums/authentication-status"; import { AuthenticationStatus } from "../../../auth/enums/authentication-status";
import { DomainSettingsService } from "../../../autofill/services/domain-settings.service"; import { DomainSettingsService } from "../../../autofill/services/domain-settings.service";
import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "../../../platform/abstractions/config/config.service";
import { Utils } from "../../../platform/misc/utils"; import { Utils } from "../../../platform/misc/utils";
import { import {
Fido2AuthenticatorError, Fido2AuthenticatorError,
@ -30,7 +30,7 @@ const VaultUrl = "https://vault.bitwarden.com";
describe("FidoAuthenticatorService", () => { describe("FidoAuthenticatorService", () => {
let authenticator!: MockProxy<Fido2AuthenticatorService>; let authenticator!: MockProxy<Fido2AuthenticatorService>;
let configService!: MockProxy<ConfigServiceAbstraction>; let configService!: MockProxy<ConfigService>;
let authService!: MockProxy<AuthService>; let authService!: MockProxy<AuthService>;
let vaultSettingsService: MockProxy<VaultSettingsService>; let vaultSettingsService: MockProxy<VaultSettingsService>;
let domainSettingsService: MockProxy<DomainSettingsService>; let domainSettingsService: MockProxy<DomainSettingsService>;
@ -39,7 +39,7 @@ describe("FidoAuthenticatorService", () => {
beforeEach(async () => { beforeEach(async () => {
authenticator = mock<Fido2AuthenticatorService>(); authenticator = mock<Fido2AuthenticatorService>();
configService = mock<ConfigServiceAbstraction>(); configService = mock<ConfigService>();
authService = mock<AuthService>(); authService = mock<AuthService>();
vaultSettingsService = mock<VaultSettingsService>(); vaultSettingsService = mock<VaultSettingsService>();
domainSettingsService = mock<DomainSettingsService>(); domainSettingsService = mock<DomainSettingsService>();

View File

@ -4,7 +4,7 @@ import { parse } from "tldts";
import { AuthService } from "../../../auth/abstractions/auth.service"; import { AuthService } from "../../../auth/abstractions/auth.service";
import { AuthenticationStatus } from "../../../auth/enums/authentication-status"; import { AuthenticationStatus } from "../../../auth/enums/authentication-status";
import { DomainSettingsService } from "../../../autofill/services/domain-settings.service"; import { DomainSettingsService } from "../../../autofill/services/domain-settings.service";
import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction"; import { ConfigService } from "../../../platform/abstractions/config/config.service";
import { LogService } from "../../../platform/abstractions/log.service"; import { LogService } from "../../../platform/abstractions/log.service";
import { Utils } from "../../../platform/misc/utils"; import { Utils } from "../../../platform/misc/utils";
import { import {
@ -40,7 +40,7 @@ import { Fido2Utils } from "./fido2-utils";
export class Fido2ClientService implements Fido2ClientServiceAbstraction { export class Fido2ClientService implements Fido2ClientServiceAbstraction {
constructor( constructor(
private authenticator: Fido2AuthenticatorService, private authenticator: Fido2AuthenticatorService,
private configService: ConfigServiceAbstraction, private configService: ConfigService,
private authService: AuthService, private authService: AuthService,
private vaultSettingsService: VaultSettingsService, private vaultSettingsService: VaultSettingsService,
private domainSettingsService: DomainSettingsService, private domainSettingsService: DomainSettingsService,

View File

@ -1,6 +1,7 @@
import { webcrypto } from "crypto"; import { webcrypto } from "crypto";
import { toEqualBuffer } from "./spec"; import { toEqualBuffer } from "./spec";
import { toAlmostEqual } from "./spec/matchers/to-almost-equal";
Object.defineProperty(window, "crypto", { Object.defineProperty(window, "crypto", {
value: webcrypto, value: webcrypto,
@ -10,8 +11,15 @@ Object.defineProperty(window, "crypto", {
expect.extend({ expect.extend({
toEqualBuffer: toEqualBuffer, toEqualBuffer: toEqualBuffer,
toAlmostEqual: toAlmostEqual,
}); });
export interface CustomMatchers<R = unknown> { export interface CustomMatchers<R = unknown> {
toEqualBuffer(expected: Uint8Array | ArrayBuffer): R; toEqualBuffer(expected: Uint8Array | ArrayBuffer): R;
/**
* Matches the expected date within an optional ms precision
* @param expected The expected date
* @param msPrecision The optional precision in milliseconds
*/
toAlmostEqual(expected: Date, msPrecision?: number): R;
} }