1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 08:13:42 +00:00

[PM-24677] Slim StateService down so it can be moved to state lib (#16021)

* Slim StateService down so it can be moved to state lib

* Fix accidental import changes

* Add `switchAccount` assertion

* Needs to use mock
This commit is contained in:
Justin Baur
2025-08-18 12:37:25 -04:00
committed by GitHub
parent ea305a0f71
commit 939fd402c3
49 changed files with 286 additions and 1274 deletions

View File

@@ -129,7 +129,7 @@ export abstract class BaseProgram {
if (!userId) {
fail();
}
const authed = await this.serviceContainer.stateService.getIsAuthenticated({ userId });
const authed = await firstValueFrom(this.serviceContainer.tokenService.hasAccessToken$(userId));
if (!authed) {
fail();
}

View File

@@ -107,7 +107,8 @@ export class OssServeConfigurator {
);
this.generateCommand = new GenerateCommand(
this.serviceContainer.passwordGenerationService,
this.serviceContainer.stateService,
this.serviceContainer.tokenService,
this.serviceContainer.accountService,
);
this.syncCommand = new SyncCommand(this.serviceContainer.syncService);
this.statusCommand = new StatusCommand(
@@ -417,14 +418,18 @@ export class OssServeConfigurator {
}
protected async errorIfLocked(res: koa.Response) {
const authed = await this.serviceContainer.stateService.getIsAuthenticated();
const userId = await firstValueFrom(
this.serviceContainer.accountService.activeAccount$.pipe(map((account) => account?.id)),
);
const authed =
userId != null ||
(await firstValueFrom(this.serviceContainer.tokenService.hasAccessToken$(userId)));
if (!authed) {
this.processResponse(res, Response.error("You are not logged in."));
return true;
}
const userId = await firstValueFrom(
this.serviceContainer.accountService.activeAccount$.pipe(map((account) => account?.id)),
);
if (await this.serviceContainer.keyService.hasUserKey(userId)) {
return false;
}

View File

@@ -2,7 +2,7 @@
// @ts-strict-ignore
import * as chalk from "chalk";
import { program, Command, OptionValues } from "commander";
import { firstValueFrom } from "rxjs";
import { firstValueFrom, of, switchMap } from "rxjs";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
@@ -129,7 +129,17 @@ export class Program extends BaseProgram {
"Path to a file containing your password as its first line",
)
.option("--check", "Check login status.", async () => {
const authed = await this.serviceContainer.stateService.getIsAuthenticated();
const authed = await firstValueFrom(
this.serviceContainer.accountService.activeAccount$.pipe(
switchMap((account) => {
if (account == null) {
return of(false);
}
return this.serviceContainer.tokenService.hasAccessToken$(account.id);
}),
),
);
if (authed) {
const res = new MessageResponse("You are logged in!", null);
this.processResponse(Response.success(res), true);
@@ -350,7 +360,8 @@ export class Program extends BaseProgram {
.action(async (options) => {
const command = new GenerateCommand(
this.serviceContainer.passwordGenerationService,
this.serviceContainer.stateService,
this.serviceContainer.tokenService,
this.serviceContainer.accountService,
);
const response = await command.run(options);
this.processResponse(response);

View File

@@ -88,10 +88,7 @@ import {
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
import { KeySuffixOptions, LogLevelType } from "@bitwarden/common/platform/enums";
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
import { MessageSender } from "@bitwarden/common/platform/messaging";
import { Account } from "@bitwarden/common/platform/models/domain/account";
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
import {
TaskSchedulerService,
DefaultTaskSchedulerService,
@@ -108,16 +105,17 @@ import { MigrationRunner } from "@bitwarden/common/platform/services/migration-r
import { DefaultSdkClientFactory } from "@bitwarden/common/platform/services/sdk/default-sdk-client-factory";
import { DefaultSdkService } from "@bitwarden/common/platform/services/sdk/default-sdk.service";
import { NoopSdkClientFactory } from "@bitwarden/common/platform/services/sdk/noop-sdk-client-factory";
import { StateService } from "@bitwarden/common/platform/services/state.service";
import { StorageServiceProvider } from "@bitwarden/common/platform/services/storage-service.provider";
import { UserAutoUnlockKeyService } from "@bitwarden/common/platform/services/user-auto-unlock-key.service";
import {
ActiveUserStateProvider,
DefaultStateService,
DerivedStateProvider,
GlobalStateProvider,
SingleUserStateProvider,
StateEventRunnerService,
StateProvider,
StateService,
} from "@bitwarden/common/platform/state";
/* eslint-disable import/no-restricted-paths -- We need the implementation to inject, but generally these should not be accessed */
import { DefaultActiveUserStateProvider } from "@bitwarden/common/platform/state/implementations/default-active-user-state.provider";
@@ -212,6 +210,7 @@ export class ServiceContainer {
secureStorageService: NodeEnvSecureStorageService;
memoryStorageService: MemoryStorageService;
memoryStorageForStateProviders: MemoryStorageServiceForStateProviders;
migrationRunner: MigrationRunner;
i18nService: I18nService;
platformUtilsService: CliPlatformUtilsService;
keyService: KeyService;
@@ -379,8 +378,10 @@ export class ServiceContainer {
this.singleUserStateProvider,
);
const activeUserAccessor = new DefaultActiveUserAccessor(this.accountService);
this.activeUserStateProvider = new DefaultActiveUserStateProvider(
new DefaultActiveUserAccessor(this.accountService),
activeUserAccessor,
this.singleUserStateProvider,
);
@@ -412,23 +413,17 @@ export class ServiceContainer {
logoutCallback,
);
const migrationRunner = new MigrationRunner(
this.migrationRunner = new MigrationRunner(
this.storageService,
this.logService,
new MigrationBuilderService(),
ClientType.Cli,
);
this.stateService = new StateService(
this.stateService = new DefaultStateService(
this.storageService,
this.secureStorageService,
this.memoryStorageService,
this.logService,
new StateFactory(GlobalState, Account),
this.accountService,
this.environmentService,
this.tokenService,
migrationRunner,
activeUserAccessor,
);
this.kdfConfigService = new DefaultKdfConfigService(this.stateProvider);
@@ -713,7 +708,6 @@ export class ServiceContainer {
this.apiService,
this.i18nService,
this.searchService,
this.stateService,
this.autofillSettingsService,
this.encryptService,
this.cipherFileUploadService,
@@ -764,6 +758,7 @@ export class ServiceContainer {
this.messagingService,
this.searchService,
this.stateService,
this.tokenService,
this.authService,
this.vaultTimeoutSettingsService,
this.stateEventRunnerService,
@@ -790,7 +785,6 @@ export class ServiceContainer {
this.sendService,
this.logService,
this.keyConnectorService,
this.stateService,
this.providerService,
this.folderApiService,
this.organizationService,
@@ -903,7 +897,8 @@ export class ServiceContainer {
await this.stateEventRunnerService.handleEvent("logout", userId as UserId);
await this.stateService.clean();
await this.stateService.clean({ userId: userId });
await this.tokenService.clearAccessToken(userId);
await this.accountService.clean(userId as UserId);
await this.accountService.switchAccount(null);
process.env.BW_SESSION = undefined;
@@ -917,7 +912,8 @@ export class ServiceContainer {
await this.sdkLoadService.loadAndInit();
await this.storageService.init();
await this.stateService.init();
await this.migrationRunner.run();
this.containerService.attachToGlobal(global);
await this.i18nService.init();
this.twoFactorService.init();

View File

@@ -1,6 +1,9 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { firstValueFrom, of, switchMap } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import {
DefaultPasswordGenerationOptions,
DefaultPassphraseGenerationOptions,
@@ -17,7 +20,8 @@ import { CliUtils } from "../utils";
export class GenerateCommand {
constructor(
private passwordGenerationService: PasswordGenerationServiceAbstraction,
private stateService: StateService,
private tokenService: TokenService,
private accountService: AccountService,
) {}
async run(cmdOptions: Record<string, any>): Promise<Response> {
@@ -38,7 +42,18 @@ export class GenerateCommand {
ambiguous: !normalizedOptions.ambiguous,
};
const enforcedOptions = (await this.stateService.getIsAuthenticated())
const shouldEnforceOptions = await firstValueFrom(
this.accountService.activeAccount$.pipe(
switchMap((account) => {
if (account == null) {
return of(false);
}
return this.tokenService.hasAccessToken$(account.id);
}),
),
);
const enforcedOptions = shouldEnforceOptions
? (await this.passwordGenerationService.enforcePasswordGeneratorPoliciesOnOptions(options))[0]
: options;