Added --trash to delete cmd, added restore cmd
This commit is contained in:
parent
6e63a79cfd
commit
49f1fac3ed
2
jslib
2
jslib
|
@ -1 +1 @@
|
||||||
Subproject commit 72e3893f8eee79f1e3678839aa194f1096c343ea
|
Subproject commit e9db844285e21525f5152e782063f04e02543553
|
|
@ -116,9 +116,9 @@ export class Main {
|
||||||
this.i18nService);
|
this.i18nService);
|
||||||
this.searchService = new SearchService(this.cipherService, this.platformUtilsService);
|
this.searchService = new SearchService(this.cipherService, this.platformUtilsService);
|
||||||
this.policyService = new PolicyService(this.userService, this.storageService);
|
this.policyService = new PolicyService(this.userService, this.storageService);
|
||||||
this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService, this.collectionService,
|
this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService,
|
||||||
this.cryptoService, this.platformUtilsService, this.storageService, this.messagingService,
|
this.collectionService, this.cryptoService, this.platformUtilsService, this.storageService,
|
||||||
this.searchService, this.userService, this.tokenService, null, null);
|
this.messagingService, this.searchService, this.userService, this.tokenService, null, null);
|
||||||
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, this.policyService,
|
this.storageService, this.messagingService, this.policyService,
|
||||||
|
|
|
@ -13,15 +13,16 @@ export class ConfigCommand {
|
||||||
setting = setting.toLowerCase();
|
setting = setting.toLowerCase();
|
||||||
switch (setting) {
|
switch (setting) {
|
||||||
case 'server':
|
case 'server':
|
||||||
return await this.getOrSetServer(value);
|
return await this.getOrSetServer(value, cmd);
|
||||||
default:
|
default:
|
||||||
return Response.badRequest('Unknown setting.');
|
return Response.badRequest('Unknown setting.');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getOrSetServer(url: string): Promise<Response> {
|
private async getOrSetServer(url: string, cmd: program.Command): Promise<Response> {
|
||||||
if (url == null || url.trim() === '') {
|
if ((url == null || url.trim() === '') &&
|
||||||
|
!cmd.webVault && !cmd.api && !cmd.identity && !cmd.icons && !cmd.notifications && !cmd.events) {
|
||||||
const baseUrl = this.environmentService.baseUrl;
|
const baseUrl = this.environmentService.baseUrl;
|
||||||
const stringRes = new StringResponse(baseUrl == null ? 'https://bitwarden.com' : baseUrl);
|
const stringRes = new StringResponse(baseUrl == null ? 'https://bitwarden.com' : baseUrl);
|
||||||
return Response.success(stringRes);
|
return Response.success(stringRes);
|
||||||
|
@ -30,6 +31,12 @@ export class ConfigCommand {
|
||||||
url = (url === 'null' || url === 'bitwarden.com' || url === 'https://bitwarden.com' ? null : url);
|
url = (url === 'null' || url === 'bitwarden.com' || url === 'https://bitwarden.com' ? null : url);
|
||||||
await this.environmentService.setUrls({
|
await this.environmentService.setUrls({
|
||||||
base: url,
|
base: url,
|
||||||
|
webVault: cmd.webVault || null,
|
||||||
|
api: cmd.api || null,
|
||||||
|
identity: cmd.identity || null,
|
||||||
|
icons: cmd.icons || null,
|
||||||
|
notifications: cmd.notifications || null,
|
||||||
|
events: cmd.events || null,
|
||||||
});
|
});
|
||||||
const res = new MessageResponse('Saved setting `config`.', null);
|
const res = new MessageResponse('Saved setting `config`.', null);
|
||||||
return Response.success(res);
|
return Response.success(res);
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class DeleteCommand {
|
||||||
|
|
||||||
switch (object.toLowerCase()) {
|
switch (object.toLowerCase()) {
|
||||||
case 'item':
|
case 'item':
|
||||||
return await this.deleteCipher(id);
|
return await this.deleteCipher(id, cmd);
|
||||||
case 'attachment':
|
case 'attachment':
|
||||||
return await this.deleteAttachment(id, cmd);
|
return await this.deleteAttachment(id, cmd);
|
||||||
case 'folder':
|
case 'folder':
|
||||||
|
@ -32,14 +32,18 @@ export class DeleteCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async deleteCipher(id: string) {
|
private async deleteCipher(id: string, cmd: program.Command) {
|
||||||
const cipher = await this.cipherService.get(id);
|
const cipher = await this.cipherService.get(id);
|
||||||
if (cipher == null) {
|
if (cipher == null) {
|
||||||
return Response.notFound();
|
return Response.notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (cmd.trash) {
|
||||||
|
await this.cipherService.softDeleteWithServer(id);
|
||||||
|
} else {
|
||||||
await this.cipherService.deleteWithServer(id);
|
await this.cipherService.deleteWithServer(id);
|
||||||
|
}
|
||||||
return Response.success();
|
return Response.success();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Response.error(e);
|
return Response.error(e);
|
||||||
|
|
|
@ -70,6 +70,9 @@ export class EditCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
let cipherView = await cipher.decrypt();
|
let cipherView = await cipher.decrypt();
|
||||||
|
if (cipherView.isDeleted) {
|
||||||
|
return Response.badRequest('You may not edit a deleted cipher. Use restore item <id> command first.');
|
||||||
|
}
|
||||||
cipherView = Cipher.toView(req, cipherView);
|
cipherView = Cipher.toView(req, cipherView);
|
||||||
const encCipher = await this.cipherService.encrypt(cipherView);
|
const encCipher = await this.cipherService.encrypt(cipherView);
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -66,6 +66,9 @@ export class ListCommand {
|
||||||
|
|
||||||
if (cmd.folderid != null || cmd.collectionid != null || cmd.organizationid != null) {
|
if (cmd.folderid != null || cmd.collectionid != null || cmd.organizationid != null) {
|
||||||
ciphers = ciphers.filter((c) => {
|
ciphers = ciphers.filter((c) => {
|
||||||
|
if (cmd.trash && !c.isDeleted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (cmd.folderid != null) {
|
if (cmd.folderid != null) {
|
||||||
if (cmd.folderid === 'notnull' && c.folderId != null) {
|
if (cmd.folderid === 'notnull' && c.folderId != null) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -100,10 +103,12 @@ export class ListCommand {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
} else if (cmd.search == null || cmd.search.trim() === '') {
|
||||||
|
ciphers = ciphers.filter((c) => (cmd.trash || false) === c.isDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd.search != null && cmd.search.trim() !== '') {
|
if (cmd.search != null && cmd.search.trim() !== '') {
|
||||||
ciphers = this.searchService.searchCiphersBasic(ciphers, cmd.search);
|
ciphers = this.searchService.searchCiphersBasic(ciphers, cmd.search, cmd.trash || false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = new ListResponse(ciphers.map((o) => new CipherResponse(o)));
|
const res = new ListResponse(ciphers.map((o) => new CipherResponse(o)));
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import * as program from 'commander';
|
||||||
|
|
||||||
|
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||||
|
|
||||||
|
import { Response } from 'jslib/cli/models/response';
|
||||||
|
|
||||||
|
export class RestoreCommand {
|
||||||
|
constructor(private cipherService: CipherService) { }
|
||||||
|
|
||||||
|
async run(object: string, id: string, cmd: program.Command): Promise<Response> {
|
||||||
|
if (id != null) {
|
||||||
|
id = id.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (object.toLowerCase()) {
|
||||||
|
case 'item':
|
||||||
|
return await this.restoreCipher(id, cmd);
|
||||||
|
default:
|
||||||
|
return Response.badRequest('Unknown object.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async restoreCipher(id: string, cmd: program.Command) {
|
||||||
|
const cipher = await this.cipherService.get(id);
|
||||||
|
if (cipher == null) {
|
||||||
|
return Response.notFound();
|
||||||
|
}
|
||||||
|
if (cipher.deletedDate == null) {
|
||||||
|
return Response.badRequest('Cipher is not in trash.');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.cipherService.restoreWithServer(id);
|
||||||
|
return Response.success();
|
||||||
|
} catch (e) {
|
||||||
|
return Response.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import { ImportCommand } from './commands/import.command';
|
||||||
import { ListCommand } from './commands/list.command';
|
import { ListCommand } from './commands/list.command';
|
||||||
import { LockCommand } from './commands/lock.command';
|
import { LockCommand } from './commands/lock.command';
|
||||||
import { LoginCommand } from './commands/login.command';
|
import { LoginCommand } from './commands/login.command';
|
||||||
|
import { RestoreCommand } from './commands/restore.command';
|
||||||
import { ShareCommand } from './commands/share.command';
|
import { ShareCommand } from './commands/share.command';
|
||||||
import { SyncCommand } from './commands/sync.command';
|
import { SyncCommand } from './commands/sync.command';
|
||||||
import { UnlockCommand } from './commands/unlock.command';
|
import { UnlockCommand } from './commands/unlock.command';
|
||||||
|
@ -231,6 +232,7 @@ export class Program extends BaseProgram {
|
||||||
.option('--folderid <folderid>', 'Filter items by folder id.')
|
.option('--folderid <folderid>', 'Filter items by folder id.')
|
||||||
.option('--collectionid <collectionid>', 'Filter items by collection id.')
|
.option('--collectionid <collectionid>', 'Filter items by collection id.')
|
||||||
.option('--organizationid <organizationid>', 'Filter items or collections by organization id.')
|
.option('--organizationid <organizationid>', 'Filter items or collections by organization id.')
|
||||||
|
.option('--trash', 'Filter items that are deleted and in the trash.')
|
||||||
.on('--help', () => {
|
.on('--help', () => {
|
||||||
writeLn('\n Objects:');
|
writeLn('\n Objects:');
|
||||||
writeLn('');
|
writeLn('');
|
||||||
|
@ -256,6 +258,7 @@ export class Program extends BaseProgram {
|
||||||
writeLn(' bw list items --folderid null');
|
writeLn(' bw list items --folderid null');
|
||||||
writeLn(' bw list items --organizationid notnull');
|
writeLn(' bw list items --organizationid notnull');
|
||||||
writeLn(' bw list items --folderid 60556c31-e649-4b5d-8daf-fc1c391a1bf2 --organizationid notnull');
|
writeLn(' bw list items --folderid 60556c31-e649-4b5d-8daf-fc1c391a1bf2 --organizationid notnull');
|
||||||
|
writeLn(' bw list items --trash');
|
||||||
writeLn(' bw list folders --search email');
|
writeLn(' bw list folders --search email');
|
||||||
writeLn(' bw list org-members --organizationid 60556c31-e649-4b5d-8daf-fc1c391a1bf2');
|
writeLn(' bw list org-members --organizationid 60556c31-e649-4b5d-8daf-fc1c391a1bf2');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
|
@ -393,6 +396,7 @@ export class Program extends BaseProgram {
|
||||||
.command('delete <object> <id>')
|
.command('delete <object> <id>')
|
||||||
.option('--itemid <itemid>', 'Attachment\'s item id.')
|
.option('--itemid <itemid>', 'Attachment\'s item id.')
|
||||||
.option('--organizationid <organizationid>', 'Organization id for an organization object.')
|
.option('--organizationid <organizationid>', 'Organization id for an organization object.')
|
||||||
|
.option('-t, --trash', 'Places the item in the trash instead of permanently deleting it (item only).')
|
||||||
.description('Delete an object from the vault.')
|
.description('Delete an object from the vault.')
|
||||||
.on('--help', () => {
|
.on('--help', () => {
|
||||||
writeLn('\n Objects:');
|
writeLn('\n Objects:');
|
||||||
|
@ -409,6 +413,7 @@ export class Program extends BaseProgram {
|
||||||
writeLn(' Examples:');
|
writeLn(' Examples:');
|
||||||
writeLn('');
|
writeLn('');
|
||||||
writeLn(' bw delete item 7063feab-4b10-472e-b64c-785e2b870b92');
|
writeLn(' bw delete item 7063feab-4b10-472e-b64c-785e2b870b92');
|
||||||
|
writeLn(' bw delete item 89c21cd2-fab0-4f69-8c6e-ab8a0168f69a --trash');
|
||||||
writeLn(' bw delete folder 5cdfbd80-d99f-409b-915b-f4c5d0241b02');
|
writeLn(' bw delete folder 5cdfbd80-d99f-409b-915b-f4c5d0241b02');
|
||||||
writeLn(' bw delete attachment b857igwl1dzrs2 --itemid 310d5ffd-e9a2-4451-af87-ea054dce0f78');
|
writeLn(' bw delete attachment b857igwl1dzrs2 --itemid 310d5ffd-e9a2-4451-af87-ea054dce0f78');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
|
@ -421,6 +426,30 @@ export class Program extends BaseProgram {
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('restore <object> <id>')
|
||||||
|
.description('Restores an object from the trash.')
|
||||||
|
.on('--help', () => {
|
||||||
|
writeLn('\n Objects:');
|
||||||
|
writeLn('');
|
||||||
|
writeLn(' item');
|
||||||
|
writeLn('');
|
||||||
|
writeLn(' Id:');
|
||||||
|
writeLn('');
|
||||||
|
writeLn(' Object\'s globally unique `id`.');
|
||||||
|
writeLn('');
|
||||||
|
writeLn(' Examples:');
|
||||||
|
writeLn('');
|
||||||
|
writeLn(' bw restore item 7063feab-4b10-472e-b64c-785e2b870b92');
|
||||||
|
writeLn('', true);
|
||||||
|
})
|
||||||
|
.action(async (object, id, cmd) => {
|
||||||
|
await this.exitIfLocked();
|
||||||
|
const command = new RestoreCommand(this.main.cipherService);
|
||||||
|
const response = await command.run(object, id, cmd);
|
||||||
|
this.processResponse(response);
|
||||||
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('share <id> <organizationId> [encodedJson]')
|
.command('share <id> <organizationId> [encodedJson]')
|
||||||
.description('Share an item to an organization.')
|
.description('Share an item to an organization.')
|
||||||
|
@ -583,6 +612,12 @@ export class Program extends BaseProgram {
|
||||||
program
|
program
|
||||||
.command('config <setting> [value]')
|
.command('config <setting> [value]')
|
||||||
.description('Configure CLI settings.')
|
.description('Configure CLI settings.')
|
||||||
|
.option('--web-vault <url>', 'Provides a custom web vault URL that differs from the base URL.')
|
||||||
|
.option('--api <url>', 'Provides a custom API URL that differs from the base URL.')
|
||||||
|
.option('--identity <url>', 'Provides a custom identity URL that differs from the base URL.')
|
||||||
|
.option('--icons <url>', 'Provides a custom icons service URL that differs from the base URL.')
|
||||||
|
.option('--notifications <url>', 'Provides a custom notifications URL that differs from the base URL.')
|
||||||
|
.option('--events <url>', 'Provides a custom events URL that differs from the base URL.')
|
||||||
.on('--help', () => {
|
.on('--help', () => {
|
||||||
writeLn('\n Settings:');
|
writeLn('\n Settings:');
|
||||||
writeLn('');
|
writeLn('');
|
||||||
|
@ -593,6 +628,7 @@ export class Program extends BaseProgram {
|
||||||
writeLn(' bw config server');
|
writeLn(' bw config server');
|
||||||
writeLn(' bw config server https://bw.company.com');
|
writeLn(' bw config server https://bw.company.com');
|
||||||
writeLn(' bw config server bitwarden.com');
|
writeLn(' bw config server bitwarden.com');
|
||||||
|
writeLn(' bw config server --api http://localhost:4000 --identity http://localhost:33656');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (setting, value, cmd) => {
|
.action(async (setting, value, cmd) => {
|
||||||
|
|
Loading…
Reference in New Issue