mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
* Passed in userId on RemovePasswordComponent. * Added userId on other references to KeyConnectorService methods * remove password component refactor, test coverage, enabled strict * explicit user id provided to key connector service * redirect to / instead when user not logged in or not managing organization * key connector service explicit user id * key connector service no longer requires account service * key connector service missing null type * cli convert to key connector unit tests * remove unnecessary SyncService * error toast not showing on ErrorResponse * bad import due to merge conflict * bad import due to merge conflict * missing loading in remove password component for browser extension * error handling in remove password component * organization observable race condition in key-connector * usesKeyConnector always returns boolean * unit test coverage * key connector reactive * reactive key connector service * introducing convertAccountRequired$ * cli build fix * moving message sending side effect to sync * key connector service unit tests * fix unit tests * move key connector components to KM team ownership * new unit tests in wrong place * key connector domain shown in remove password component * type safety improvements * convert to key connector command localization * key connector domain in convert to key connector command * convert to key connector command unit tests with prompt assert * organization name placement change in the remove password component * unit test update * key connector url required to be provided when migrating user * unit tests in wrong place after KM code ownership move * infinite page reload * failing unit tests * failing unit tests --------- Co-authored-by: Todd Martin <tmartin@bitwarden.com>
128 lines
5.1 KiB
TypeScript
128 lines
5.1 KiB
TypeScript
// FIXME: Update this file to be type safe and remove this and next line
|
|
// @ts-strict-ignore
|
|
import { firstValueFrom, map } from "rxjs";
|
|
|
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
|
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
|
import { MasterPasswordVerification } from "@bitwarden/common/auth/types/verification";
|
|
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
|
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service";
|
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
|
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
|
import { MasterKey } from "@bitwarden/common/types/key";
|
|
import { KeyService } from "@bitwarden/key-management";
|
|
|
|
import { ConvertToKeyConnectorCommand } from "../../key-management/convert-to-key-connector.command";
|
|
import { Response } from "../../models/response";
|
|
import { MessageResponse } from "../../models/response/message.response";
|
|
import { I18nService } from "../../platform/services/i18n.service";
|
|
import { CliUtils } from "../../utils";
|
|
|
|
export class UnlockCommand {
|
|
constructor(
|
|
private accountService: AccountService,
|
|
private masterPasswordService: InternalMasterPasswordServiceAbstraction,
|
|
private keyService: KeyService,
|
|
private userVerificationService: UserVerificationService,
|
|
private cryptoFunctionService: CryptoFunctionService,
|
|
private logService: ConsoleLogService,
|
|
private keyConnectorService: KeyConnectorService,
|
|
private environmentService: EnvironmentService,
|
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
|
private logout: () => Promise<void>,
|
|
private i18nService: I18nService,
|
|
) {}
|
|
|
|
async run(password: string, cmdOptions: Record<string, any>) {
|
|
const normalizedOptions = new Options(cmdOptions);
|
|
const passwordResult = await CliUtils.getPassword(password, normalizedOptions, this.logService);
|
|
|
|
if (passwordResult instanceof Response) {
|
|
return passwordResult;
|
|
} else {
|
|
password = passwordResult;
|
|
}
|
|
|
|
await this.setNewSessionKey();
|
|
const [userId, email] = await firstValueFrom(
|
|
this.accountService.activeAccount$.pipe(map((a) => [a?.id, a?.email])),
|
|
);
|
|
|
|
const verification = {
|
|
type: VerificationType.MasterPassword,
|
|
secret: password,
|
|
} as MasterPasswordVerification;
|
|
|
|
let masterKey: MasterKey;
|
|
try {
|
|
const response = await this.userVerificationService.verifyUserByMasterPassword(
|
|
verification,
|
|
userId,
|
|
email,
|
|
);
|
|
masterKey = response.masterKey;
|
|
} catch (e) {
|
|
// verification failure throws
|
|
return Response.error(e.message);
|
|
}
|
|
|
|
const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey, userId);
|
|
await this.keyService.setUserKey(userKey, userId);
|
|
|
|
if (await firstValueFrom(this.keyConnectorService.convertAccountRequired$)) {
|
|
const convertToKeyConnectorCommand = new ConvertToKeyConnectorCommand(
|
|
userId,
|
|
this.keyConnectorService,
|
|
this.environmentService,
|
|
this.organizationApiService,
|
|
this.logout,
|
|
this.i18nService,
|
|
);
|
|
const convertResponse = await convertToKeyConnectorCommand.run();
|
|
if (!convertResponse.success) {
|
|
return convertResponse;
|
|
}
|
|
}
|
|
|
|
return this.successResponse();
|
|
}
|
|
|
|
private async setNewSessionKey() {
|
|
const key = await this.cryptoFunctionService.randomBytes(64);
|
|
process.env.BW_SESSION = Utils.fromBufferToB64(key);
|
|
}
|
|
|
|
private async successResponse() {
|
|
const res = new MessageResponse(
|
|
"Your vault is now unlocked!",
|
|
"\n" +
|
|
"To unlock your vault, set your session key to the `BW_SESSION` environment variable. ex:\n" +
|
|
'$ export BW_SESSION="' +
|
|
process.env.BW_SESSION +
|
|
'"\n' +
|
|
'> $env:BW_SESSION="' +
|
|
process.env.BW_SESSION +
|
|
'"\n\n' +
|
|
"You can also pass the session key to any command with the `--session` option. ex:\n" +
|
|
"$ bw list items --session " +
|
|
process.env.BW_SESSION,
|
|
);
|
|
res.raw = process.env.BW_SESSION;
|
|
return Response.success(res);
|
|
}
|
|
}
|
|
|
|
class Options {
|
|
passwordEnv: string;
|
|
passwordFile: string;
|
|
|
|
constructor(passedOptions: Record<string, any>) {
|
|
this.passwordEnv = passedOptions?.passwordenv || passedOptions?.passwordEnv;
|
|
this.passwordFile = passedOptions?.passwordfile || passedOptions?.passwordFile;
|
|
}
|
|
}
|