diff --git a/apps/cli/src/auth/commands/unlock.command.ts b/apps/cli/src/auth/commands/unlock.command.ts index 70533b04132..27e9f29fa34 100644 --- a/apps/cli/src/auth/commands/unlock.command.ts +++ b/apps/cli/src/auth/commands/unlock.command.ts @@ -19,6 +19,7 @@ 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 { @@ -33,6 +34,7 @@ export class UnlockCommand { private environmentService: EnvironmentService, private organizationApiService: OrganizationApiServiceAbstraction, private logout: () => Promise, + private i18nService: I18nService, ) {} async run(password: string, cmdOptions: Record) { @@ -78,6 +80,7 @@ export class UnlockCommand { this.environmentService, this.organizationApiService, this.logout, + this.i18nService, ); const convertResponse = await convertToKeyConnectorCommand.run(); if (!convertResponse.success) { diff --git a/apps/cli/src/base-program.ts b/apps/cli/src/base-program.ts index 40b95df64e4..5719f78c1b9 100644 --- a/apps/cli/src/base-program.ts +++ b/apps/cli/src/base-program.ts @@ -181,6 +181,7 @@ export abstract class BaseProgram { this.serviceContainer.environmentService, this.serviceContainer.organizationApiService, this.serviceContainer.logout, + this.serviceContainer.i18nService, ); const response = await command.run(null, null); if (!response.success) { diff --git a/apps/cli/src/key-management/convert-to-key-connector.command.spec.ts b/apps/cli/src/key-management/convert-to-key-connector.command.spec.ts index 59be187c1c1..13283e81b1c 100644 --- a/apps/cli/src/key-management/convert-to-key-connector.command.spec.ts +++ b/apps/cli/src/key-management/convert-to-key-connector.command.spec.ts @@ -15,6 +15,7 @@ import { UserId } from "@bitwarden/common/types/guid"; import { Response } from "../models/response"; import { MessageResponse } from "../models/response/message.response"; +import { I18nService } from "../platform/services/i18n.service"; import { ConvertToKeyConnectorCommand } from "./convert-to-key-connector.command"; @@ -38,6 +39,7 @@ describe("ConvertToKeyConnectorCommand", () => { const environmentService = mock(); const organizationApiService = mock(); const logout = jest.fn(); + const i18nService = mock(); beforeEach(async () => { command = new ConvertToKeyConnectorCommand( @@ -46,31 +48,30 @@ describe("ConvertToKeyConnectorCommand", () => { environmentService, organizationApiService, logout, + i18nService, ); }); describe("run", () => { it("should logout and return error response if no interaction available", async () => { process.env.BW_NOINTERACTION = "true"; + const errorMessage = + "An organization you are a member of is using Key Connector. In order to access the vault, you must opt-in to Key Connector now via the web vault. You have been logged out."; + i18nService.t.mockReturnValue(errorMessage); const response = await command.run(); expect(response).not.toBeNull(); expect(response.success).toEqual(false); - expect(response).toEqual( - Response.error( - new MessageResponse( - "An organization you are a member of is using Key Connector. In order to access the vault, you must opt-in to Key Connector now via the web vault. You have been logged out.", - null, - ), - ), - ); + expect(response).toEqual(Response.error(new MessageResponse(errorMessage, null))); expect(logout).toHaveBeenCalled(); }); it("should logout and return error response if interaction answer is exit", async () => { process.env.BW_NOINTERACTION = "false"; keyConnectorService.getManagingOrganization.mockResolvedValue(organization); + const errorMessage = "You have been logged out."; + i18nService.t.mockReturnValue(errorMessage); (createPromptModule as jest.Mock).mockImplementation(() => jest.fn(() => Promise.resolve({ convert: "exit" })), @@ -80,7 +81,7 @@ describe("ConvertToKeyConnectorCommand", () => { expect(response).not.toBeNull(); expect(response.success).toEqual(false); - expect(response).toEqual(Response.error("You have been logged out.")); + expect(response).toEqual(Response.error(errorMessage)); expect(logout).toHaveBeenCalled(); }); diff --git a/apps/cli/src/key-management/convert-to-key-connector.command.ts b/apps/cli/src/key-management/convert-to-key-connector.command.ts index 481c23fc5a0..f7801538b33 100644 --- a/apps/cli/src/key-management/convert-to-key-connector.command.ts +++ b/apps/cli/src/key-management/convert-to-key-connector.command.ts @@ -11,6 +11,7 @@ import { UserId } from "@bitwarden/common/types/guid"; import { Response } from "../models/response"; import { MessageResponse } from "../models/response/message.response"; +import { I18nService } from "../platform/services/i18n.service"; export class ConvertToKeyConnectorCommand { constructor( @@ -19,6 +20,7 @@ export class ConvertToKeyConnectorCommand { private environmentService: EnvironmentService, private organizationApiService: OrganizationApiServiceAbstraction, private logout: () => Promise, + private i18nService: I18nService, ) {} async run(): Promise { @@ -28,8 +30,7 @@ export class ConvertToKeyConnectorCommand { await this.logout(); return Response.error( new MessageResponse( - "An organization you are a member of is using Key Connector. " + - "In order to access the vault, you must opt-in to Key Connector now via the web vault. You have been logged out.", + this.i18nService.t("organizationUsingKeyConnectorOptInLoggedOut"), null, ), ); @@ -40,20 +41,21 @@ export class ConvertToKeyConnectorCommand { const answer: inquirer.Answers = await inquirer.createPromptModule({ output: process.stderr })({ type: "list", name: "convert", - message: - organization.name + - " is using a self-hosted key server. A master password is no longer required to log in for members of this organization. ", + message: this.i18nService.t( + "removeMasterPasswordForOrganizationUserKeyConnector", + organization.name, + ), choices: [ { - name: "Remove master password and unlock", + name: this.i18nService.t("removeMasterPasswordAndUnlock"), value: "remove", }, { - name: "Leave organization and unlock", + name: this.i18nService.t("leaveOrganizationAndUnlock"), value: "leave", }, { - name: "Log out", + name: this.i18nService.t("logOut"), value: "exit", }, ], @@ -79,7 +81,7 @@ export class ConvertToKeyConnectorCommand { return Response.success(); } else { await this.logout(); - return Response.error("You have been logged out."); + return Response.error(this.i18nService.t("youHaveBeenLoggedOut")); } } } diff --git a/apps/cli/src/locales/en/messages.json b/apps/cli/src/locales/en/messages.json index a9c7af91524..15844f26485 100644 --- a/apps/cli/src/locales/en/messages.json +++ b/apps/cli/src/locales/en/messages.json @@ -184,5 +184,29 @@ "example": "JustTrust.us" } } + }, + "organizationUsingKeyConnectorOptInLoggedOut": { + "message": "An organization you are a member of is using Key Connector. In order to access the vault, you must opt-in to Key Connector now via the web vault. You have been logged out." + }, + "removeMasterPasswordForOrganizationUserKeyConnector": { + "message": "$ORGANIZATION$ has updated its member decryption options. You no longer need a password when logging into Bitwarden. Please confirm the domain below with your organization administrator.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "removeMasterPasswordAndUnlock": { + "message": "Remove master password and unlock" + }, + "leaveOrganizationAndUnlock": { + "message": "Leave organization and unlock" + }, + "logOut": { + "message": "Log out" + }, + "youHaveBeenLoggedOut": { + "message": "You have been logged out." } } diff --git a/apps/cli/src/oss-serve-configurator.ts b/apps/cli/src/oss-serve-configurator.ts index 81165d8c74e..750a40eb2be 100644 --- a/apps/cli/src/oss-serve-configurator.ts +++ b/apps/cli/src/oss-serve-configurator.ts @@ -144,6 +144,7 @@ export class OssServeConfigurator { this.serviceContainer.environmentService, this.serviceContainer.organizationApiService, async () => await this.serviceContainer.logout(), + this.serviceContainer.i18nService, ); this.sendCreateCommand = new SendCreateCommand( diff --git a/apps/cli/src/program.ts b/apps/cli/src/program.ts index 1f5b928ce0e..a0603d9f796 100644 --- a/apps/cli/src/program.ts +++ b/apps/cli/src/program.ts @@ -279,6 +279,7 @@ export class Program extends BaseProgram { this.serviceContainer.environmentService, this.serviceContainer.organizationApiService, async () => await this.serviceContainer.logout(), + this.serviceContainer.i18nService, ); const response = await command.run(password, cmd); this.processResponse(response);