lock/unlock commands
This commit is contained in:
parent
e7782b2082
commit
8d66118b19
2
jslib
2
jslib
|
@ -1 +1 @@
|
||||||
Subproject commit 799c90af1702c681874cb8fce8f8adcf1049d0c8
|
Subproject commit e6fde2e92be4be472933234daa7bae242ee17794
|
|
@ -78,8 +78,7 @@ export class Main {
|
||||||
this.collectionService = new CollectionService(this.cryptoService, this.userService, this.storageService,
|
this.collectionService = new CollectionService(this.cryptoService, this.userService, this.storageService,
|
||||||
this.i18nService);
|
this.i18nService);
|
||||||
this.lockService = new LockService(this.cipherService, this.folderService, this.collectionService,
|
this.lockService = new LockService(this.cipherService, this.folderService, this.collectionService,
|
||||||
this.cryptoService, this.platformUtilsService, this.storageService, this.messagingService,
|
this.cryptoService, this.platformUtilsService, this.storageService, this.messagingService, null);
|
||||||
() => { /* do nothing */ });
|
|
||||||
this.syncService = new SyncService(this.userService, this.apiService, this.settingsService,
|
this.syncService = new SyncService(this.userService, this.apiService, this.settingsService,
|
||||||
this.folderService, this.cipherService, this.cryptoService, this.collectionService,
|
this.folderService, this.cipherService, this.cryptoService, this.collectionService,
|
||||||
this.storageService, this.messagingService, async (expired: boolean) => await this.logout());
|
this.storageService, this.messagingService, async (expired: boolean) => await this.logout());
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import * as program from 'commander';
|
||||||
|
|
||||||
|
import { LockService } from 'jslib/abstractions/lock.service';
|
||||||
|
|
||||||
|
import { Response } from '../models/response';
|
||||||
|
import { MessageResponse } from '../models/response/messageResponse';
|
||||||
|
|
||||||
|
export class LockCommand {
|
||||||
|
constructor(private lockService: LockService) { }
|
||||||
|
|
||||||
|
async run(cmd: program.Command) {
|
||||||
|
await this.lockService.lock();
|
||||||
|
process.env.BW_SESSION = null;
|
||||||
|
const res = new MessageResponse('Your vault is locked.', null);
|
||||||
|
return Response.success(res);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
import * as program from 'commander';
|
||||||
|
import * as readline from 'readline-sync';
|
||||||
|
|
||||||
|
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||||
|
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
|
||||||
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
|
|
||||||
|
import { Response } from '../models/response';
|
||||||
|
import { MessageResponse } from '../models/response/messageResponse';
|
||||||
|
|
||||||
|
import { Utils } from 'jslib/misc/utils';
|
||||||
|
|
||||||
|
export class UnlockCommand {
|
||||||
|
constructor(private cryptoService: CryptoService, private userService: UserService,
|
||||||
|
private cryptoFunctionService: CryptoFunctionService) { }
|
||||||
|
|
||||||
|
async run(password: string, cmd: program.Command) {
|
||||||
|
if (password == null || password === '') {
|
||||||
|
password = readline.question('Master password: ', {
|
||||||
|
hideEchoBack: true,
|
||||||
|
mask: '*',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (password == null || password === '') {
|
||||||
|
return Response.badRequest('Master password is required.');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setNewSessionKey();
|
||||||
|
const email = await this.userService.getEmail();
|
||||||
|
const key = await this.cryptoService.makeKey(password, email);
|
||||||
|
const keyHash = await this.cryptoService.hashPassword(password, key);
|
||||||
|
const storedKeyHash = await this.cryptoService.getKeyHash();
|
||||||
|
if (storedKeyHash != null && keyHash != null && storedKeyHash === keyHash) {
|
||||||
|
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\n' +
|
||||||
|
'You can also pass the session key to any command with the `--session` option. ex:\n' +
|
||||||
|
'$ bw get items --session ' + process.env.BW_SESSION);
|
||||||
|
res.raw = process.env.BW_SESSION;
|
||||||
|
return Response.success(res);
|
||||||
|
} else {
|
||||||
|
return Response.error('Invalid master password.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async setNewSessionKey() {
|
||||||
|
const key = await this.cryptoFunctionService.randomBytes(64);
|
||||||
|
process.env.BW_SESSION = Utils.fromBufferToB64(key);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,9 +9,11 @@ import { EditCommand } from './commands/edit.command';
|
||||||
import { EncodeCommand } from './commands/encode.command';
|
import { EncodeCommand } from './commands/encode.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';
|
||||||
|
import { LockCommand } from './commands/lock.command';
|
||||||
import { LoginCommand } from './commands/login.command';
|
import { LoginCommand } from './commands/login.command';
|
||||||
import { LogoutCommand } from './commands/logout.command';
|
import { LogoutCommand } from './commands/logout.command';
|
||||||
import { SyncCommand } from './commands/sync.command';
|
import { SyncCommand } from './commands/sync.command';
|
||||||
|
import { UnlockCommand } from './commands/unlock.command';
|
||||||
|
|
||||||
import { Response } from './models/response';
|
import { Response } from './models/response';
|
||||||
import { ListResponse } from './models/response/listResponse';
|
import { ListResponse } from './models/response/listResponse';
|
||||||
|
@ -53,7 +55,7 @@ export class Program {
|
||||||
const command = new LoginCommand(this.main.authService, this.main.apiService,
|
const command = new LoginCommand(this.main.authService, this.main.apiService,
|
||||||
this.main.cryptoFunctionService);
|
this.main.cryptoFunctionService);
|
||||||
const response = await command.run(email, password, cmd);
|
const response = await command.run(email, password, cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -63,7 +65,7 @@ export class Program {
|
||||||
await this.exitIfNotAuthed();
|
await this.exitIfNotAuthed();
|
||||||
const command = new LogoutCommand(this.main.authService, async () => await this.main.logout());
|
const command = new LogoutCommand(this.main.authService, async () => await this.main.logout());
|
||||||
const response = await command.run(cmd);
|
const response = await command.run(cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -71,15 +73,20 @@ export class Program {
|
||||||
.description('Lock the vault and destroy the current session token.')
|
.description('Lock the vault and destroy the current session token.')
|
||||||
.action(async (cmd) => {
|
.action(async (cmd) => {
|
||||||
await this.exitIfNotAuthed();
|
await this.exitIfNotAuthed();
|
||||||
// TODO
|
const command = new LockCommand(this.main.lockService);
|
||||||
|
const response = await command.run(cmd);
|
||||||
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('unlock [password]')
|
.command('unlock [password]')
|
||||||
.description('Unlock the vault and obtain a new session token.')
|
.description('Unlock the vault and obtain a new session token.')
|
||||||
.action(async (cmd) => {
|
.action(async (password, cmd) => {
|
||||||
await this.exitIfNotAuthed();
|
await this.exitIfNotAuthed();
|
||||||
// TODO
|
const command = new UnlockCommand(this.main.cryptoService, this.main.userService,
|
||||||
|
this.main.cryptoFunctionService);
|
||||||
|
const response = await command.run(password, cmd);
|
||||||
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -90,7 +97,7 @@ export class Program {
|
||||||
await this.exitIfLocked();
|
await this.exitIfLocked();
|
||||||
const command = new SyncCommand(this.main.syncService);
|
const command = new SyncCommand(this.main.syncService);
|
||||||
const response = await command.run(cmd);
|
const response = await command.run(cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -101,7 +108,7 @@ export class Program {
|
||||||
const command = new ListCommand(this.main.cipherService, this.main.folderService,
|
const command = new ListCommand(this.main.cipherService, this.main.folderService,
|
||||||
this.main.collectionService);
|
this.main.collectionService);
|
||||||
const response = await command.run(object, cmd);
|
const response = await command.run(object, cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -118,7 +125,7 @@ export class Program {
|
||||||
this.main.collectionService, this.main.totpService, this.main.syncService,
|
this.main.collectionService, this.main.totpService, this.main.syncService,
|
||||||
this.main.passwordGenerationService);
|
this.main.passwordGenerationService);
|
||||||
const response = await command.run(object, id, cmd);
|
const response = await command.run(object, id, cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -128,7 +135,7 @@ export class Program {
|
||||||
await this.exitIfLocked();
|
await this.exitIfLocked();
|
||||||
const command = new CreateCommand(this.main.cipherService, this.main.folderService);
|
const command = new CreateCommand(this.main.cipherService, this.main.folderService);
|
||||||
const response = await command.run(object, encodedData, cmd);
|
const response = await command.run(object, encodedData, cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -138,7 +145,7 @@ export class Program {
|
||||||
await this.exitIfLocked();
|
await this.exitIfLocked();
|
||||||
const command = new EditCommand(this.main.cipherService, this.main.folderService);
|
const command = new EditCommand(this.main.cipherService, this.main.folderService);
|
||||||
const response = await command.run(object, id, encodedData, cmd);
|
const response = await command.run(object, id, encodedData, cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -148,7 +155,7 @@ export class Program {
|
||||||
await this.exitIfLocked();
|
await this.exitIfLocked();
|
||||||
const command = new DeleteCommand(this.main.cipherService, this.main.folderService);
|
const command = new DeleteCommand(this.main.cipherService, this.main.folderService);
|
||||||
const response = await command.run(object, id, cmd);
|
const response = await command.run(object, id, cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -157,14 +164,21 @@ export class Program {
|
||||||
.action(async (object, id, cmd) => {
|
.action(async (object, id, cmd) => {
|
||||||
const command = new EncodeCommand();
|
const command = new EncodeCommand();
|
||||||
const response = await command.run(cmd);
|
const response = await command.run(cmd);
|
||||||
this.processResponse(response, cmd);
|
this.processResponse(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('update')
|
||||||
|
.description('Check for updates.')
|
||||||
|
.action(async (object, id, cmd) => {
|
||||||
|
console.log('Checking...');
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
.parse(process.argv);
|
.parse(process.argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
private processResponse(response: Response, cmd: program.Command) {
|
private processResponse(response: Response) {
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
process.stdout.write(chalk.redBright(response.message));
|
process.stdout.write(chalk.redBright(response.message));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -179,13 +193,13 @@ export class Program {
|
||||||
out = data;
|
out = data;
|
||||||
}
|
}
|
||||||
} else if (response.data.object === 'list') {
|
} else if (response.data.object === 'list') {
|
||||||
out = this.getJson((response.data as ListResponse).data, cmd);
|
out = this.getJson((response.data as ListResponse).data);
|
||||||
} else if (response.data.object === 'template') {
|
} else if (response.data.object === 'template') {
|
||||||
out = this.getJson((response.data as TemplateResponse).template, cmd);
|
out = this.getJson((response.data as TemplateResponse).template);
|
||||||
} else if (response.data.object === 'message') {
|
} else if (response.data.object === 'message') {
|
||||||
out = this.getMessage(response);
|
out = this.getMessage(response);
|
||||||
} else {
|
} else {
|
||||||
out = this.getJson(response.data, cmd);
|
out = this.getJson(response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
|
@ -195,7 +209,7 @@ export class Program {
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getJson(obj: any, cmd: program.Command): string {
|
private getJson(obj: any): string {
|
||||||
if (process.env.BW_PRETTY === 'true') {
|
if (process.env.BW_PRETTY === 'true') {
|
||||||
return JSON.stringify(obj, null, ' ');
|
return JSON.stringify(obj, null, ' ');
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue