From 17ab740914d786cb36196648d805294e929b65af Mon Sep 17 00:00:00 2001 From: Matt Gibson Date: Wed, 16 Jun 2021 08:50:29 -0500 Subject: [PATCH] Allow import to organization (#325) * Allow import to organization vaults * Use organization-aware Importer --- src/commands/import.command.ts | 26 ++++++++++++++++++++------ src/vault.program.ts | 4 +++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/commands/import.command.ts b/src/commands/import.command.ts index 9ce6801a28..e07769f002 100644 --- a/src/commands/import.command.ts +++ b/src/commands/import.command.ts @@ -1,5 +1,6 @@ import * as program from 'commander'; import { ImportService } from 'jslib-common/abstractions/import.service'; +import { UserService } from 'jslib-common/abstractions/user.service'; import { Response } from 'jslib-node/cli/models/response'; import { MessageResponse } from 'jslib-node/cli/models/response/messageResponse'; @@ -7,17 +8,30 @@ import { MessageResponse } from 'jslib-node/cli/models/response/messageResponse' import { CliUtils } from '../utils'; export class ImportCommand { - constructor(private importService: ImportService) { } + constructor(private importService: ImportService, private userService: UserService) { } async run(format: string, filepath: string, options: program.OptionValues): Promise { + const organizationId = options.organizationid; + if (organizationId != null) { + const organization = await this.userService.getOrganization(organizationId); + + if (organization == null) { + return Response.badRequest(`You do not belong to an organization with the ID of ${organizationId}. Check the organization ID and sync your vault.`); + } + + if (!organization.canAccessImportExport) { + return Response.badRequest('You are not authorized to import into the provided organization.'); + } + } + if (options.formats || false) { - return this.list(); + return await this.list(); } else { - return this.import(format, filepath); + return await this.import(format, filepath, organizationId); } } - private async import(format: string, filepath: string) { + private async import(format: string, filepath: string, organizationId: string) { if (format == null || format === '') { return Response.badRequest('`format` was not provided.'); } @@ -25,7 +39,7 @@ export class ImportCommand { return Response.badRequest('`filepath` was not provided.'); } - const importer = await this.importService.getImporter(format, null); + const importer = await this.importService.getImporter(format, organizationId); if (importer === null) { return Response.badRequest('Proper importer type required.'); } @@ -36,7 +50,7 @@ export class ImportCommand { return Response.badRequest('Import file was empty.'); } - const err = await this.importService.import(importer, contents, null); + const err = await this.importService.import(importer, contents, organizationId); if (err != null) { return Response.badRequest(err.message); } diff --git a/src/vault.program.ts b/src/vault.program.ts index 53be3427fd..af59097660 100644 --- a/src/vault.program.ts +++ b/src/vault.program.ts @@ -320,16 +320,18 @@ export class VaultProgram extends Program { .command('import [format] [input]') .description('Import vault data from a file.') .option('--formats', 'List formats') + .option('--organizationid ', 'ID of the organization to import to.') .on('--help', () => { writeLn('\n Examples:'); writeLn(''); writeLn(' bw import --formats'); writeLn(' bw import bitwardencsv ./from/source.csv'); writeLn(' bw import keepass2xml keepass_backup.xml'); + writeLn(' bw import --organizationid cf14adc3-aca5-4573-890a-f6fa231436d9 keepass2xml keepass_backup.xml'); }) .action(async (format, filepath, options) => { await this.exitIfLocked(); - const command = new ImportCommand(this.main.importService); + const command = new ImportCommand(this.main.importService, this.main.userService); const response = await command.run(format, filepath, options); this.processResponse(response); });