lock/unlock commands

This commit is contained in:
Kyle Spearrin 2018-05-16 10:25:25 -04:00
parent e7782b2082
commit 8d66118b19
5 changed files with 101 additions and 20 deletions

2
jslib

@ -1 +1 @@
Subproject commit 799c90af1702c681874cb8fce8f8adcf1049d0c8
Subproject commit e6fde2e92be4be472933234daa7bae242ee17794

View File

@ -78,8 +78,7 @@ export class Main {
this.collectionService = new CollectionService(this.cryptoService, this.userService, this.storageService,
this.i18nService);
this.lockService = new LockService(this.cipherService, this.folderService, this.collectionService,
this.cryptoService, this.platformUtilsService, this.storageService, this.messagingService,
() => { /* do nothing */ });
this.cryptoService, this.platformUtilsService, this.storageService, this.messagingService, null);
this.syncService = new SyncService(this.userService, this.apiService, this.settingsService,
this.folderService, this.cipherService, this.cryptoService, this.collectionService,
this.storageService, this.messagingService, async (expired: boolean) => await this.logout());

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -9,9 +9,11 @@ import { EditCommand } from './commands/edit.command';
import { EncodeCommand } from './commands/encode.command';
import { GetCommand } from './commands/get.command';
import { ListCommand } from './commands/list.command';
import { LockCommand } from './commands/lock.command';
import { LoginCommand } from './commands/login.command';
import { LogoutCommand } from './commands/logout.command';
import { SyncCommand } from './commands/sync.command';
import { UnlockCommand } from './commands/unlock.command';
import { Response } from './models/response';
import { ListResponse } from './models/response/listResponse';
@ -53,7 +55,7 @@ export class Program {
const command = new LoginCommand(this.main.authService, this.main.apiService,
this.main.cryptoFunctionService);
const response = await command.run(email, password, cmd);
this.processResponse(response, cmd);
this.processResponse(response);
});
program
@ -63,7 +65,7 @@ export class Program {
await this.exitIfNotAuthed();
const command = new LogoutCommand(this.main.authService, async () => await this.main.logout());
const response = await command.run(cmd);
this.processResponse(response, cmd);
this.processResponse(response);
});
program
@ -71,15 +73,20 @@ export class Program {
.description('Lock the vault and destroy the current session token.')
.action(async (cmd) => {
await this.exitIfNotAuthed();
// TODO
const command = new LockCommand(this.main.lockService);
const response = await command.run(cmd);
this.processResponse(response);
});
program
.command('unlock [password]')
.description('Unlock the vault and obtain a new session token.')
.action(async (cmd) => {
.action(async (password, cmd) => {
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
@ -90,7 +97,7 @@ export class Program {
await this.exitIfLocked();
const command = new SyncCommand(this.main.syncService);
const response = await command.run(cmd);
this.processResponse(response, cmd);
this.processResponse(response);
});
program
@ -101,7 +108,7 @@ export class Program {
const command = new ListCommand(this.main.cipherService, this.main.folderService,
this.main.collectionService);
const response = await command.run(object, cmd);
this.processResponse(response, cmd);
this.processResponse(response);
});
program
@ -118,7 +125,7 @@ export class Program {
this.main.collectionService, this.main.totpService, this.main.syncService,
this.main.passwordGenerationService);
const response = await command.run(object, id, cmd);
this.processResponse(response, cmd);
this.processResponse(response);
});
program
@ -128,7 +135,7 @@ export class Program {
await this.exitIfLocked();
const command = new CreateCommand(this.main.cipherService, this.main.folderService);
const response = await command.run(object, encodedData, cmd);
this.processResponse(response, cmd);
this.processResponse(response);
});
program
@ -138,7 +145,7 @@ export class Program {
await this.exitIfLocked();
const command = new EditCommand(this.main.cipherService, this.main.folderService);
const response = await command.run(object, id, encodedData, cmd);
this.processResponse(response, cmd);
this.processResponse(response);
});
program
@ -148,7 +155,7 @@ export class Program {
await this.exitIfLocked();
const command = new DeleteCommand(this.main.cipherService, this.main.folderService);
const response = await command.run(object, id, cmd);
this.processResponse(response, cmd);
this.processResponse(response);
});
program
@ -157,14 +164,21 @@ export class Program {
.action(async (object, id, cmd) => {
const command = new EncodeCommand();
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
.parse(process.argv);
}
private processResponse(response: Response, cmd: program.Command) {
private processResponse(response: Response) {
if (!response.success) {
process.stdout.write(chalk.redBright(response.message));
process.exit(1);
@ -179,13 +193,13 @@ export class Program {
out = data;
}
} 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') {
out = this.getJson((response.data as TemplateResponse).template, cmd);
out = this.getJson((response.data as TemplateResponse).template);
} else if (response.data.object === 'message') {
out = this.getMessage(response);
} else {
out = this.getJson(response.data, cmd);
out = this.getJson(response.data);
}
if (out != null) {
@ -195,7 +209,7 @@ export class Program {
process.exit();
}
private getJson(obj: any, cmd: program.Command): string {
private getJson(obj: any): string {
if (process.env.BW_PRETTY === 'true') {
return JSON.stringify(obj, null, ' ');
} else {