1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 17:53:39 +00:00

Merge branch 'main' of github.com:bitwarden/clients

This commit is contained in:
gbubemismith
2024-05-15 11:27:30 -04:00
23 changed files with 1212 additions and 1040 deletions

View File

@@ -167,6 +167,11 @@ export class NativeMessagingBackground {
cancelButtonText: null, cancelButtonText: null,
type: "danger", type: "danger",
}); });
if (this.resolver) {
this.resolver(message);
}
break; break;
case "verifyFingerprint": { case "verifyFingerprint": {
if (this.sharedSecret == null) { if (this.sharedSecret == null) {

View File

@@ -33,6 +33,18 @@
"dist:mac": "npm run build:prod && npm run clean && npm run package:mac", "dist:mac": "npm run build:prod && npm run clean && npm run package:mac",
"dist:lin": "npm run build:prod && npm run clean && npm run package:lin", "dist:lin": "npm run build:prod && npm run clean && npm run package:lin",
"publish:npm": "npm run build:prod && npm publish --access public", "publish:npm": "npm run build:prod && npm publish --access public",
"build:bit": "webpack -c ../../bitwarden_license/bit-cli/webpack.config.js",
"build:bit:debug": "npm run build:bit && node --inspect ./build/bw.js",
"build:bit:watch": "webpack --watch -c ../../bitwarden_license/bit-cli/webpack.config.js",
"build:bit:prod": "cross-env NODE_ENV=production npm run build:bit",
"build:bit:prod:watch": "cross-env NODE_ENV=production npm run build:bit:watch",
"dist:bit": "npm run build:bit:prod && npm run clean && npm run package",
"dist:bit:win": "npm run build:bit:prod && npm run clean && npm run package:bit:win",
"dist:bit:mac": "npm run build:bit:prod && npm run clean && npm run package:bit:mac",
"dist:bit:lin": "npm run build:bit:prod && npm run clean && npm run package:bit:lin",
"package:bit:win": "pkg . --targets win-x64 --output ./dist/bit/windows/bw.exe",
"package:bit:mac": "pkg . --targets macos-x64 --output ./dist/bit/macos/bw",
"package:bit:lin": "pkg . --targets linux-x64 --output ./dist/bit/linux/bw",
"test": "jest", "test": "jest",
"test:watch": "jest --watch", "test:watch": "jest --watch",
"test:watch:all": "jest --watchAll" "test:watch:all": "jest --watchAll"

View File

@@ -1,788 +1,17 @@
import * as fs from "fs";
import * as path from "path";
import { program } from "commander"; import { program } from "commander";
import * as jsdom from "jsdom";
import { firstValueFrom } from "rxjs";
import { import { registerOssPrograms } from "./register-oss-programs";
InternalUserDecryptionOptionsServiceAbstraction, import { ServiceContainer } from "./service-container";
AuthRequestService,
LoginStrategyService,
LoginStrategyServiceAbstraction,
PinService,
PinServiceAbstraction,
UserDecryptionOptionsService,
} from "@bitwarden/auth/common";
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { ProviderApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider/provider-api.service.abstraction";
import { OrganizationApiService } from "@bitwarden/common/admin-console/services/organization/organization-api.service";
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
import { OrganizationUserServiceImplementation } from "@bitwarden/common/admin-console/services/organization-user/organization-user.service.implementation";
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
import { ProviderApiService } from "@bitwarden/common/admin-console/services/provider/provider-api.service";
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service";
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { KdfConfigService as KdfConfigServiceAbstraction } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust.service.implementation";
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
import { KdfConfigService } from "@bitwarden/common/auth/services/kdf-config.service";
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
import { MasterPasswordService } from "@bitwarden/common/auth/services/master-password/master-password.service";
import { TokenService } from "@bitwarden/common/auth/services/token.service";
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service";
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
import {
DefaultDomainSettingsService,
DomainSettingsService,
} from "@bitwarden/common/autofill/services/domain-settings.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/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 { 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 { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service";
import {
BiometricStateService,
DefaultBiometricStateService,
} from "@bitwarden/common/platform/biometrics/biometric-state.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 { AppIdService } from "@bitwarden/common/platform/services/app-id.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 { CryptoService } from "@bitwarden/common/platform/services/crypto.service";
import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation";
import { DefaultEnvironmentService } from "@bitwarden/common/platform/services/default-environment.service";
import { FileUploadService } from "@bitwarden/common/platform/services/file-upload/file-upload.service";
import { KeyGenerationService } from "@bitwarden/common/platform/services/key-generation.service";
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
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,
DerivedStateProvider,
GlobalStateProvider,
SingleUserStateProvider,
StateEventRunnerService,
StateProvider,
} 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";
import { DefaultDerivedStateProvider } from "@bitwarden/common/platform/state/implementations/default-derived-state.provider";
import { DefaultGlobalStateProvider } from "@bitwarden/common/platform/state/implementations/default-global-state.provider";
import { DefaultSingleUserStateProvider } from "@bitwarden/common/platform/state/implementations/default-single-user-state.provider";
import { DefaultStateProvider } from "@bitwarden/common/platform/state/implementations/default-state.provider";
import { StateEventRegistrarService } from "@bitwarden/common/platform/state/state-event-registrar.service";
import { MemoryStorageService as MemoryStorageServiceForStateProviders } from "@bitwarden/common/platform/state/storage/memory-storage.service";
/* eslint-enable import/no-restricted-paths */
import { AuditService } from "@bitwarden/common/services/audit.service";
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
import { SearchService } from "@bitwarden/common/services/search.service";
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
import {
PasswordGenerationService,
PasswordGenerationServiceAbstraction,
} from "@bitwarden/common/tools/generator/password";
import {
PasswordStrengthService,
PasswordStrengthServiceAbstraction,
} from "@bitwarden/common/tools/password-strength";
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service";
import { SendStateProvider } from "@bitwarden/common/tools/send/services/send-state.provider";
import { SendService } from "@bitwarden/common/tools/send/services/send.service";
import { UserId } from "@bitwarden/common/types/guid";
import { VaultTimeoutStringType } from "@bitwarden/common/types/vault-timeout.type";
import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { CipherService } from "@bitwarden/common/vault/services/cipher.service";
import { CollectionService } from "@bitwarden/common/vault/services/collection.service";
import { CipherFileUploadService } from "@bitwarden/common/vault/services/file-upload/cipher-file-upload.service";
import { FolderApiService } from "@bitwarden/common/vault/services/folder/folder-api.service";
import { FolderService } from "@bitwarden/common/vault/services/folder/folder.service";
import { SyncNotifierService } from "@bitwarden/common/vault/services/sync/sync-notifier.service";
import { SyncService } from "@bitwarden/common/vault/services/sync/sync.service";
import { TotpService } from "@bitwarden/common/vault/services/totp.service";
import {
ImportApiService,
ImportApiServiceAbstraction,
ImportService,
ImportServiceAbstraction,
} from "@bitwarden/importer/core";
import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service";
import {
IndividualVaultExportService,
IndividualVaultExportServiceAbstraction,
OrganizationVaultExportService,
OrganizationVaultExportServiceAbstraction,
VaultExportService,
VaultExportServiceAbstraction,
} from "@bitwarden/vault-export-core";
import { CliPlatformUtilsService } from "./platform/services/cli-platform-utils.service"; async function main() {
import { ConsoleLogService } from "./platform/services/console-log.service"; const serviceContainer = new ServiceContainer();
import { I18nService } from "./platform/services/i18n.service"; await serviceContainer.init();
import { LowdbStorageService } from "./platform/services/lowdb-storage.service";
import { NodeApiService } from "./platform/services/node-api.service";
import { NodeEnvSecureStorageService } from "./platform/services/node-env-secure-storage.service";
import { Program } from "./program";
import { SendProgram } from "./tools/send/send.program";
import { VaultProgram } from "./vault.program";
// Polyfills await registerOssPrograms(serviceContainer);
global.DOMParser = new jsdom.JSDOM().window.DOMParser;
// eslint-disable-next-line
const packageJson = require("../package.json");
export class Main {
messagingService: MessageSender;
storageService: LowdbStorageService;
secureStorageService: NodeEnvSecureStorageService;
memoryStorageService: MemoryStorageService;
memoryStorageForStateProviders: MemoryStorageServiceForStateProviders;
i18nService: I18nService;
platformUtilsService: CliPlatformUtilsService;
cryptoService: CryptoService;
tokenService: TokenService;
appIdService: AppIdService;
apiService: NodeApiService;
environmentService: EnvironmentService;
cipherService: CipherService;
folderService: InternalFolderService;
organizationUserService: OrganizationUserService;
collectionService: CollectionService;
vaultTimeoutService: VaultTimeoutService;
masterPasswordService: InternalMasterPasswordServiceAbstraction;
vaultTimeoutSettingsService: VaultTimeoutSettingsService;
syncService: SyncService;
eventCollectionService: EventCollectionServiceAbstraction;
eventUploadService: EventUploadServiceAbstraction;
passwordGenerationService: PasswordGenerationServiceAbstraction;
passwordStrengthService: PasswordStrengthServiceAbstraction;
userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction;
totpService: TotpService;
containerService: ContainerService;
auditService: AuditService;
importService: ImportServiceAbstraction;
importApiService: ImportApiServiceAbstraction;
exportService: VaultExportServiceAbstraction;
individualExportService: IndividualVaultExportServiceAbstraction;
organizationExportService: OrganizationVaultExportServiceAbstraction;
searchService: SearchService;
keyGenerationService: KeyGenerationServiceAbstraction;
cryptoFunctionService: NodeCryptoFunctionService;
encryptService: EncryptServiceImplementation;
authService: AuthService;
policyService: PolicyService;
policyApiService: PolicyApiServiceAbstraction;
program: Program;
vaultProgram: VaultProgram;
sendProgram: SendProgram;
logService: ConsoleLogService;
sendService: SendService;
sendStateProvider: SendStateProvider;
fileUploadService: FileUploadService;
cipherFileUploadService: CipherFileUploadService;
keyConnectorService: KeyConnectorService;
userVerificationService: UserVerificationService;
pinService: PinServiceAbstraction;
stateService: StateService;
autofillSettingsService: AutofillSettingsServiceAbstraction;
domainSettingsService: DomainSettingsService;
organizationService: OrganizationService;
providerService: ProviderService;
twoFactorService: TwoFactorService;
folderApiService: FolderApiService;
userVerificationApiService: UserVerificationApiService;
organizationApiService: OrganizationApiServiceAbstraction;
syncNotifierService: SyncNotifierService;
sendApiService: SendApiService;
devicesApiService: DevicesApiServiceAbstraction;
deviceTrustService: DeviceTrustServiceAbstraction;
authRequestService: AuthRequestService;
configApiService: ConfigApiServiceAbstraction;
configService: ConfigService;
accountService: AccountService;
globalStateProvider: GlobalStateProvider;
singleUserStateProvider: SingleUserStateProvider;
activeUserStateProvider: ActiveUserStateProvider;
derivedStateProvider: DerivedStateProvider;
stateProvider: StateProvider;
loginStrategyService: LoginStrategyServiceAbstraction;
avatarService: AvatarServiceAbstraction;
stateEventRunnerService: StateEventRunnerService;
biometricStateService: BiometricStateService;
billingAccountProfileStateService: BillingAccountProfileStateService;
providerApiService: ProviderApiServiceAbstraction;
userAutoUnlockKeyService: UserAutoUnlockKeyService;
kdfConfigService: KdfConfigServiceAbstraction;
constructor() {
let p = null;
const relativeDataDir = path.join(path.dirname(process.execPath), "bw-data");
if (fs.existsSync(relativeDataDir)) {
p = relativeDataDir;
} else if (process.env.BITWARDENCLI_APPDATA_DIR) {
p = path.resolve(process.env.BITWARDENCLI_APPDATA_DIR);
} else if (process.platform === "darwin") {
p = path.join(process.env.HOME, "Library/Application Support/Bitwarden CLI");
} else if (process.platform === "win32") {
p = path.join(process.env.APPDATA, "Bitwarden CLI");
} else if (process.env.XDG_CONFIG_HOME) {
p = path.join(process.env.XDG_CONFIG_HOME, "Bitwarden CLI");
} else {
p = path.join(process.env.HOME, ".config/Bitwarden CLI");
}
this.platformUtilsService = new CliPlatformUtilsService(ClientType.Cli, packageJson);
this.logService = new ConsoleLogService(
this.platformUtilsService.isDev(),
(level) => process.env.BITWARDENCLI_DEBUG !== "true" && level <= LogLevelType.Info,
);
this.cryptoFunctionService = new NodeCryptoFunctionService();
this.encryptService = new EncryptServiceImplementation(
this.cryptoFunctionService,
this.logService,
true,
);
this.storageService = new LowdbStorageService(this.logService, null, p, false, true);
this.secureStorageService = new NodeEnvSecureStorageService(
this.storageService,
this.logService,
this.encryptService,
);
this.memoryStorageService = new MemoryStorageService();
this.memoryStorageForStateProviders = new MemoryStorageServiceForStateProviders();
const storageServiceProvider = new StorageServiceProvider(
this.storageService,
this.memoryStorageForStateProviders,
);
this.globalStateProvider = new DefaultGlobalStateProvider(storageServiceProvider);
const stateEventRegistrarService = new StateEventRegistrarService(
this.globalStateProvider,
storageServiceProvider,
);
this.stateEventRunnerService = new StateEventRunnerService(
this.globalStateProvider,
storageServiceProvider,
);
this.i18nService = new I18nService("en", "./locales", this.globalStateProvider);
this.singleUserStateProvider = new DefaultSingleUserStateProvider(
storageServiceProvider,
stateEventRegistrarService,
);
this.messagingService = MessageSender.EMPTY;
this.accountService = new AccountServiceImplementation(
this.messagingService,
this.logService,
this.globalStateProvider,
);
this.activeUserStateProvider = new DefaultActiveUserStateProvider(
this.accountService,
this.singleUserStateProvider,
);
this.derivedStateProvider = new DefaultDerivedStateProvider();
this.stateProvider = new DefaultStateProvider(
this.activeUserStateProvider,
this.singleUserStateProvider,
this.globalStateProvider,
this.derivedStateProvider,
);
this.environmentService = new DefaultEnvironmentService(
this.stateProvider,
this.accountService,
);
this.keyGenerationService = new KeyGenerationService(this.cryptoFunctionService);
this.tokenService = new TokenService(
this.singleUserStateProvider,
this.globalStateProvider,
this.platformUtilsService.supportsSecureStorage(),
this.secureStorageService,
this.keyGenerationService,
this.encryptService,
this.logService,
);
const migrationRunner = new MigrationRunner(
this.storageService,
this.logService,
new MigrationBuilderService(),
ClientType.Cli,
);
this.stateService = new StateService(
this.storageService,
this.secureStorageService,
this.memoryStorageService,
this.logService,
new StateFactory(GlobalState, Account),
this.accountService,
this.environmentService,
this.tokenService,
migrationRunner,
);
this.masterPasswordService = new MasterPasswordService(
this.stateProvider,
this.stateService,
this.keyGenerationService,
this.encryptService,
);
this.kdfConfigService = new KdfConfigService(this.stateProvider);
this.pinService = new PinService(
this.accountService,
this.cryptoFunctionService,
this.encryptService,
this.kdfConfigService,
this.keyGenerationService,
this.logService,
this.masterPasswordService,
this.stateProvider,
this.stateService,
);
this.cryptoService = new CryptoService(
this.pinService,
this.masterPasswordService,
this.keyGenerationService,
this.cryptoFunctionService,
this.encryptService,
this.platformUtilsService,
this.logService,
this.stateService,
this.accountService,
this.stateProvider,
this.kdfConfigService,
);
this.appIdService = new AppIdService(this.globalStateProvider);
const customUserAgent =
"Bitwarden_CLI/" +
this.platformUtilsService.getApplicationVersionSync() +
" (" +
this.platformUtilsService.getDeviceString().toUpperCase() +
")";
this.biometricStateService = new DefaultBiometricStateService(this.stateProvider);
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
this.organizationService = new OrganizationService(this.stateProvider);
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
this.accountService,
this.pinService,
this.userDecryptionOptionsService,
this.cryptoService,
this.tokenService,
this.policyService,
this.biometricStateService,
this.stateProvider,
this.logService,
VaultTimeoutStringType.Never, // default vault timeout
);
this.apiService = new NodeApiService(
this.tokenService,
this.platformUtilsService,
this.environmentService,
this.appIdService,
this.vaultTimeoutSettingsService,
async (expired: boolean) => await this.logout(),
customUserAgent,
);
this.syncNotifierService = new SyncNotifierService();
this.organizationApiService = new OrganizationApiService(this.apiService, this.syncService);
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
this.domainSettingsService = new DefaultDomainSettingsService(this.stateProvider);
this.fileUploadService = new FileUploadService(this.logService);
this.sendStateProvider = new SendStateProvider(this.stateProvider);
this.sendService = new SendService(
this.cryptoService,
this.i18nService,
this.keyGenerationService,
this.sendStateProvider,
this.encryptService,
);
this.cipherFileUploadService = new CipherFileUploadService(
this.apiService,
this.fileUploadService,
);
this.sendApiService = this.sendApiService = new SendApiService(
this.apiService,
this.fileUploadService,
this.sendService,
);
this.searchService = new SearchService(this.logService, this.i18nService, this.stateProvider);
this.collectionService = new CollectionService(
this.cryptoService,
this.i18nService,
this.stateProvider,
);
this.providerService = new ProviderService(this.stateProvider);
this.organizationUserService = new OrganizationUserServiceImplementation(this.apiService);
this.policyApiService = new PolicyApiService(this.policyService, this.apiService);
this.keyConnectorService = new KeyConnectorService(
this.accountService,
this.masterPasswordService,
this.cryptoService,
this.apiService,
this.tokenService,
this.logService,
this.organizationService,
this.keyGenerationService,
async (expired: boolean) => await this.logout(),
this.stateProvider,
);
this.twoFactorService = new TwoFactorService(
this.i18nService,
this.platformUtilsService,
this.globalStateProvider,
);
this.passwordStrengthService = new PasswordStrengthService();
this.passwordGenerationService = new PasswordGenerationService(
this.cryptoService,
this.policyService,
this.stateService,
);
this.devicesApiService = new DevicesApiServiceImplementation(this.apiService);
this.deviceTrustService = new DeviceTrustService(
this.keyGenerationService,
this.cryptoFunctionService,
this.cryptoService,
this.encryptService,
this.appIdService,
this.devicesApiService,
this.i18nService,
this.platformUtilsService,
this.stateProvider,
this.secureStorageService,
this.userDecryptionOptionsService,
this.logService,
);
this.authRequestService = new AuthRequestService(
this.appIdService,
this.accountService,
this.masterPasswordService,
this.cryptoService,
this.apiService,
this.stateProvider,
);
this.billingAccountProfileStateService = new DefaultBillingAccountProfileStateService(
this.stateProvider,
);
this.loginStrategyService = new LoginStrategyService(
this.accountService,
this.masterPasswordService,
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.keyConnectorService,
this.environmentService,
this.stateService,
this.twoFactorService,
this.i18nService,
this.encryptService,
this.passwordStrengthService,
this.policyService,
this.deviceTrustService,
this.authRequestService,
this.userDecryptionOptionsService,
this.globalStateProvider,
this.billingAccountProfileStateService,
this.vaultTimeoutSettingsService,
this.kdfConfigService,
);
this.authService = new AuthService(
this.accountService,
this.messagingService,
this.cryptoService,
this.apiService,
this.stateService,
this.tokenService,
);
this.configApiService = new ConfigApiService(this.apiService, this.tokenService);
this.configService = new DefaultConfigService(
this.configApiService,
this.environmentService,
this.logService,
this.stateProvider,
);
this.cipherService = new CipherService(
this.cryptoService,
this.domainSettingsService,
this.apiService,
this.i18nService,
this.searchService,
this.stateService,
this.autofillSettingsService,
this.encryptService,
this.cipherFileUploadService,
this.configService,
this.stateProvider,
);
this.folderService = new FolderService(
this.cryptoService,
this.i18nService,
this.cipherService,
this.stateProvider,
);
this.folderApiService = new FolderApiService(this.folderService, this.apiService);
const lockedCallback = async (userId?: string) =>
await this.cryptoService.clearStoredUserKey(KeySuffixOptions.Auto);
this.userVerificationService = new UserVerificationService(
this.stateService,
this.cryptoService,
this.accountService,
this.masterPasswordService,
this.i18nService,
this.userVerificationApiService,
this.userDecryptionOptionsService,
this.pinService,
this.logService,
this.vaultTimeoutSettingsService,
this.platformUtilsService,
this.kdfConfigService,
);
this.vaultTimeoutService = new VaultTimeoutService(
this.accountService,
this.masterPasswordService,
this.cipherService,
this.folderService,
this.collectionService,
this.platformUtilsService,
this.messagingService,
this.searchService,
this.stateService,
this.authService,
this.vaultTimeoutSettingsService,
this.stateEventRunnerService,
lockedCallback,
null,
);
this.avatarService = new AvatarService(this.apiService, this.stateProvider);
this.syncService = new SyncService(
this.masterPasswordService,
this.accountService,
this.apiService,
this.domainSettingsService,
this.folderService,
this.cipherService,
this.cryptoService,
this.collectionService,
this.messagingService,
this.policyService,
this.sendService,
this.logService,
this.keyConnectorService,
this.stateService,
this.providerService,
this.folderApiService,
this.organizationService,
this.sendApiService,
this.userDecryptionOptionsService,
this.avatarService,
async (expired: boolean) => await this.logout(),
this.billingAccountProfileStateService,
this.tokenService,
this.authService,
);
this.totpService = new TotpService(this.cryptoFunctionService, this.logService);
this.importApiService = new ImportApiService(this.apiService);
this.importService = new ImportService(
this.cipherService,
this.folderService,
this.importApiService,
this.i18nService,
this.collectionService,
this.cryptoService,
this.pinService,
);
this.individualExportService = new IndividualVaultExportService(
this.folderService,
this.cipherService,
this.pinService,
this.cryptoService,
this.cryptoFunctionService,
this.kdfConfigService,
);
this.organizationExportService = new OrganizationVaultExportService(
this.cipherService,
this.apiService,
this.pinService,
this.cryptoService,
this.cryptoFunctionService,
this.collectionService,
this.kdfConfigService,
);
this.exportService = new VaultExportService(
this.individualExportService,
this.organizationExportService,
);
this.userAutoUnlockKeyService = new UserAutoUnlockKeyService(this.cryptoService);
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
this.program = new Program(this);
this.vaultProgram = new VaultProgram(this);
this.sendProgram = new SendProgram(this);
this.userVerificationApiService = new UserVerificationApiService(this.apiService);
this.eventUploadService = new EventUploadService(
this.apiService,
this.stateProvider,
this.logService,
this.authService,
);
this.eventCollectionService = new EventCollectionService(
this.cipherService,
this.stateProvider,
this.organizationService,
this.eventUploadService,
this.authService,
);
this.providerApiService = new ProviderApiService(this.apiService);
}
async run() {
await this.init();
await this.program.register();
await this.vaultProgram.register();
await this.sendProgram.register();
program.parse(process.argv); program.parse(process.argv);
if (process.argv.slice(2).length === 0) {
program.outputHelp();
}
}
async logout() {
this.authService.logOut(() => {
/* Do nothing */
});
const userId = (await this.stateService.getUserId()) as UserId;
await Promise.all([
this.eventUploadService.uploadEvents(userId as UserId),
this.syncService.setLastSync(new Date(0)),
this.cryptoService.clearKeys(),
this.cipherService.clear(userId),
this.folderService.clear(userId),
this.collectionService.clear(userId as UserId),
this.passwordGenerationService.clear(),
]);
await this.stateEventRunnerService.handleEvent("logout", userId);
await this.stateService.clean();
await this.accountService.clean(userId);
process.env.BW_SESSION = null;
}
private async init() {
await this.storageService.init();
await this.stateService.init();
this.containerService.attachToGlobal(global);
await this.i18nService.init();
this.twoFactorService.init();
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
if (activeAccount) {
await this.userAutoUnlockKeyService.setUserKeyInMemoryIfAutoUserKeySet(activeAccount.id);
}
}
} }
const main = new Main(); // Node does not support top-level await statements until ES2022, esnext, etc which we don't use yet
// 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
main.run(); main();

View File

@@ -11,9 +11,9 @@ import { ConfirmCommand } from "../admin-console/commands/confirm.command";
import { ShareCommand } from "../admin-console/commands/share.command"; import { ShareCommand } from "../admin-console/commands/share.command";
import { LockCommand } from "../auth/commands/lock.command"; import { LockCommand } from "../auth/commands/lock.command";
import { UnlockCommand } from "../auth/commands/unlock.command"; import { UnlockCommand } from "../auth/commands/unlock.command";
import { Main } from "../bw";
import { Response } from "../models/response"; import { Response } from "../models/response";
import { FileResponse } from "../models/response/file.response"; import { FileResponse } from "../models/response/file.response";
import { ServiceContainer } from "../service-container";
import { GenerateCommand } from "../tools/generate.command"; import { GenerateCommand } from "../tools/generate.command";
import { import {
SendEditCommand, SendEditCommand,
@@ -55,116 +55,119 @@ export class ServeCommand {
private sendListCommand: SendListCommand; private sendListCommand: SendListCommand;
private sendRemovePasswordCommand: SendRemovePasswordCommand; private sendRemovePasswordCommand: SendRemovePasswordCommand;
constructor(protected main: Main) { constructor(protected serviceContainer: ServiceContainer) {
this.getCommand = new GetCommand( this.getCommand = new GetCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.collectionService, this.serviceContainer.collectionService,
this.main.totpService, this.serviceContainer.totpService,
this.main.auditService, this.serviceContainer.auditService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.stateService, this.serviceContainer.stateService,
this.main.searchService, this.serviceContainer.searchService,
this.main.apiService, this.serviceContainer.apiService,
this.main.organizationService, this.serviceContainer.organizationService,
this.main.eventCollectionService, this.serviceContainer.eventCollectionService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
this.listCommand = new ListCommand( this.listCommand = new ListCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.collectionService, this.serviceContainer.collectionService,
this.main.organizationService, this.serviceContainer.organizationService,
this.main.searchService, this.serviceContainer.searchService,
this.main.organizationUserService, this.serviceContainer.organizationUserService,
this.main.apiService, this.serviceContainer.apiService,
this.main.eventCollectionService, this.serviceContainer.eventCollectionService,
); );
this.createCommand = new CreateCommand( this.createCommand = new CreateCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.apiService, this.serviceContainer.apiService,
this.main.folderApiService, this.serviceContainer.folderApiService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
this.editCommand = new EditCommand( this.editCommand = new EditCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.apiService, this.serviceContainer.apiService,
this.main.folderApiService, this.serviceContainer.folderApiService,
); );
this.generateCommand = new GenerateCommand( this.generateCommand = new GenerateCommand(
this.main.passwordGenerationService, this.serviceContainer.passwordGenerationService,
this.main.stateService, this.serviceContainer.stateService,
); );
this.syncCommand = new SyncCommand(this.main.syncService); this.syncCommand = new SyncCommand(this.serviceContainer.syncService);
this.statusCommand = new StatusCommand( this.statusCommand = new StatusCommand(
this.main.environmentService, this.serviceContainer.environmentService,
this.main.syncService, this.serviceContainer.syncService,
this.main.stateService, this.serviceContainer.stateService,
this.main.authService, this.serviceContainer.authService,
); );
this.deleteCommand = new DeleteCommand( this.deleteCommand = new DeleteCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.apiService, this.serviceContainer.apiService,
this.main.folderApiService, this.serviceContainer.folderApiService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
this.confirmCommand = new ConfirmCommand( this.confirmCommand = new ConfirmCommand(
this.main.apiService, this.serviceContainer.apiService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.organizationUserService, this.serviceContainer.organizationUserService,
); );
this.restoreCommand = new RestoreCommand(this.main.cipherService); this.restoreCommand = new RestoreCommand(this.serviceContainer.cipherService);
this.shareCommand = new ShareCommand(this.main.cipherService); this.shareCommand = new ShareCommand(this.serviceContainer.cipherService);
this.lockCommand = new LockCommand(this.main.vaultTimeoutService); this.lockCommand = new LockCommand(this.serviceContainer.vaultTimeoutService);
this.unlockCommand = new UnlockCommand( this.unlockCommand = new UnlockCommand(
this.main.accountService, this.serviceContainer.accountService,
this.main.masterPasswordService, this.serviceContainer.masterPasswordService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.stateService, this.serviceContainer.stateService,
this.main.cryptoFunctionService, this.serviceContainer.cryptoFunctionService,
this.main.apiService, this.serviceContainer.apiService,
this.main.logService, this.serviceContainer.logService,
this.main.keyConnectorService, this.serviceContainer.keyConnectorService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.syncService, this.serviceContainer.syncService,
this.main.organizationApiService, this.serviceContainer.organizationApiService,
async () => await this.main.logout(), async () => await this.serviceContainer.logout(),
this.main.kdfConfigService, this.serviceContainer.kdfConfigService,
); );
this.sendCreateCommand = new SendCreateCommand( this.sendCreateCommand = new SendCreateCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.sendApiService, this.serviceContainer.sendApiService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
);
this.sendDeleteCommand = new SendDeleteCommand(
this.serviceContainer.sendService,
this.serviceContainer.sendApiService,
); );
this.sendDeleteCommand = new SendDeleteCommand(this.main.sendService, this.main.sendApiService);
this.sendGetCommand = new SendGetCommand( this.sendGetCommand = new SendGetCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.searchService, this.serviceContainer.searchService,
this.main.cryptoService, this.serviceContainer.cryptoService,
); );
this.sendEditCommand = new SendEditCommand( this.sendEditCommand = new SendEditCommand(
this.main.sendService, this.serviceContainer.sendService,
this.sendGetCommand, this.sendGetCommand,
this.main.sendApiService, this.serviceContainer.sendApiService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
this.sendListCommand = new SendListCommand( this.sendListCommand = new SendListCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.searchService, this.serviceContainer.searchService,
); );
this.sendRemovePasswordCommand = new SendRemovePasswordCommand( this.sendRemovePasswordCommand = new SendRemovePasswordCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.sendApiService, this.serviceContainer.sendApiService,
this.main.environmentService, this.serviceContainer.environmentService,
); );
} }
@@ -172,7 +175,7 @@ export class ServeCommand {
const protectOrigin = !options.disableOriginProtection; const protectOrigin = !options.disableOriginProtection;
const port = options.port || 8087; const port = options.port || 8087;
const hostname = options.hostname || "localhost"; const hostname = options.hostname || "localhost";
this.main.logService.info( this.serviceContainer.logService.info(
`Starting server on ${hostname}:${port} with ${ `Starting server on ${hostname}:${port} with ${
protectOrigin ? "origin protection" : "no origin protection" protectOrigin ? "origin protection" : "no origin protection"
}`, }`,
@@ -187,7 +190,7 @@ export class ServeCommand {
.use(async (ctx, next) => { .use(async (ctx, next) => {
if (protectOrigin && ctx.headers.origin != undefined) { if (protectOrigin && ctx.headers.origin != undefined) {
ctx.status = 403; ctx.status = 403;
this.main.logService.warning( this.serviceContainer.logService.warning(
`Blocking request from "${ `Blocking request from "${
Utils.isNullOrEmpty(ctx.headers.origin) Utils.isNullOrEmpty(ctx.headers.origin)
? "(Origin header value missing)" ? "(Origin header value missing)"
@@ -407,7 +410,7 @@ export class ServeCommand {
.use(router.routes()) .use(router.routes())
.use(router.allowedMethods()) .use(router.allowedMethods())
.listen(port, hostname === "all" ? null : hostname, () => { .listen(port, hostname === "all" ? null : hostname, () => {
this.main.logService.info("Listening on " + hostname + ":" + port); this.serviceContainer.logService.info("Listening on " + hostname + ":" + port);
}); });
} }
@@ -426,12 +429,12 @@ export class ServeCommand {
} }
private async errorIfLocked(res: koa.Response) { private async errorIfLocked(res: koa.Response) {
const authed = await this.main.stateService.getIsAuthenticated(); const authed = await this.serviceContainer.stateService.getIsAuthenticated();
if (!authed) { if (!authed) {
this.processResponse(res, Response.error("You are not logged in.")); this.processResponse(res, Response.error("You are not logged in."));
return true; return true;
} }
if (await this.main.cryptoService.hasUserKey()) { if (await this.serviceContainer.cryptoService.hasUserKey()) {
return false; return false;
} }
this.processResponse(res, Response.error("Vault is locked.")); this.processResponse(res, Response.error("Vault is locked."));

View File

@@ -8,7 +8,6 @@ import { LockCommand } from "./auth/commands/lock.command";
import { LoginCommand } from "./auth/commands/login.command"; import { LoginCommand } from "./auth/commands/login.command";
import { LogoutCommand } from "./auth/commands/logout.command"; import { LogoutCommand } from "./auth/commands/logout.command";
import { UnlockCommand } from "./auth/commands/unlock.command"; import { UnlockCommand } from "./auth/commands/unlock.command";
import { Main } from "./bw";
import { CompletionCommand } from "./commands/completion.command"; import { CompletionCommand } from "./commands/completion.command";
import { ConfigCommand } from "./commands/config.command"; import { ConfigCommand } from "./commands/config.command";
import { EncodeCommand } from "./commands/encode.command"; import { EncodeCommand } from "./commands/encode.command";
@@ -20,6 +19,7 @@ import { ListResponse } from "./models/response/list.response";
import { MessageResponse } from "./models/response/message.response"; import { MessageResponse } from "./models/response/message.response";
import { StringResponse } from "./models/response/string.response"; import { StringResponse } from "./models/response/string.response";
import { TemplateResponse } from "./models/response/template.response"; import { TemplateResponse } from "./models/response/template.response";
import { ServiceContainer } from "./service-container";
import { GenerateCommand } from "./tools/generate.command"; import { GenerateCommand } from "./tools/generate.command";
import { CliUtils } from "./utils"; import { CliUtils } from "./utils";
import { SyncCommand } from "./vault/sync.command"; import { SyncCommand } from "./vault/sync.command";
@@ -27,7 +27,7 @@ import { SyncCommand } from "./vault/sync.command";
const writeLn = CliUtils.writeLn; const writeLn = CliUtils.writeLn;
export class Program { export class Program {
constructor(protected main: Main) {} constructor(protected serviceContainer: ServiceContainer) {}
async register() { async register() {
program program
@@ -38,7 +38,10 @@ export class Program {
.option("--quiet", "Don't return anything to stdout.") .option("--quiet", "Don't return anything to stdout.")
.option("--nointeraction", "Do not prompt for interactive user input.") .option("--nointeraction", "Do not prompt for interactive user input.")
.option("--session <session>", "Pass session key instead of reading from env.") .option("--session <session>", "Pass session key instead of reading from env.")
.version(await this.main.platformUtilsService.getApplicationVersion(), "-v, --version"); .version(
await this.serviceContainer.platformUtilsService.getApplicationVersion(),
"-v, --version",
);
program.on("option:pretty", () => { program.on("option:pretty", () => {
process.env.BW_PRETTY = "true"; process.env.BW_PRETTY = "true";
@@ -68,9 +71,11 @@ export class Program {
process.env.BW_SESSION = key; process.env.BW_SESSION = key;
// once we have the session key, we can set the user key in memory // once we have the session key, we can set the user key in memory
const activeAccount = await firstValueFrom(this.main.accountService.activeAccount$); const activeAccount = await firstValueFrom(
this.serviceContainer.accountService.activeAccount$,
);
if (activeAccount) { if (activeAccount) {
await this.main.userAutoUnlockKeyService.setUserKeyInMemoryIfAutoUserKeySet( await this.serviceContainer.userAutoUnlockKeyService.setUserKeyInMemoryIfAutoUserKeySet(
activeAccount.id, activeAccount.id,
); );
} }
@@ -122,7 +127,7 @@ export class Program {
"Path to a file containing your password as its first line", "Path to a file containing your password as its first line",
) )
.option("--check", "Check login status.", async () => { .option("--check", "Check login status.", async () => {
const authed = await this.main.stateService.getIsAuthenticated(); const authed = await this.serviceContainer.stateService.getIsAuthenticated();
if (authed) { if (authed) {
const res = new MessageResponse("You are logged in!", null); const res = new MessageResponse("You are logged in!", null);
this.processResponse(Response.success(res), true); this.processResponse(Response.success(res), true);
@@ -148,24 +153,24 @@ export class Program {
if (!options.check) { if (!options.check) {
await this.exitIfAuthed(); await this.exitIfAuthed();
const command = new LoginCommand( const command = new LoginCommand(
this.main.loginStrategyService, this.serviceContainer.loginStrategyService,
this.main.authService, this.serviceContainer.authService,
this.main.apiService, this.serviceContainer.apiService,
this.main.cryptoFunctionService, this.serviceContainer.cryptoFunctionService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.passwordGenerationService, this.serviceContainer.passwordGenerationService,
this.main.passwordStrengthService, this.serviceContainer.passwordStrengthService,
this.main.platformUtilsService, this.serviceContainer.platformUtilsService,
this.main.stateService, this.serviceContainer.stateService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.policyService, this.serviceContainer.policyService,
this.main.twoFactorService, this.serviceContainer.twoFactorService,
this.main.syncService, this.serviceContainer.syncService,
this.main.keyConnectorService, this.serviceContainer.keyConnectorService,
this.main.policyApiService, this.serviceContainer.policyApiService,
this.main.organizationService, this.serviceContainer.organizationService,
async () => await this.main.logout(), async () => await this.serviceContainer.logout(),
this.main.kdfConfigService, this.serviceContainer.kdfConfigService,
); );
const response = await command.run(email, password, options); const response = await command.run(email, password, options);
this.processResponse(response, true); this.processResponse(response, true);
@@ -184,9 +189,9 @@ export class Program {
.action(async (cmd) => { .action(async (cmd) => {
await this.exitIfNotAuthed(); await this.exitIfNotAuthed();
const command = new LogoutCommand( const command = new LogoutCommand(
this.main.authService, this.serviceContainer.authService,
this.main.i18nService, this.serviceContainer.i18nService,
async () => await this.main.logout(), async () => await this.serviceContainer.logout(),
); );
const response = await command.run(); const response = await command.run();
this.processResponse(response); this.processResponse(response);
@@ -204,11 +209,11 @@ export class Program {
.action(async (cmd) => { .action(async (cmd) => {
await this.exitIfNotAuthed(); await this.exitIfNotAuthed();
if (await this.main.keyConnectorService.getUsesKeyConnector()) { if (await this.serviceContainer.keyConnectorService.getUsesKeyConnector()) {
const logoutCommand = new LogoutCommand( const logoutCommand = new LogoutCommand(
this.main.authService, this.serviceContainer.authService,
this.main.i18nService, this.serviceContainer.i18nService,
async () => await this.main.logout(), async () => await this.serviceContainer.logout(),
); );
await logoutCommand.run(); await logoutCommand.run();
this.processResponse( this.processResponse(
@@ -221,7 +226,7 @@ export class Program {
return; return;
} }
const command = new LockCommand(this.main.vaultTimeoutService); const command = new LockCommand(this.serviceContainer.vaultTimeoutService);
const response = await command.run(); const response = await command.run();
this.processResponse(response); this.processResponse(response);
}); });
@@ -246,7 +251,7 @@ export class Program {
.option("--check", "Check lock status.", async () => { .option("--check", "Check lock status.", async () => {
await this.exitIfNotAuthed(); await this.exitIfNotAuthed();
const authStatus = await this.main.authService.getAuthStatus(); const authStatus = await this.serviceContainer.authService.getAuthStatus();
if (authStatus === AuthenticationStatus.Unlocked) { if (authStatus === AuthenticationStatus.Unlocked) {
const res = new MessageResponse("Vault is unlocked!", null); const res = new MessageResponse("Vault is unlocked!", null);
this.processResponse(Response.success(res), true); this.processResponse(Response.success(res), true);
@@ -263,19 +268,19 @@ export class Program {
if (!cmd.check) { if (!cmd.check) {
await this.exitIfNotAuthed(); await this.exitIfNotAuthed();
const command = new UnlockCommand( const command = new UnlockCommand(
this.main.accountService, this.serviceContainer.accountService,
this.main.masterPasswordService, this.serviceContainer.masterPasswordService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.stateService, this.serviceContainer.stateService,
this.main.cryptoFunctionService, this.serviceContainer.cryptoFunctionService,
this.main.apiService, this.serviceContainer.apiService,
this.main.logService, this.serviceContainer.logService,
this.main.keyConnectorService, this.serviceContainer.keyConnectorService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.syncService, this.serviceContainer.syncService,
this.main.organizationApiService, this.serviceContainer.organizationApiService,
async () => await this.main.logout(), async () => await this.serviceContainer.logout(),
this.main.kdfConfigService, this.serviceContainer.kdfConfigService,
); );
const response = await command.run(password, cmd); const response = await command.run(password, cmd);
this.processResponse(response); this.processResponse(response);
@@ -297,7 +302,7 @@ export class Program {
}) })
.action(async (cmd) => { .action(async (cmd) => {
await this.exitIfNotAuthed(); await this.exitIfNotAuthed();
const command = new SyncCommand(this.main.syncService); const command = new SyncCommand(this.serviceContainer.syncService);
const response = await command.run(cmd); const response = await command.run(cmd);
this.processResponse(response); this.processResponse(response);
}); });
@@ -340,8 +345,8 @@ export class Program {
}) })
.action(async (options) => { .action(async (options) => {
const command = new GenerateCommand( const command = new GenerateCommand(
this.main.passwordGenerationService, this.serviceContainer.passwordGenerationService,
this.main.stateService, this.serviceContainer.stateService,
); );
const response = await command.run(options); const response = await command.run(options);
this.processResponse(response); this.processResponse(response);
@@ -401,7 +406,7 @@ export class Program {
writeLn("", true); writeLn("", true);
}) })
.action(async (setting, value, options) => { .action(async (setting, value, options) => {
const command = new ConfigCommand(this.main.environmentService); const command = new ConfigCommand(this.serviceContainer.environmentService);
const response = await command.run(setting, value, options); const response = await command.run(setting, value, options);
this.processResponse(response); this.processResponse(response);
}); });
@@ -423,7 +428,7 @@ export class Program {
writeLn("", true); writeLn("", true);
}) })
.action(async () => { .action(async () => {
const command = new UpdateCommand(this.main.platformUtilsService); const command = new UpdateCommand(this.serviceContainer.platformUtilsService);
const response = await command.run(); const response = await command.run();
this.processResponse(response); this.processResponse(response);
}); });
@@ -474,10 +479,10 @@ export class Program {
}) })
.action(async () => { .action(async () => {
const command = new StatusCommand( const command = new StatusCommand(
this.main.environmentService, this.serviceContainer.environmentService,
this.main.syncService, this.serviceContainer.syncService,
this.main.stateService, this.serviceContainer.stateService,
this.main.authService, this.serviceContainer.authService,
); );
const response = await command.run(); const response = await command.run();
this.processResponse(response); this.processResponse(response);
@@ -508,7 +513,7 @@ export class Program {
}) })
.action(async (cmd) => { .action(async (cmd) => {
await this.exitIfNotAuthed(); await this.exitIfNotAuthed();
const command = new ServeCommand(this.main); const command = new ServeCommand(this.serviceContainer);
await command.run(cmd); await command.run(cmd);
}); });
} }
@@ -598,15 +603,15 @@ export class Program {
} }
private async exitIfAuthed() { private async exitIfAuthed() {
const authed = await this.main.stateService.getIsAuthenticated(); const authed = await this.serviceContainer.stateService.getIsAuthenticated();
if (authed) { if (authed) {
const email = await this.main.stateService.getEmail(); const email = await this.serviceContainer.stateService.getEmail();
this.processResponse(Response.error("You are already logged in as " + email + "."), true); this.processResponse(Response.error("You are already logged in as " + email + "."), true);
} }
} }
private async exitIfNotAuthed() { private async exitIfNotAuthed() {
const authed = await this.main.stateService.getIsAuthenticated(); const authed = await this.serviceContainer.stateService.getIsAuthenticated();
if (!authed) { if (!authed) {
this.processResponse(Response.error("You are not logged in."), true); this.processResponse(Response.error("You are not logged in."), true);
} }
@@ -614,11 +619,11 @@ export class Program {
protected async exitIfLocked() { protected async exitIfLocked() {
await this.exitIfNotAuthed(); await this.exitIfNotAuthed();
if (await this.main.cryptoService.hasUserKey()) { if (await this.serviceContainer.cryptoService.hasUserKey()) {
return; return;
} else if (process.env.BW_NOINTERACTION !== "true") { } else if (process.env.BW_NOINTERACTION !== "true") {
// must unlock // must unlock
if (await this.main.keyConnectorService.getUsesKeyConnector()) { if (await this.serviceContainer.keyConnectorService.getUsesKeyConnector()) {
const response = Response.error( const response = Response.error(
"Your vault is locked. You must unlock your vault using your session key.\n" + "Your vault is locked. You must unlock your vault using your session key.\n" +
"If you do not have your session key, you can get a new one by logging out and logging in again.", "If you do not have your session key, you can get a new one by logging out and logging in again.",
@@ -626,19 +631,19 @@ export class Program {
this.processResponse(response, true); this.processResponse(response, true);
} else { } else {
const command = new UnlockCommand( const command = new UnlockCommand(
this.main.accountService, this.serviceContainer.accountService,
this.main.masterPasswordService, this.serviceContainer.masterPasswordService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.stateService, this.serviceContainer.stateService,
this.main.cryptoFunctionService, this.serviceContainer.cryptoFunctionService,
this.main.apiService, this.serviceContainer.apiService,
this.main.logService, this.serviceContainer.logService,
this.main.keyConnectorService, this.serviceContainer.keyConnectorService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.syncService, this.serviceContainer.syncService,
this.main.organizationApiService, this.serviceContainer.organizationApiService,
this.main.logout, this.serviceContainer.logout,
this.main.kdfConfigService, this.serviceContainer.kdfConfigService,
); );
const response = await command.run(null, null); const response = await command.run(null, null);
if (!response.success) { if (!response.success) {

View File

@@ -0,0 +1,22 @@
import { Program } from "./program";
import { ServiceContainer } from "./service-container";
import { SendProgram } from "./tools/send/send.program";
import { VaultProgram } from "./vault.program";
/**
* All OSS licensed programs should be registered here.
* @example
* const myProgram = new myProgram(serviceContainer);
* myProgram.register();
* @param serviceContainer A class that instantiates services and makes them available for dependency injection
*/
export async function registerOssPrograms(serviceContainer: ServiceContainer) {
const program = new Program(serviceContainer);
await program.register();
const vaultProgram = new VaultProgram(serviceContainer);
await vaultProgram.register();
const sendProgram = new SendProgram(serviceContainer);
await sendProgram.register();
}

View File

@@ -0,0 +1,7 @@
import { ServiceContainer } from "./service-container";
describe("ServiceContainer", () => {
it("instantiates", async () => {
expect(() => new ServiceContainer()).not.toThrow();
});
});

View File

@@ -0,0 +1,772 @@
import * as fs from "fs";
import * as path from "path";
import * as jsdom from "jsdom";
import { firstValueFrom } from "rxjs";
import {
InternalUserDecryptionOptionsServiceAbstraction,
AuthRequestService,
LoginStrategyService,
LoginStrategyServiceAbstraction,
PinService,
PinServiceAbstraction,
UserDecryptionOptionsService,
} from "@bitwarden/auth/common";
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { ProviderApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider/provider-api.service.abstraction";
import { OrganizationApiService } from "@bitwarden/common/admin-console/services/organization/organization-api.service";
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
import { OrganizationUserServiceImplementation } from "@bitwarden/common/admin-console/services/organization-user/organization-user.service.implementation";
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
import { ProviderApiService } from "@bitwarden/common/admin-console/services/provider/provider-api.service";
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service";
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { KdfConfigService as KdfConfigServiceAbstraction } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust.service.implementation";
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
import { KdfConfigService } from "@bitwarden/common/auth/services/kdf-config.service";
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
import { MasterPasswordService } from "@bitwarden/common/auth/services/master-password/master-password.service";
import { TokenService } from "@bitwarden/common/auth/services/token.service";
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service";
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
import {
DefaultDomainSettingsService,
DomainSettingsService,
} from "@bitwarden/common/autofill/services/domain-settings.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/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 { 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 { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service";
import {
BiometricStateService,
DefaultBiometricStateService,
} from "@bitwarden/common/platform/biometrics/biometric-state.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 { AppIdService } from "@bitwarden/common/platform/services/app-id.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 { CryptoService } from "@bitwarden/common/platform/services/crypto.service";
import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation";
import { DefaultEnvironmentService } from "@bitwarden/common/platform/services/default-environment.service";
import { FileUploadService } from "@bitwarden/common/platform/services/file-upload/file-upload.service";
import { KeyGenerationService } from "@bitwarden/common/platform/services/key-generation.service";
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
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,
DerivedStateProvider,
GlobalStateProvider,
SingleUserStateProvider,
StateEventRunnerService,
StateProvider,
} 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";
import { DefaultDerivedStateProvider } from "@bitwarden/common/platform/state/implementations/default-derived-state.provider";
import { DefaultGlobalStateProvider } from "@bitwarden/common/platform/state/implementations/default-global-state.provider";
import { DefaultSingleUserStateProvider } from "@bitwarden/common/platform/state/implementations/default-single-user-state.provider";
import { DefaultStateProvider } from "@bitwarden/common/platform/state/implementations/default-state.provider";
import { StateEventRegistrarService } from "@bitwarden/common/platform/state/state-event-registrar.service";
import { MemoryStorageService as MemoryStorageServiceForStateProviders } from "@bitwarden/common/platform/state/storage/memory-storage.service";
/* eslint-enable import/no-restricted-paths */
import { AuditService } from "@bitwarden/common/services/audit.service";
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
import { SearchService } from "@bitwarden/common/services/search.service";
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
import {
PasswordGenerationService,
PasswordGenerationServiceAbstraction,
} from "@bitwarden/common/tools/generator/password";
import {
PasswordStrengthService,
PasswordStrengthServiceAbstraction,
} from "@bitwarden/common/tools/password-strength";
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service";
import { SendStateProvider } from "@bitwarden/common/tools/send/services/send-state.provider";
import { SendService } from "@bitwarden/common/tools/send/services/send.service";
import { UserId } from "@bitwarden/common/types/guid";
import { VaultTimeoutStringType } from "@bitwarden/common/types/vault-timeout.type";
import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { CipherService } from "@bitwarden/common/vault/services/cipher.service";
import { CollectionService } from "@bitwarden/common/vault/services/collection.service";
import { CipherFileUploadService } from "@bitwarden/common/vault/services/file-upload/cipher-file-upload.service";
import { FolderApiService } from "@bitwarden/common/vault/services/folder/folder-api.service";
import { FolderService } from "@bitwarden/common/vault/services/folder/folder.service";
import { SyncNotifierService } from "@bitwarden/common/vault/services/sync/sync-notifier.service";
import { SyncService } from "@bitwarden/common/vault/services/sync/sync.service";
import { TotpService } from "@bitwarden/common/vault/services/totp.service";
import {
ImportApiService,
ImportApiServiceAbstraction,
ImportService,
ImportServiceAbstraction,
} from "@bitwarden/importer/core";
import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service";
import {
IndividualVaultExportService,
IndividualVaultExportServiceAbstraction,
OrganizationVaultExportService,
OrganizationVaultExportServiceAbstraction,
VaultExportService,
VaultExportServiceAbstraction,
} from "@bitwarden/vault-export-core";
import { CliPlatformUtilsService } from "./platform/services/cli-platform-utils.service";
import { ConsoleLogService } from "./platform/services/console-log.service";
import { I18nService } from "./platform/services/i18n.service";
import { LowdbStorageService } from "./platform/services/lowdb-storage.service";
import { NodeApiService } from "./platform/services/node-api.service";
import { NodeEnvSecureStorageService } from "./platform/services/node-env-secure-storage.service";
// Polyfills
global.DOMParser = new jsdom.JSDOM().window.DOMParser;
// eslint-disable-next-line
const packageJson = require("../package.json");
/**
* Instantiates services and makes them available for dependency injection.
* Any Bitwarden-licensed services should be registered here.
*/
export class ServiceContainer {
private inited = false;
messagingService: MessageSender;
storageService: LowdbStorageService;
secureStorageService: NodeEnvSecureStorageService;
memoryStorageService: MemoryStorageService;
memoryStorageForStateProviders: MemoryStorageServiceForStateProviders;
i18nService: I18nService;
platformUtilsService: CliPlatformUtilsService;
cryptoService: CryptoService;
tokenService: TokenService;
appIdService: AppIdService;
apiService: NodeApiService;
environmentService: EnvironmentService;
cipherService: CipherService;
folderService: InternalFolderService;
organizationUserService: OrganizationUserService;
collectionService: CollectionService;
vaultTimeoutService: VaultTimeoutService;
masterPasswordService: InternalMasterPasswordServiceAbstraction;
vaultTimeoutSettingsService: VaultTimeoutSettingsService;
syncService: SyncService;
eventCollectionService: EventCollectionServiceAbstraction;
eventUploadService: EventUploadServiceAbstraction;
passwordGenerationService: PasswordGenerationServiceAbstraction;
passwordStrengthService: PasswordStrengthServiceAbstraction;
userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction;
totpService: TotpService;
containerService: ContainerService;
auditService: AuditService;
importService: ImportServiceAbstraction;
importApiService: ImportApiServiceAbstraction;
exportService: VaultExportServiceAbstraction;
individualExportService: IndividualVaultExportServiceAbstraction;
organizationExportService: OrganizationVaultExportServiceAbstraction;
searchService: SearchService;
keyGenerationService: KeyGenerationServiceAbstraction;
cryptoFunctionService: NodeCryptoFunctionService;
encryptService: EncryptServiceImplementation;
authService: AuthService;
policyService: PolicyService;
policyApiService: PolicyApiServiceAbstraction;
logService: ConsoleLogService;
sendService: SendService;
sendStateProvider: SendStateProvider;
fileUploadService: FileUploadService;
cipherFileUploadService: CipherFileUploadService;
keyConnectorService: KeyConnectorService;
userVerificationService: UserVerificationService;
pinService: PinServiceAbstraction;
stateService: StateService;
autofillSettingsService: AutofillSettingsServiceAbstraction;
domainSettingsService: DomainSettingsService;
organizationService: OrganizationService;
providerService: ProviderService;
twoFactorService: TwoFactorService;
folderApiService: FolderApiService;
userVerificationApiService: UserVerificationApiService;
organizationApiService: OrganizationApiServiceAbstraction;
syncNotifierService: SyncNotifierService;
sendApiService: SendApiService;
devicesApiService: DevicesApiServiceAbstraction;
deviceTrustService: DeviceTrustServiceAbstraction;
authRequestService: AuthRequestService;
configApiService: ConfigApiServiceAbstraction;
configService: ConfigService;
accountService: AccountService;
globalStateProvider: GlobalStateProvider;
singleUserStateProvider: SingleUserStateProvider;
activeUserStateProvider: ActiveUserStateProvider;
derivedStateProvider: DerivedStateProvider;
stateProvider: StateProvider;
loginStrategyService: LoginStrategyServiceAbstraction;
avatarService: AvatarServiceAbstraction;
stateEventRunnerService: StateEventRunnerService;
biometricStateService: BiometricStateService;
billingAccountProfileStateService: BillingAccountProfileStateService;
providerApiService: ProviderApiServiceAbstraction;
userAutoUnlockKeyService: UserAutoUnlockKeyService;
kdfConfigService: KdfConfigServiceAbstraction;
constructor() {
let p = null;
const relativeDataDir = path.join(path.dirname(process.execPath), "bw-data");
if (fs.existsSync(relativeDataDir)) {
p = relativeDataDir;
} else if (process.env.BITWARDENCLI_APPDATA_DIR) {
p = path.resolve(process.env.BITWARDENCLI_APPDATA_DIR);
} else if (process.platform === "darwin") {
p = path.join(process.env.HOME, "Library/Application Support/Bitwarden CLI");
} else if (process.platform === "win32") {
p = path.join(process.env.APPDATA, "Bitwarden CLI");
} else if (process.env.XDG_CONFIG_HOME) {
p = path.join(process.env.XDG_CONFIG_HOME, "Bitwarden CLI");
} else {
p = path.join(process.env.HOME, ".config/Bitwarden CLI");
}
this.platformUtilsService = new CliPlatformUtilsService(ClientType.Cli, packageJson);
this.logService = new ConsoleLogService(
this.platformUtilsService.isDev(),
(level) => process.env.BITWARDENCLI_DEBUG !== "true" && level <= LogLevelType.Info,
);
this.cryptoFunctionService = new NodeCryptoFunctionService();
this.encryptService = new EncryptServiceImplementation(
this.cryptoFunctionService,
this.logService,
true,
);
this.storageService = new LowdbStorageService(this.logService, null, p, false, true);
this.secureStorageService = new NodeEnvSecureStorageService(
this.storageService,
this.logService,
this.encryptService,
);
this.memoryStorageService = new MemoryStorageService();
this.memoryStorageForStateProviders = new MemoryStorageServiceForStateProviders();
const storageServiceProvider = new StorageServiceProvider(
this.storageService,
this.memoryStorageForStateProviders,
);
this.globalStateProvider = new DefaultGlobalStateProvider(storageServiceProvider);
const stateEventRegistrarService = new StateEventRegistrarService(
this.globalStateProvider,
storageServiceProvider,
);
this.stateEventRunnerService = new StateEventRunnerService(
this.globalStateProvider,
storageServiceProvider,
);
this.i18nService = new I18nService("en", "./locales", this.globalStateProvider);
this.singleUserStateProvider = new DefaultSingleUserStateProvider(
storageServiceProvider,
stateEventRegistrarService,
);
this.messagingService = MessageSender.EMPTY;
this.accountService = new AccountServiceImplementation(
this.messagingService,
this.logService,
this.globalStateProvider,
);
this.activeUserStateProvider = new DefaultActiveUserStateProvider(
this.accountService,
this.singleUserStateProvider,
);
this.derivedStateProvider = new DefaultDerivedStateProvider();
this.stateProvider = new DefaultStateProvider(
this.activeUserStateProvider,
this.singleUserStateProvider,
this.globalStateProvider,
this.derivedStateProvider,
);
this.environmentService = new DefaultEnvironmentService(
this.stateProvider,
this.accountService,
);
this.keyGenerationService = new KeyGenerationService(this.cryptoFunctionService);
this.tokenService = new TokenService(
this.singleUserStateProvider,
this.globalStateProvider,
this.platformUtilsService.supportsSecureStorage(),
this.secureStorageService,
this.keyGenerationService,
this.encryptService,
this.logService,
);
const migrationRunner = new MigrationRunner(
this.storageService,
this.logService,
new MigrationBuilderService(),
ClientType.Cli,
);
this.stateService = new StateService(
this.storageService,
this.secureStorageService,
this.memoryStorageService,
this.logService,
new StateFactory(GlobalState, Account),
this.accountService,
this.environmentService,
this.tokenService,
migrationRunner,
);
this.masterPasswordService = new MasterPasswordService(
this.stateProvider,
this.stateService,
this.keyGenerationService,
this.encryptService,
);
this.kdfConfigService = new KdfConfigService(this.stateProvider);
this.pinService = new PinService(
this.accountService,
this.cryptoFunctionService,
this.encryptService,
this.kdfConfigService,
this.keyGenerationService,
this.logService,
this.masterPasswordService,
this.stateProvider,
this.stateService,
);
this.cryptoService = new CryptoService(
this.pinService,
this.masterPasswordService,
this.keyGenerationService,
this.cryptoFunctionService,
this.encryptService,
this.platformUtilsService,
this.logService,
this.stateService,
this.accountService,
this.stateProvider,
this.kdfConfigService,
);
this.appIdService = new AppIdService(this.globalStateProvider);
const customUserAgent =
"Bitwarden_CLI/" +
this.platformUtilsService.getApplicationVersionSync() +
" (" +
this.platformUtilsService.getDeviceString().toUpperCase() +
")";
this.biometricStateService = new DefaultBiometricStateService(this.stateProvider);
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
this.organizationService = new OrganizationService(this.stateProvider);
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
this.accountService,
this.pinService,
this.userDecryptionOptionsService,
this.cryptoService,
this.tokenService,
this.policyService,
this.biometricStateService,
this.stateProvider,
this.logService,
VaultTimeoutStringType.Never, // default vault timeout
);
this.apiService = new NodeApiService(
this.tokenService,
this.platformUtilsService,
this.environmentService,
this.appIdService,
this.vaultTimeoutSettingsService,
async (expired: boolean) => await this.logout(),
customUserAgent,
);
this.syncNotifierService = new SyncNotifierService();
this.organizationApiService = new OrganizationApiService(this.apiService, this.syncService);
this.containerService = new ContainerService(this.cryptoService, this.encryptService);
this.domainSettingsService = new DefaultDomainSettingsService(this.stateProvider);
this.fileUploadService = new FileUploadService(this.logService);
this.sendStateProvider = new SendStateProvider(this.stateProvider);
this.sendService = new SendService(
this.cryptoService,
this.i18nService,
this.keyGenerationService,
this.sendStateProvider,
this.encryptService,
);
this.cipherFileUploadService = new CipherFileUploadService(
this.apiService,
this.fileUploadService,
);
this.sendApiService = this.sendApiService = new SendApiService(
this.apiService,
this.fileUploadService,
this.sendService,
);
this.searchService = new SearchService(this.logService, this.i18nService, this.stateProvider);
this.collectionService = new CollectionService(
this.cryptoService,
this.i18nService,
this.stateProvider,
);
this.providerService = new ProviderService(this.stateProvider);
this.organizationUserService = new OrganizationUserServiceImplementation(this.apiService);
this.policyApiService = new PolicyApiService(this.policyService, this.apiService);
this.keyConnectorService = new KeyConnectorService(
this.accountService,
this.masterPasswordService,
this.cryptoService,
this.apiService,
this.tokenService,
this.logService,
this.organizationService,
this.keyGenerationService,
async (expired: boolean) => await this.logout(),
this.stateProvider,
);
this.twoFactorService = new TwoFactorService(
this.i18nService,
this.platformUtilsService,
this.globalStateProvider,
);
this.passwordStrengthService = new PasswordStrengthService();
this.passwordGenerationService = new PasswordGenerationService(
this.cryptoService,
this.policyService,
this.stateService,
);
this.devicesApiService = new DevicesApiServiceImplementation(this.apiService);
this.deviceTrustService = new DeviceTrustService(
this.keyGenerationService,
this.cryptoFunctionService,
this.cryptoService,
this.encryptService,
this.appIdService,
this.devicesApiService,
this.i18nService,
this.platformUtilsService,
this.stateProvider,
this.secureStorageService,
this.userDecryptionOptionsService,
this.logService,
);
this.authRequestService = new AuthRequestService(
this.appIdService,
this.accountService,
this.masterPasswordService,
this.cryptoService,
this.apiService,
this.stateProvider,
);
this.billingAccountProfileStateService = new DefaultBillingAccountProfileStateService(
this.stateProvider,
);
this.loginStrategyService = new LoginStrategyService(
this.accountService,
this.masterPasswordService,
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.keyConnectorService,
this.environmentService,
this.stateService,
this.twoFactorService,
this.i18nService,
this.encryptService,
this.passwordStrengthService,
this.policyService,
this.deviceTrustService,
this.authRequestService,
this.userDecryptionOptionsService,
this.globalStateProvider,
this.billingAccountProfileStateService,
this.vaultTimeoutSettingsService,
this.kdfConfigService,
);
this.authService = new AuthService(
this.accountService,
this.messagingService,
this.cryptoService,
this.apiService,
this.stateService,
this.tokenService,
);
this.configApiService = new ConfigApiService(this.apiService, this.tokenService);
this.configService = new DefaultConfigService(
this.configApiService,
this.environmentService,
this.logService,
this.stateProvider,
);
this.cipherService = new CipherService(
this.cryptoService,
this.domainSettingsService,
this.apiService,
this.i18nService,
this.searchService,
this.stateService,
this.autofillSettingsService,
this.encryptService,
this.cipherFileUploadService,
this.configService,
this.stateProvider,
);
this.folderService = new FolderService(
this.cryptoService,
this.i18nService,
this.cipherService,
this.stateProvider,
);
this.folderApiService = new FolderApiService(this.folderService, this.apiService);
const lockedCallback = async (userId?: string) =>
await this.cryptoService.clearStoredUserKey(KeySuffixOptions.Auto);
this.userVerificationService = new UserVerificationService(
this.stateService,
this.cryptoService,
this.accountService,
this.masterPasswordService,
this.i18nService,
this.userVerificationApiService,
this.userDecryptionOptionsService,
this.pinService,
this.logService,
this.vaultTimeoutSettingsService,
this.platformUtilsService,
this.kdfConfigService,
);
this.vaultTimeoutService = new VaultTimeoutService(
this.accountService,
this.masterPasswordService,
this.cipherService,
this.folderService,
this.collectionService,
this.platformUtilsService,
this.messagingService,
this.searchService,
this.stateService,
this.authService,
this.vaultTimeoutSettingsService,
this.stateEventRunnerService,
lockedCallback,
null,
);
this.avatarService = new AvatarService(this.apiService, this.stateProvider);
this.syncService = new SyncService(
this.masterPasswordService,
this.accountService,
this.apiService,
this.domainSettingsService,
this.folderService,
this.cipherService,
this.cryptoService,
this.collectionService,
this.messagingService,
this.policyService,
this.sendService,
this.logService,
this.keyConnectorService,
this.stateService,
this.providerService,
this.folderApiService,
this.organizationService,
this.sendApiService,
this.userDecryptionOptionsService,
this.avatarService,
async (expired: boolean) => await this.logout(),
this.billingAccountProfileStateService,
this.tokenService,
this.authService,
);
this.totpService = new TotpService(this.cryptoFunctionService, this.logService);
this.importApiService = new ImportApiService(this.apiService);
this.importService = new ImportService(
this.cipherService,
this.folderService,
this.importApiService,
this.i18nService,
this.collectionService,
this.cryptoService,
this.pinService,
);
this.individualExportService = new IndividualVaultExportService(
this.folderService,
this.cipherService,
this.pinService,
this.cryptoService,
this.cryptoFunctionService,
this.kdfConfigService,
);
this.organizationExportService = new OrganizationVaultExportService(
this.cipherService,
this.apiService,
this.pinService,
this.cryptoService,
this.cryptoFunctionService,
this.collectionService,
this.kdfConfigService,
);
this.exportService = new VaultExportService(
this.individualExportService,
this.organizationExportService,
);
this.userAutoUnlockKeyService = new UserAutoUnlockKeyService(this.cryptoService);
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
this.userVerificationApiService = new UserVerificationApiService(this.apiService);
this.eventUploadService = new EventUploadService(
this.apiService,
this.stateProvider,
this.logService,
this.authService,
);
this.eventCollectionService = new EventCollectionService(
this.cipherService,
this.stateProvider,
this.organizationService,
this.eventUploadService,
this.authService,
);
this.providerApiService = new ProviderApiService(this.apiService);
}
async logout() {
this.authService.logOut(() => {
/* Do nothing */
});
const userId = (await this.stateService.getUserId()) as UserId;
await Promise.all([
this.eventUploadService.uploadEvents(userId as UserId),
this.syncService.setLastSync(new Date(0)),
this.cryptoService.clearKeys(),
this.cipherService.clear(userId),
this.folderService.clear(userId),
this.collectionService.clear(userId as UserId),
this.passwordGenerationService.clear(),
]);
await this.stateEventRunnerService.handleEvent("logout", userId);
await this.stateService.clean();
await this.accountService.clean(userId);
process.env.BW_SESSION = null;
}
async init() {
if (this.inited) {
this.logService.warning("ServiceContainer.init called more than once");
return;
}
await this.storageService.init();
await this.stateService.init();
this.containerService.attachToGlobal(global);
await this.i18nService.init();
this.twoFactorService.init();
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
if (activeAccount) {
await this.userAutoUnlockKeyService.setUserKeyInMemoryIfAutoUserKeySet(activeAccount.id);
}
this.inited = true;
}
}

View File

@@ -7,7 +7,6 @@ import { program, Command, OptionValues } from "commander";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SendType } from "@bitwarden/common/tools/send/enums/send-type"; import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
import { Main } from "../../bw";
import { GetCommand } from "../../commands/get.command"; import { GetCommand } from "../../commands/get.command";
import { Response } from "../../models/response"; import { Response } from "../../models/response";
import { Program } from "../../program"; import { Program } from "../../program";
@@ -29,10 +28,6 @@ import { SendResponse } from "./models/send.response";
const writeLn = CliUtils.writeLn; const writeLn = CliUtils.writeLn;
export class SendProgram extends Program { export class SendProgram extends Program {
constructor(main: Main) {
super(main);
}
async register() { async register() {
program.addCommand(this.sendCommand()); program.addCommand(this.sendCommand());
// receive is accessible both at `bw receive` and `bw send receive` // receive is accessible both at `bw receive` and `bw send receive`
@@ -105,12 +100,12 @@ export class SendProgram extends Program {
}) })
.action(async (url: string, options: OptionValues) => { .action(async (url: string, options: OptionValues) => {
const cmd = new SendReceiveCommand( const cmd = new SendReceiveCommand(
this.main.apiService, this.serviceContainer.apiService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.cryptoFunctionService, this.serviceContainer.cryptoFunctionService,
this.main.platformUtilsService, this.serviceContainer.platformUtilsService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.sendApiService, this.serviceContainer.sendApiService,
); );
const response = await cmd.run(url, options); const response = await cmd.run(url, options);
this.processResponse(response); this.processResponse(response);
@@ -127,9 +122,9 @@ export class SendProgram extends Program {
.action(async (options: OptionValues) => { .action(async (options: OptionValues) => {
await this.exitIfLocked(); await this.exitIfLocked();
const cmd = new SendListCommand( const cmd = new SendListCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.searchService, this.serviceContainer.searchService,
); );
const response = await cmd.run(options); const response = await cmd.run(options);
this.processResponse(response); this.processResponse(response);
@@ -142,18 +137,18 @@ export class SendProgram extends Program {
.description("Get json templates for send objects") .description("Get json templates for send objects")
.action(async (object) => { .action(async (object) => {
const cmd = new GetCommand( const cmd = new GetCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.collectionService, this.serviceContainer.collectionService,
this.main.totpService, this.serviceContainer.totpService,
this.main.auditService, this.serviceContainer.auditService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.stateService, this.serviceContainer.stateService,
this.main.searchService, this.serviceContainer.searchService,
this.main.apiService, this.serviceContainer.apiService,
this.main.organizationService, this.serviceContainer.organizationService,
this.main.eventCollectionService, this.serviceContainer.eventCollectionService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
const response = await cmd.run("template", object, null); const response = await cmd.run("template", object, null);
this.processResponse(response); this.processResponse(response);
@@ -188,10 +183,10 @@ export class SendProgram extends Program {
.action(async (id: string, options: OptionValues) => { .action(async (id: string, options: OptionValues) => {
await this.exitIfLocked(); await this.exitIfLocked();
const cmd = new SendGetCommand( const cmd = new SendGetCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.searchService, this.serviceContainer.searchService,
this.main.cryptoService, this.serviceContainer.cryptoService,
); );
const response = await cmd.run(id, options); const response = await cmd.run(id, options);
this.processResponse(response); this.processResponse(response);
@@ -247,16 +242,16 @@ export class SendProgram extends Program {
.action(async (encodedJson: string, options: OptionValues) => { .action(async (encodedJson: string, options: OptionValues) => {
await this.exitIfLocked(); await this.exitIfLocked();
const getCmd = new SendGetCommand( const getCmd = new SendGetCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.searchService, this.serviceContainer.searchService,
this.main.cryptoService, this.serviceContainer.cryptoService,
); );
const cmd = new SendEditCommand( const cmd = new SendEditCommand(
this.main.sendService, this.serviceContainer.sendService,
getCmd, getCmd,
this.main.sendApiService, this.serviceContainer.sendApiService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
const response = await cmd.run(encodedJson, options); const response = await cmd.run(encodedJson, options);
this.processResponse(response); this.processResponse(response);
@@ -269,7 +264,10 @@ export class SendProgram extends Program {
.description("delete a Send") .description("delete a Send")
.action(async (id: string) => { .action(async (id: string) => {
await this.exitIfLocked(); await this.exitIfLocked();
const cmd = new SendDeleteCommand(this.main.sendService, this.main.sendApiService); const cmd = new SendDeleteCommand(
this.serviceContainer.sendService,
this.serviceContainer.sendApiService,
);
const response = await cmd.run(id); const response = await cmd.run(id);
this.processResponse(response); this.processResponse(response);
}); });
@@ -282,9 +280,9 @@ export class SendProgram extends Program {
.action(async (id: string) => { .action(async (id: string) => {
await this.exitIfLocked(); await this.exitIfLocked();
const cmd = new SendRemovePasswordCommand( const cmd = new SendRemovePasswordCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.sendApiService, this.serviceContainer.sendApiService,
this.main.environmentService, this.serviceContainer.environmentService,
); );
const response = await cmd.run(id); const response = await cmd.run(id);
this.processResponse(response); this.processResponse(response);
@@ -323,10 +321,10 @@ export class SendProgram extends Program {
private async runCreate(encodedJson: string, options: OptionValues) { private async runCreate(encodedJson: string, options: OptionValues) {
await this.exitIfLocked(); await this.exitIfLocked();
const cmd = new SendCreateCommand( const cmd = new SendCreateCommand(
this.main.sendService, this.serviceContainer.sendService,
this.main.environmentService, this.serviceContainer.environmentService,
this.main.sendApiService, this.serviceContainer.sendApiService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
return await cmd.run(encodedJson, options); return await cmd.run(encodedJson, options);
} }

View File

@@ -2,7 +2,6 @@ import { program, Command } from "commander";
import { ConfirmCommand } from "./admin-console/commands/confirm.command"; import { ConfirmCommand } from "./admin-console/commands/confirm.command";
import { ShareCommand } from "./admin-console/commands/share.command"; import { ShareCommand } from "./admin-console/commands/share.command";
import { Main } from "./bw";
import { EditCommand } from "./commands/edit.command"; import { EditCommand } from "./commands/edit.command";
import { GetCommand } from "./commands/get.command"; import { GetCommand } from "./commands/get.command";
import { ListCommand } from "./commands/list.command"; import { ListCommand } from "./commands/list.command";
@@ -18,10 +17,6 @@ import { DeleteCommand } from "./vault/delete.command";
const writeLn = CliUtils.writeLn; const writeLn = CliUtils.writeLn;
export class VaultProgram extends Program { export class VaultProgram extends Program {
constructor(protected main: Main) {
super(main);
}
async register() { async register() {
program program
.addCommand(this.listCommand()) .addCommand(this.listCommand())
@@ -108,14 +103,14 @@ export class VaultProgram extends Program {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new ListCommand( const command = new ListCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.collectionService, this.serviceContainer.collectionService,
this.main.organizationService, this.serviceContainer.organizationService,
this.main.searchService, this.serviceContainer.searchService,
this.main.organizationUserService, this.serviceContainer.organizationUserService,
this.main.apiService, this.serviceContainer.apiService,
this.main.eventCollectionService, this.serviceContainer.eventCollectionService,
); );
const response = await command.run(object, cmd); const response = await command.run(object, cmd);
@@ -177,18 +172,18 @@ export class VaultProgram extends Program {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new GetCommand( const command = new GetCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.collectionService, this.serviceContainer.collectionService,
this.main.totpService, this.serviceContainer.totpService,
this.main.auditService, this.serviceContainer.auditService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.stateService, this.serviceContainer.stateService,
this.main.searchService, this.serviceContainer.searchService,
this.main.apiService, this.serviceContainer.apiService,
this.main.organizationService, this.serviceContainer.organizationService,
this.main.eventCollectionService, this.serviceContainer.eventCollectionService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
const response = await command.run(object, id, cmd); const response = await command.run(object, id, cmd);
this.processResponse(response); this.processResponse(response);
@@ -225,12 +220,12 @@ export class VaultProgram extends Program {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new CreateCommand( const command = new CreateCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.apiService, this.serviceContainer.apiService,
this.main.folderApiService, this.serviceContainer.folderApiService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
const response = await command.run(object, encodedJson, cmd); const response = await command.run(object, encodedJson, cmd);
this.processResponse(response); this.processResponse(response);
@@ -271,11 +266,11 @@ export class VaultProgram extends Program {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new EditCommand( const command = new EditCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.apiService, this.serviceContainer.apiService,
this.main.folderApiService, this.serviceContainer.folderApiService,
); );
const response = await command.run(object, id, encodedJson, cmd); const response = await command.run(object, id, encodedJson, cmd);
this.processResponse(response); this.processResponse(response);
@@ -312,11 +307,11 @@ export class VaultProgram extends Program {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new DeleteCommand( const command = new DeleteCommand(
this.main.cipherService, this.serviceContainer.cipherService,
this.main.folderService, this.serviceContainer.folderService,
this.main.apiService, this.serviceContainer.apiService,
this.main.folderApiService, this.serviceContainer.folderApiService,
this.main.billingAccountProfileStateService, this.serviceContainer.billingAccountProfileStateService,
); );
const response = await command.run(object, id, cmd); const response = await command.run(object, id, cmd);
this.processResponse(response); this.processResponse(response);
@@ -341,7 +336,7 @@ export class VaultProgram extends Program {
} }
await this.exitIfLocked(); await this.exitIfLocked();
const command = new RestoreCommand(this.main.cipherService); const command = new RestoreCommand(this.serviceContainer.cipherService);
const response = await command.run(object, id); const response = await command.run(object, id);
this.processResponse(response); this.processResponse(response);
}); });
@@ -379,7 +374,7 @@ export class VaultProgram extends Program {
}) })
.action(async (id, organizationId, encodedJson, cmd) => { .action(async (id, organizationId, encodedJson, cmd) => {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new ShareCommand(this.main.cipherService); const command = new ShareCommand(this.serviceContainer.cipherService);
const response = await command.run(id, organizationId, encodedJson); const response = await command.run(id, organizationId, encodedJson);
this.processResponse(response); this.processResponse(response);
}); });
@@ -408,9 +403,9 @@ export class VaultProgram extends Program {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new ConfirmCommand( const command = new ConfirmCommand(
this.main.apiService, this.serviceContainer.apiService,
this.main.cryptoService, this.serviceContainer.cryptoService,
this.main.organizationUserService, this.serviceContainer.organizationUserService,
); );
const response = await command.run(object, id, cmd); const response = await command.run(object, id, cmd);
this.processResponse(response); this.processResponse(response);
@@ -437,9 +432,9 @@ export class VaultProgram extends Program {
.action(async (format, filepath, options) => { .action(async (format, filepath, options) => {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new ImportCommand( const command = new ImportCommand(
this.main.importService, this.serviceContainer.importService,
this.main.organizationService, this.serviceContainer.organizationService,
this.main.syncService, this.serviceContainer.syncService,
); );
const response = await command.run(format, filepath, options); const response = await command.run(format, filepath, options);
this.processResponse(response); this.processResponse(response);
@@ -484,9 +479,9 @@ export class VaultProgram extends Program {
.action(async (options) => { .action(async (options) => {
await this.exitIfLocked(); await this.exitIfLocked();
const command = new ExportCommand( const command = new ExportCommand(
this.main.exportService, this.serviceContainer.exportService,
this.main.policyService, this.serviceContainer.policyService,
this.main.eventCollectionService, this.serviceContainer.eventCollectionService,
); );
const response = await command.run(options); const response = await command.run(options);
this.processResponse(response); this.processResponse(response);

View File

@@ -92,7 +92,9 @@ export class ElectronCryptoService extends CryptoService {
if (keySuffix === KeySuffixOptions.Biometric) { if (keySuffix === KeySuffixOptions.Biometric) {
await this.migrateBiometricKeyIfNeeded(userId); await this.migrateBiometricKeyIfNeeded(userId);
const userKey = await this.stateService.getUserKeyBiometric({ userId: userId }); const userKey = await this.stateService.getUserKeyBiometric({ userId: userId });
return new SymmetricCryptoKey(Utils.fromB64ToArray(userKey)) as UserKey; return userKey == null
? null
: (new SymmetricCryptoKey(Utils.fromB64ToArray(userKey)) as UserKey);
} }
return await super.getKeyFromStorage(keySuffix, userId); return await super.getKeyFromStorage(keySuffix, userId);
} }
@@ -169,7 +171,9 @@ export class ElectronCryptoService extends CryptoService {
// decrypt // decrypt
const masterKey = new SymmetricCryptoKey(Utils.fromB64ToArray(oldBiometricKey)) as MasterKey; const masterKey = new SymmetricCryptoKey(Utils.fromB64ToArray(oldBiometricKey)) as MasterKey;
userId ??= (await firstValueFrom(this.accountService.activeAccount$))?.id; userId ??= (await firstValueFrom(this.accountService.activeAccount$))?.id;
const encUserKeyPrim = await this.stateService.getEncryptedCryptoSymmetricKey(); const encUserKeyPrim = await this.stateService.getEncryptedCryptoSymmetricKey({
userId: userId,
});
const encUserKey = const encUserKey =
encUserKeyPrim != null encUserKeyPrim != null
? new EncString(encUserKeyPrim) ? new EncString(encUserKeyPrim)
@@ -180,6 +184,7 @@ export class ElectronCryptoService extends CryptoService {
const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey( const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(
masterKey, masterKey,
encUserKey, encUserKey,
userId,
); );
// migrate // migrate
await this.storeBiometricKey(userKey, userId); await this.storeBiometricKey(userKey, userId);

View File

@@ -0,0 +1,5 @@
{
"env": {
"node": true
}
}

View File

@@ -0,0 +1,16 @@
const { pathsToModuleNameMapper } = require("ts-jest");
const { compilerOptions } = require("./tsconfig");
const sharedConfig = require("../../libs/shared/jest.config.ts");
/** @type {import('jest').Config} */
module.exports = {
...sharedConfig,
preset: "ts-jest",
testEnvironment: "node",
setupFilesAfterEnv: ["<rootDir>/../../apps/cli/test.setup.ts"],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
prefix: "<rootDir>/",
}),
};

View File

@@ -0,0 +1,5 @@
describe("Jest", () => {
it("is set up", () => {
expect(true).toBeTruthy();
});
});

View File

@@ -0,0 +1,20 @@
import { program } from "commander";
import { registerOssPrograms } from "@bitwarden/cli/register-oss-programs";
import { registerBitPrograms } from "./register-bit-programs";
import { ServiceContainer } from "./service-container";
async function main() {
const serviceContainer = new ServiceContainer();
await serviceContainer.init();
await registerOssPrograms(serviceContainer);
await registerBitPrograms(serviceContainer);
program.parse(process.argv);
}
// Node does not support top-level await statements until ES2022, esnext, etc which we don't use yet
// eslint-disable-next-line @typescript-eslint/no-floating-promises
main();

View File

@@ -0,0 +1,10 @@
import { ServiceContainer } from "./service-container";
/**
* All Bitwarden-licensed programs should be registered here.
* @example
* const myProgram = new myProgram(serviceContainer);
* myProgram.register();
* @param serviceContainer A class that instantiates services and makes them available for dependency injection
*/
export async function registerBitPrograms(serviceContainer: ServiceContainer) {}

View File

@@ -0,0 +1,7 @@
import { ServiceContainer } from "./service-container";
describe("ServiceContainer", () => {
it("instantiates", async () => {
expect(() => new ServiceContainer()).not.toThrow();
});
});

View File

@@ -0,0 +1,7 @@
import { ServiceContainer as OssServiceContainer } from "@bitwarden/cli/service-container";
/**
* Instantiates services and makes them available for dependency injection.
* Any Bitwarden-licensed services should be registered here.
*/
export class ServiceContainer extends OssServiceContainer {}

View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
"pretty": true,
"moduleResolution": "node",
"target": "ES2016",
"module": "es6",
"noImplicitAny": true,
"allowSyntheticDefaultImports": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowJs": true,
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@bitwarden/cli/*": ["../../apps/cli/src/*"],
"@bitwarden/common/spec": ["../../libs/common/spec"],
"@bitwarden/auth/common": ["../../libs/auth/src/common"],
"@bitwarden/auth/angular": ["../../libs/auth/src/angular"],
"@bitwarden/common/*": ["../../libs/common/src/*"],
"@bitwarden/importer/core": ["../../libs/importer/src"],
"@bitwarden/vault-export-core": [
"../../libs/tools/export/vault-export/vault-export-core/src"
],
"@bitwarden/node/*": ["../../libs/node/src/*"]
}
},
"include": ["src", "src/**/*.spec.ts"]
}

View File

@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"files": ["../../apps/cli/test.setup.ts"]
}

View File

@@ -0,0 +1,12 @@
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
// Re-use the OSS CLI webpack config
const webpackConfig = require("../../apps/cli/webpack.config");
// Update paths to use the bit-cli entrypoint and tsconfig
webpackConfig.entry = { bw: "../../bitwarden_license/bit-cli/src/bw.ts" };
webpackConfig.resolve.plugins = [
new TsconfigPathsPlugin({ configFile: "../../bitwarden_license/bit-cli/tsconfig.json" }),
];
module.exports = webpackConfig;

View File

@@ -16,6 +16,10 @@
"name": "cli", "name": "cli",
"path": "apps/cli", "path": "apps/cli",
}, },
{
"name": "cli (bit)",
"path": "bitwarden_license/bit-cli",
},
{ {
"name": "desktop", "name": "desktop",
"path": "apps/desktop", "path": "apps/desktop",

View File

@@ -21,6 +21,7 @@ module.exports = {
"<rootDir>/apps/desktop/jest.config.js", "<rootDir>/apps/desktop/jest.config.js",
"<rootDir>/apps/web/jest.config.js", "<rootDir>/apps/web/jest.config.js",
"<rootDir>/bitwarden_license/bit-web/jest.config.js", "<rootDir>/bitwarden_license/bit-web/jest.config.js",
"<rootDir>/bitwarden_license/bit-cli/jest.config.js",
"<rootDir>/libs/admin-console/jest.config.js", "<rootDir>/libs/admin-console/jest.config.js",
"<rootDir>/libs/angular/jest.config.js", "<rootDir>/libs/angular/jest.config.js",