diff --git a/src/commands/delete.command.ts b/src/commands/delete.command.ts index de88f7de3a..2c71cbf702 100644 --- a/src/commands/delete.command.ts +++ b/src/commands/delete.command.ts @@ -15,7 +15,11 @@ export class DeleteCommand { switch (object.toLowerCase()) { case 'item': - return await this.deleteCipher(id); + if (cmd.attachmentid == null || cmd.attachmentid === '') { + return await this.deleteCipher(id); + } else { + return await this.deleteAttachment(id, cmd.attachmentid); + } case 'folder': return await this.deleteFolder(id); default: @@ -37,6 +41,36 @@ export class DeleteCommand { } } + private async deleteAttachment(id: string, attachmentId: string) { + attachmentId = attachmentId.toLowerCase(); + + const encCipher = await this.cipherService.get(id); + if (encCipher == null) { + return Response.notFound(); + } + + const cipher = await encCipher.decrypt(); + if (cipher.attachments == null || cipher.attachments.length === 0) { + return Response.error('No attachments available for this item.'); + } + + const attachments = cipher.attachments.filter((a) => + a.id.toLowerCase() === attachmentId || a.fileName.toLowerCase() === attachmentId); + if (attachments.length === 0) { + return Response.error('Attachment `' + attachmentId + '` was not found.'); + } + if (attachments.length > 1) { + return Response.multipleResults(attachments.map((a) => a.id)); + } + + try { + await this.cipherService.deleteAttachmentWithServer(id, attachments[0].id); + return Response.success(); + } catch (e) { + return Response.error(e); + } + } + private async deleteFolder(id: string) { const folder = await this.folderService.get(id); if (folder == null) { diff --git a/src/commands/get.command.ts b/src/commands/get.command.ts index 0be8d11fab..032425b2a2 100644 --- a/src/commands/get.command.ts +++ b/src/commands/get.command.ts @@ -47,11 +47,10 @@ export class GetCommand { switch (object.toLowerCase()) { case 'item': - if (cmd.attachmentid === null || cmd.attachmentid === '') { + if (cmd.attachmentid == null || cmd.attachmentid === '') { return await this.getCipher(id); } else { - - return await this.getAttachment(id, cmd); + return await this.getAttachment(id, cmd.attachmentid, cmd); } case 'username': return await this.getUsername(id); @@ -193,7 +192,9 @@ export class GetCommand { return Response.success(res); } - private async getAttachment(id: string, cmd: program.Command) { + private async getAttachment(id: string, attachmentId: string, cmd: program.Command) { + attachmentId = attachmentId.toLowerCase(); + // TODO: Premium check const cipherResponse = await this.getCipher(id); @@ -206,16 +207,16 @@ export class GetCommand { return Response.error('No attachments available for this item.'); } - const attachment = cipher.attachments.filter((a) => - a.id === cmd.attachmentid || a.fileName === cmd.attachmentid); - if (attachment.length === 0) { - return Response.error('Attachment `' + cmd.attachmentid + '` was not found.'); + const attachments = cipher.attachments.filter((a) => + a.id.toLowerCase() === attachmentId || a.fileName.toLowerCase() === attachmentId); + if (attachments.length === 0) { + return Response.error('Attachment `' + attachmentId + '` was not found.'); } - if (attachment.length > 1) { - return Response.multipleResults(attachment.map((a) => a.id)); + if (attachments.length > 1) { + return Response.multipleResults(attachments.map((a) => a.id)); } - const response = await fet.default(new fet.Request(attachment[0].url, { headers: { cache: 'no-cache' } })); + const response = await fet.default(new fet.Request(attachments[0].url, { headers: { cache: 'no-cache' } })); if (response.status !== 200) { return Response.error('A ' + response.status + ' error occurred while downloading the attachment.'); } @@ -224,7 +225,7 @@ export class GetCommand { const buf = await response.arrayBuffer(); const key = await this.cryptoService.getOrgKey(cipher.organizationId); const decBuf = await this.cryptoService.decryptFromBytes(buf, key); - const filePath = await CliUtils.saveFile(new Buffer(decBuf), cmd.output, attachment[0].fileName); + const filePath = await CliUtils.saveFile(new Buffer(decBuf), cmd.output, attachments[0].fileName); const res = new MessageResponse('Saved ' + filePath, null); res.raw = filePath; return Response.success(res); diff --git a/src/program.ts b/src/program.ts index 8375ba6869..4ba02faec9 100644 --- a/src/program.ts +++ b/src/program.ts @@ -324,6 +324,7 @@ export class Program { program .command('delete ') + .option('--attachmentid ', 'Delete an item\'s attachment.') .description('Delete an object.') .on('--help', () => { writeLn('\n Objects:'); @@ -337,7 +338,10 @@ export class Program { writeLn(''); writeLn(' Examples:'); writeLn(''); + writeLn(' bw delete item 7063feab-4b10-472e-b64c-785e2b870b92'); writeLn(' bw delete folder 5cdfbd80-d99f-409b-915b-f4c5d0241b02'); + writeLn(' bw delete item 310d5ffd-e9a2-4451-af87-ea054dce0f78 --attachmentid b857igwl1dzrs2'); + writeLn(' bw delete item 310d5ffd-e9a2-4451-af87-ea054dce0f78 --attachmentid photo.jpg'); writeLn(''); }) .action(async (object, id, cmd) => {