1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

[PM-328] Move exporter to tools (#5070)

* Create and register new libs/exporter

Create package.json
Create tsconfig
Create jest.config
Extend shared and root tsconfig and jest.configs
Register with eslint

* Migrate exportService to libs/exporter

Move exportService (abstraction and impl) into libs/exporter
Refactored exportService to be split into vault-export and event-export
Created barrel-files for both exports
Moved export.service.spec.ts into vault-export
Created an export-helper, which helps build the filename (extract method refactor from ExportService)

* Move components in libs/angular into tools-subfolder

Moved components
Updated imports in jslib-services.module and jslib.module

* Register libs/exporter with browser and fix imports

Move export.component into tools-subfolder

* Register libs/exporter with cli and fix imports

Move export.command into tools-subfolder

* Register libs/exporter with desktop and fix imports

Move export.component into tools-subfolder

* Move export models to libs/exporter

* Update web imports

* Update package-lock.json

* Move export models back as it would create circular dependency

Reponse models in common rely on export models which are in libs/exporter, which relies on common

* Fix up web for event-export

* Update CODEOWNERS

* Add export-models to team-tools-dev

* Simplify domain import

* Moving EventExport into web
This commit is contained in:
Daniel James Smith
2023-04-19 11:30:46 +02:00
committed by GitHub
parent 830af7b06d
commit 192bb5a7b3
53 changed files with 266 additions and 133 deletions

View File

@@ -0,0 +1,115 @@
import * as program from "commander";
import * as inquirer from "inquirer";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { Utils } from "@bitwarden/common/misc/utils";
import {
ExportFormat,
EXPORT_FORMATS,
VaultExportServiceAbstraction,
} from "@bitwarden/exporter/vault-export";
import { Response } from "../models/response";
import { CliUtils } from "../utils";
export class ExportCommand {
constructor(
private exportService: VaultExportServiceAbstraction,
private policyService: PolicyService
) {}
async run(options: program.OptionValues): Promise<Response> {
if (
options.organizationid == null &&
(await this.policyService.policyAppliesToUser(PolicyType.DisablePersonalVaultExport))
) {
return Response.badRequest(
"One or more organization policies prevents you from exporting your personal vault."
);
}
const format = options.format ?? "csv";
if (!this.isSupportedExportFormat(format)) {
return Response.badRequest(
`'${format}' is not a supported export format. Supported formats: ${EXPORT_FORMATS.join(
", "
)}.`
);
}
if (options.organizationid != null && !Utils.isGuid(options.organizationid)) {
return Response.error("`" + options.organizationid + "` is not a GUID.");
}
let exportContent: string = null;
try {
exportContent =
format === "encrypted_json"
? await this.getProtectedExport(options.password, options.organizationid)
: await this.getUnprotectedExport(format, options.organizationid);
} catch (e) {
return Response.error(e);
}
return await this.saveFile(exportContent, options, format);
}
private async getProtectedExport(passwordOption: string | boolean, organizationId?: string) {
const password = await this.promptPassword(passwordOption);
return password == null
? await this.exportService.getExport("encrypted_json", organizationId)
: await this.exportService.getPasswordProtectedExport(password, organizationId);
}
private async getUnprotectedExport(format: ExportFormat, organizationId?: string) {
return this.exportService.getExport(format, organizationId);
}
private async saveFile(
exportContent: string,
options: program.OptionValues,
format: ExportFormat
): Promise<Response> {
try {
const fileName = this.getFileName(format, options.organizationid != null ? "org" : null);
return await CliUtils.saveResultToFile(exportContent, options.output, fileName);
} catch (e) {
return Response.error(e.toString());
}
}
private getFileName(format: ExportFormat, prefix?: string) {
if (format === "encrypted_json") {
if (prefix == null) {
prefix = "encrypted";
} else {
prefix = "encrypted_" + prefix;
}
format = "json";
}
return this.exportService.getFileName(prefix, format);
}
private async promptPassword(password: string | boolean) {
// boolean => flag set with no value, we need to prompt for password
// string => flag set with value, use this value for password
// undefined/null/false => account protect, not password, no password needed
if (typeof password === "string") {
return password;
} else if (password) {
const answer: inquirer.Answers = await inquirer.createPromptModule({
output: process.stderr,
})({
type: "password",
name: "password",
message: "Export file password:",
});
return answer.password as string;
}
return null;
}
private isSupportedExportFormat(format: string): format is ExportFormat {
return EXPORT_FORMATS.includes(format as ExportFormat);
}
}