mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-27 12:36:14 +01:00
Fix migration to Key Connector (#452)
* Move Key Connector check to subclass * Move authService.logout call to main program * Move Key Connector migration check to unlock command * Use get/setConvertAccountRequired flag * Move Key Connector convert to own command, set usesKeyConnector after conversion * Remove KC conversion check from syncCommand, fix callback * Make class service private * Fix naming convention * Update jslib and deps
This commit is contained in:
parent
922cd1dc54
commit
8b650666c5
2
jslib
2
jslib
@ -1 +1 @@
|
||||
Subproject commit cc285e5ea729795812d8f1f66f622b67c11efb4a
|
||||
Subproject commit 11e7133aefa4443e07febde9b3add25539ec2287
|
@ -50,6 +50,8 @@ import { Program } from "./program";
|
||||
import { SendProgram } from "./send.program";
|
||||
import { VaultProgram } from "./vault.program";
|
||||
|
||||
import { Account, AccountFactory } from "jslib-common/models/domain/account";
|
||||
|
||||
// Polyfills
|
||||
(global as any).DOMParser = new jsdom.JSDOM().window.DOMParser;
|
||||
|
||||
@ -136,7 +138,8 @@ export class Main {
|
||||
this.storageService,
|
||||
this.secureStorageService,
|
||||
this.logService,
|
||||
this.stateMigrationService
|
||||
this.stateMigrationService,
|
||||
new AccountFactory(Account)
|
||||
);
|
||||
|
||||
this.cryptoService = new CryptoService(
|
||||
@ -328,6 +331,9 @@ export class Main {
|
||||
}
|
||||
|
||||
async logout() {
|
||||
this.authService.logOut(() => {
|
||||
/* Do nothing */
|
||||
});
|
||||
const userId = await this.stateService.getUserId();
|
||||
await Promise.all([
|
||||
this.syncService.setLastSync(new Date(0)),
|
||||
|
85
src/commands/convertToKeyConnector.command.ts
Normal file
85
src/commands/convertToKeyConnector.command.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import * as inquirer from "inquirer";
|
||||
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
|
||||
import { Response } from "jslib-node/cli/models/response";
|
||||
import { MessageResponse } from "jslib-node/cli/models/response/messageResponse";
|
||||
|
||||
export class ConvertToKeyConnectorCommand {
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
private environmentService: EnvironmentService,
|
||||
private syncService: SyncService,
|
||||
private logout: () => Promise<void>
|
||||
) {}
|
||||
|
||||
async run(): Promise<Response> {
|
||||
// If no interaction available, alert user to use web vault
|
||||
const canInteract = process.env.BW_NOINTERACTION !== "true";
|
||||
if (!canInteract) {
|
||||
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.",
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const organization = await this.keyConnectorService.getManagingOrganization();
|
||||
|
||||
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. ",
|
||||
choices: [
|
||||
{
|
||||
name: "Remove master password and unlock",
|
||||
value: "remove",
|
||||
},
|
||||
{
|
||||
name: "Leave organization and unlock",
|
||||
value: "leave",
|
||||
},
|
||||
{
|
||||
name: "Log out",
|
||||
value: "exit",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (answer.convert === "remove") {
|
||||
try {
|
||||
await this.keyConnectorService.migrateUser();
|
||||
} catch (e) {
|
||||
await this.logout();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.keyConnectorService.removeConvertAccountRequired();
|
||||
await this.keyConnectorService.setUsesKeyConnector(true);
|
||||
|
||||
// Update environment URL - required for api key login
|
||||
const urls = this.environmentService.getUrls();
|
||||
urls.keyConnector = organization.keyConnectorUrl;
|
||||
await this.environmentService.setUrls(urls, true);
|
||||
|
||||
return Response.success();
|
||||
} else if (answer.convert === "leave") {
|
||||
await this.apiService.postLeaveOrganization(organization.id);
|
||||
await this.keyConnectorService.removeConvertAccountRequired();
|
||||
await this.syncService.fullSync(true);
|
||||
return Response.success();
|
||||
} else {
|
||||
await this.logout();
|
||||
return Response.error("You have been logged out.");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import * as program from "commander";
|
||||
import * as inquirer from "inquirer";
|
||||
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
@ -27,7 +26,6 @@ export class LoginCommand extends BaseLoginCommand {
|
||||
authService: AuthService,
|
||||
apiService: ApiService,
|
||||
cryptoFunctionService: CryptoFunctionService,
|
||||
syncService: SyncService,
|
||||
i18nService: I18nService,
|
||||
environmentService: EnvironmentService,
|
||||
passwordGenerationService: PasswordGenerationService,
|
||||
@ -35,7 +33,8 @@ export class LoginCommand extends BaseLoginCommand {
|
||||
stateService: StateService,
|
||||
cryptoService: CryptoService,
|
||||
policyService: PolicyService,
|
||||
keyConnectorService: KeyConnectorService,
|
||||
private syncService: SyncService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
private logoutCallback: () => Promise<void>
|
||||
) {
|
||||
super(
|
||||
@ -49,9 +48,7 @@ export class LoginCommand extends BaseLoginCommand {
|
||||
stateService,
|
||||
cryptoService,
|
||||
policyService,
|
||||
"cli",
|
||||
syncService,
|
||||
keyConnectorService
|
||||
"cli"
|
||||
);
|
||||
this.logout = this.logoutCallback;
|
||||
this.validatedParams = async () => {
|
||||
@ -59,6 +56,8 @@ export class LoginCommand extends BaseLoginCommand {
|
||||
process.env.BW_SESSION = Utils.fromBufferToB64(key);
|
||||
};
|
||||
this.success = async () => {
|
||||
await this.syncService.fullSync(true);
|
||||
|
||||
const usesKeyConnector = await this.keyConnectorService.getUsesKeyConnector();
|
||||
|
||||
if (
|
||||
|
@ -107,7 +107,11 @@ export class ServeCommand {
|
||||
this.main.stateService,
|
||||
this.main.cryptoFunctionService,
|
||||
this.main.apiService,
|
||||
this.main.logService
|
||||
this.main.logService,
|
||||
this.main.keyConnectorService,
|
||||
this.main.environmentService,
|
||||
this.main.syncService,
|
||||
async () => await this.main.logout()
|
||||
);
|
||||
|
||||
this.sendCreateCommand = new SendCreateCommand(
|
||||
|
@ -3,7 +3,10 @@ import * as inquirer from "inquirer";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
|
||||
import { Response } from "jslib-node/cli/models/response";
|
||||
import { MessageResponse } from "jslib-node/cli/models/response/messageResponse";
|
||||
@ -16,13 +19,19 @@ import { HashPurpose } from "jslib-common/enums/hashPurpose";
|
||||
import { NodeUtils } from "jslib-common/misc/nodeUtils";
|
||||
import { ConsoleLogService } from "jslib-common/services/consoleLog.service";
|
||||
|
||||
import { ConvertToKeyConnectorCommand } from "./convertToKeyConnector.command";
|
||||
|
||||
export class UnlockCommand {
|
||||
constructor(
|
||||
private cryptoService: CryptoService,
|
||||
private stateService: StateService,
|
||||
private cryptoFunctionService: CryptoFunctionService,
|
||||
private apiService: ApiService,
|
||||
private logService: ConsoleLogService
|
||||
private logService: ConsoleLogService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
private environmentService: EnvironmentService,
|
||||
private syncService: SyncService,
|
||||
private logout: () => Promise<void>
|
||||
) {}
|
||||
|
||||
async run(password: string, cmdOptions: Record<string, any>) {
|
||||
@ -92,22 +101,22 @@ export class UnlockCommand {
|
||||
|
||||
if (passwordValid) {
|
||||
await this.cryptoService.setKey(key);
|
||||
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);
|
||||
|
||||
if (await this.keyConnectorService.getConvertAccountRequired()) {
|
||||
const convertToKeyConnectorCommand = new ConvertToKeyConnectorCommand(
|
||||
this.apiService,
|
||||
this.keyConnectorService,
|
||||
this.environmentService,
|
||||
this.syncService,
|
||||
this.logout
|
||||
);
|
||||
const convertResponse = await convertToKeyConnectorCommand.run();
|
||||
if (!convertResponse.success) {
|
||||
return convertResponse;
|
||||
}
|
||||
}
|
||||
|
||||
return this.successResponse();
|
||||
} else {
|
||||
return Response.error("Invalid master password.");
|
||||
}
|
||||
@ -117,6 +126,25 @@ export class UnlockCommand {
|
||||
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 {
|
||||
|
@ -149,7 +149,6 @@ export class Program extends BaseProgram {
|
||||
this.main.authService,
|
||||
this.main.apiService,
|
||||
this.main.cryptoFunctionService,
|
||||
this.main.syncService,
|
||||
this.main.i18nService,
|
||||
this.main.environmentService,
|
||||
this.main.passwordGenerationService,
|
||||
@ -157,6 +156,7 @@ export class Program extends BaseProgram {
|
||||
this.main.stateService,
|
||||
this.main.cryptoService,
|
||||
this.main.policyService,
|
||||
this.main.syncService,
|
||||
this.main.keyConnectorService,
|
||||
async () => await this.main.logout()
|
||||
);
|
||||
@ -257,7 +257,11 @@ export class Program extends BaseProgram {
|
||||
this.main.stateService,
|
||||
this.main.cryptoFunctionService,
|
||||
this.main.apiService,
|
||||
this.main.logService
|
||||
this.main.logService,
|
||||
this.main.keyConnectorService,
|
||||
this.main.environmentService,
|
||||
this.main.syncService,
|
||||
async () => await this.main.logout()
|
||||
);
|
||||
const response = await command.run(password, cmd);
|
||||
this.processResponse(response);
|
||||
@ -511,7 +515,11 @@ export class Program extends BaseProgram {
|
||||
this.main.stateService,
|
||||
this.main.cryptoFunctionService,
|
||||
this.main.apiService,
|
||||
this.main.logService
|
||||
this.main.logService,
|
||||
this.main.keyConnectorService,
|
||||
this.main.environmentService,
|
||||
this.main.syncService,
|
||||
this.main.logout
|
||||
);
|
||||
const response = await command.run(null, null);
|
||||
if (!response.success) {
|
||||
|
Loading…
Reference in New Issue
Block a user