1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-20 16:07:45 +01:00
bitwarden-browser/apps/cli/src/base-program.ts
Bernd Schoolmann b486fcc689
[Pm-13097] Rename cryptoservice to keyservice and move it to km ownership (#11358)
* Rename cryptoservice to keyservice

* Rename cryptoservice to keyservice

* Move key service to key management ownership

* Remove accidentally added file

* Fix cli build

* Fix browser build

* Run prettier

* Fix builds

* Fix cli build

* Fix tests

* Fix incorrect renames

* Rename webauthn-login-crypto-service

* Fix build errors due to merge conflicts

* Fix linting
2024-10-24 19:41:30 +02:00

201 lines
6.4 KiB
TypeScript

import * as chalk from "chalk";
import { firstValueFrom, map } from "rxjs";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { UserId } from "@bitwarden/common/types/guid";
import { UnlockCommand } from "./auth/commands/unlock.command";
import { Response } from "./models/response";
import { ListResponse } from "./models/response/list.response";
import { MessageResponse } from "./models/response/message.response";
import { StringResponse } from "./models/response/string.response";
import { TemplateResponse } from "./models/response/template.response";
import { ServiceContainer } from "./service-container/service-container";
import { CliUtils } from "./utils";
const writeLn = CliUtils.writeLn;
export abstract class BaseProgram {
constructor(protected serviceContainer: ServiceContainer) {}
protected processResponse(response: Response, exitImmediately = false) {
if (!response.success) {
if (process.env.BW_QUIET !== "true") {
if (process.env.BW_RESPONSE === "true") {
writeLn(this.getJson(response), true, false);
} else {
writeLn(chalk.redBright(response.message), true, true);
}
}
const exitCode = process.env.BW_CLEANEXIT ? 0 : 1;
if (exitImmediately) {
process.exit(exitCode);
} else {
process.exitCode = exitCode;
}
return;
}
if (process.env.BW_RESPONSE === "true") {
writeLn(this.getJson(response), true, false);
} else if (response.data != null) {
let out: string = null;
if (response.data.object === "template") {
out = this.getJson((response.data as TemplateResponse).template);
}
if (out == null) {
if (response.data.object === "string") {
const data = (response.data as StringResponse).data;
if (data != null) {
out = data;
}
} else if (response.data.object === "list") {
out = this.getJson((response.data as ListResponse).data);
} else if (response.data.object === "message") {
out = this.getMessage(response);
} else {
out = this.getJson(response.data);
}
}
if (out != null && process.env.BW_QUIET !== "true") {
writeLn(out, true, false);
}
}
if (exitImmediately) {
process.exit(0);
} else {
process.exitCode = 0;
}
}
private getJson(obj: any): string {
if (process.env.BW_PRETTY === "true") {
return JSON.stringify(obj, null, " ");
} else {
return JSON.stringify(obj);
}
}
protected getMessage(response: Response): string {
const message = response.data as MessageResponse;
if (process.env.BW_RAW === "true") {
return message.raw;
}
let out = "";
if (message.title != null) {
if (message.noColor) {
out = message.title;
} else {
out = chalk.greenBright(message.title);
}
}
if (message.message != null) {
if (message.title != null) {
out += "\n";
}
out += message.message;
}
return out.trim() === "" ? null : out;
}
protected async exitIfAuthed() {
const authed = await firstValueFrom(
this.serviceContainer.authService.activeAccountStatus$.pipe(
map((status) => status > AuthenticationStatus.LoggedOut),
),
);
if (authed) {
const email = await firstValueFrom(
this.serviceContainer.accountService.activeAccount$.pipe(map((a) => a?.email)),
);
this.processResponse(Response.error("You are already logged in as " + email + "."), true);
}
}
/**
* Exist if no user is authenticated
* @returns the userId of the active account
*/
protected async exitIfNotAuthed() {
const fail = () => this.processResponse(Response.error("You are not logged in."), true);
const userId = (await firstValueFrom(this.serviceContainer.accountService.activeAccount$))?.id;
if (!userId) {
fail();
}
const authed = await this.serviceContainer.stateService.getIsAuthenticated({ userId });
if (!authed) {
fail();
}
return userId;
}
protected async exitIfLocked() {
const userId = await this.exitIfNotAuthed();
// If the process.env does not have a BW_SESSION key, then we will never be able to retrieve
// the auto user key from secure storage. This is because the auto user key is encrypted with
// the session key.
const hasUserKey =
await this.serviceContainer.userAutoUnlockKeyService.setUserKeyInMemoryIfAutoUserKeySet(
userId,
);
if (hasUserKey) {
// User is unlocked
return;
}
// User is locked
await this.handleLockedUser(userId);
}
private async handleLockedUser(userId: UserId) {
if (process.env.BW_NOINTERACTION === "true") {
this.processResponse(Response.error("Vault is locked."), true);
return;
}
// must unlock with interaction allowed
if (await this.serviceContainer.keyConnectorService.getUsesKeyConnector(userId)) {
const response = Response.error(
"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.",
);
this.processResponse(response, true);
} else {
const command = new UnlockCommand(
this.serviceContainer.accountService,
this.serviceContainer.masterPasswordService,
this.serviceContainer.keyService,
this.serviceContainer.userVerificationService,
this.serviceContainer.cryptoFunctionService,
this.serviceContainer.logService,
this.serviceContainer.keyConnectorService,
this.serviceContainer.environmentService,
this.serviceContainer.syncService,
this.serviceContainer.organizationApiService,
this.serviceContainer.logout,
);
const response = await command.run(null, null);
if (!response.success) {
this.processResponse(response, true);
}
}
}
protected async exitIfFeatureFlagDisabled(featureFlag: FeatureFlag) {
const enabled = await firstValueFrom(
this.serviceContainer.configService.getFeatureFlag$(featureFlag),
);
if (!enabled) {
this.processResponse(Response.error("This command is temporarily unavailable."), true);
}
}
}