1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-10-30 08:10:34 +01:00
bitwarden-browser/apps/cli/src/vault/create.command.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

210 lines
7.7 KiB
TypeScript
Raw Normal View History

2018-05-17 21:33:36 +02:00
import * as fs from "fs";
import * as path from "path";
2018-05-15 03:19:49 +02:00
2022-06-14 17:10:53 +02:00
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { Utils } from "@bitwarden/common/misc/utils";
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
import { FolderExport } from "@bitwarden/common/models/export/folder.export";
import { CollectionRequest } from "@bitwarden/common/models/request/collection.request";
import { SelectionReadOnlyRequest } from "@bitwarden/common/models/request/selection-read-only.request";
[SG-998] and [SG-999] Vault and Autofill team refactor (#4542) * Move DeprecatedVaultFilterService to vault folder * [libs] move VaultItemsComponent * [libs] move AddEditComponent * [libs] move AddEditCustomFields * [libs] move attachmentsComponent * [libs] folderAddEditComponent * [libs] IconComponent * [libs] PasswordRepormptComponent * [libs] PremiumComponent * [libs] ViewCustomFieldsComponent * [libs] ViewComponent * [libs] PasswordRepromptService * [libs] Move FolderService and FolderApiService abstractions * [libs] FolderService imports * [libs] PasswordHistoryComponent * [libs] move Sync and SyncNotifier abstractions * [libs] SyncService imports * [libs] fix file casing for passwordReprompt abstraction * [libs] SyncNotifier import fix * [libs] CipherServiceAbstraction * [libs] PasswordRepromptService abstraction * [libs] Fix file casing for angular passwordReprompt service * [libs] fix file casing for SyncNotifierService * [libs] CipherRepromptType * [libs] rename CipherRepromptType * [libs] CipherType * [libs] Rename CipherType * [libs] CipherData * [libs] FolderData * [libs] PasswordHistoryData * [libs] AttachmentData * [libs] CardData * [libs] FieldData * [libs] IdentityData * [libs] LocalData * [libs] LoginData * [libs] SecureNoteData * [libs] LoginUriData * [libs] Domain classes * [libs] SecureNote * [libs] Request models * [libs] Response models * [libs] View part 1 * [libs] Views part 2 * [libs] Move folder services * [libs] Views fixes * [libs] Move sync services * [libs] cipher service * [libs] Types * [libs] Sync file casing * [libs] Fix folder service import * [libs] Move spec files * [libs] casing fixes on spec files * [browser] Autofill background, clipboard, commands * [browser] Fix ContextMenusBackground casing * [browser] Rename fix * [browser] Autofill content * [browser] autofill.js * [libs] enpass importer spec fix * [browser] autofill models * [browser] autofill manifest path updates * [browser] Autofill notification files * [browser] autofill services * [browser] Fix file casing * [browser] Vault popup loose components * [browser] Vault components * [browser] Manifest fixes * [browser] Vault services * [cli] vault commands and models * [browser] File capitilization fixes * [desktop] Vault components and services * [web] vault loose components * [web] Vault components * [browser] Fix misc-utils import * [libs] Fix psono spec imports * [fix] Add comments to address lint rules
2023-01-31 22:08:37 +01:00
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
2019-03-16 03:34:59 +01:00
import { OrganizationCollectionRequest } from "../models/request/organization-collection.request";
import { Response } from "../models/response";
import { OrganizationCollectionResponse } from "../models/response/organization-collection.response";
import { CliUtils } from "../utils";
[SG-998] and [SG-999] Vault and Autofill team refactor (#4542) * Move DeprecatedVaultFilterService to vault folder * [libs] move VaultItemsComponent * [libs] move AddEditComponent * [libs] move AddEditCustomFields * [libs] move attachmentsComponent * [libs] folderAddEditComponent * [libs] IconComponent * [libs] PasswordRepormptComponent * [libs] PremiumComponent * [libs] ViewCustomFieldsComponent * [libs] ViewComponent * [libs] PasswordRepromptService * [libs] Move FolderService and FolderApiService abstractions * [libs] FolderService imports * [libs] PasswordHistoryComponent * [libs] move Sync and SyncNotifier abstractions * [libs] SyncService imports * [libs] fix file casing for passwordReprompt abstraction * [libs] SyncNotifier import fix * [libs] CipherServiceAbstraction * [libs] PasswordRepromptService abstraction * [libs] Fix file casing for angular passwordReprompt service * [libs] fix file casing for SyncNotifierService * [libs] CipherRepromptType * [libs] rename CipherRepromptType * [libs] CipherType * [libs] Rename CipherType * [libs] CipherData * [libs] FolderData * [libs] PasswordHistoryData * [libs] AttachmentData * [libs] CardData * [libs] FieldData * [libs] IdentityData * [libs] LocalData * [libs] LoginData * [libs] SecureNoteData * [libs] LoginUriData * [libs] Domain classes * [libs] SecureNote * [libs] Request models * [libs] Response models * [libs] View part 1 * [libs] Views part 2 * [libs] Move folder services * [libs] Views fixes * [libs] Move sync services * [libs] cipher service * [libs] Types * [libs] Sync file casing * [libs] Fix folder service import * [libs] Move spec files * [libs] casing fixes on spec files * [browser] Autofill background, clipboard, commands * [browser] Fix ContextMenusBackground casing * [browser] Rename fix * [browser] Autofill content * [browser] autofill.js * [libs] enpass importer spec fix * [browser] autofill models * [browser] autofill manifest path updates * [browser] Autofill notification files * [browser] autofill services * [browser] Fix file casing * [browser] Vault popup loose components * [browser] Vault components * [browser] Manifest fixes * [browser] Vault services * [cli] vault commands and models * [browser] File capitilization fixes * [desktop] Vault components and services * [web] vault loose components * [web] Vault components * [browser] Fix misc-utils import * [libs] Fix psono spec imports * [fix] Add comments to address lint rules
2023-01-31 22:08:37 +01:00
import { CipherResponse } from "./models/cipher.response";
import { FolderResponse } from "./models/folder.response";
2018-05-15 03:19:49 +02:00
export class CreateCommand {
2018-05-18 16:55:50 +02:00
constructor(
private cipherService: CipherService,
private folderService: FolderService,
private stateService: StateService,
2019-09-25 22:08:56 +02:00
private cryptoService: CryptoService,
private apiService: ApiService,
private folderApiService: FolderApiServiceAbstraction
2019-09-25 22:08:56 +02:00
) {}
2021-12-20 18:04:00 +01:00
2022-01-19 16:45:14 +01:00
async run(
object: string,
requestJson: string,
cmdOptions: Record<string, any>,
additionalData: any = null
): Promise<Response> {
2018-05-17 21:33:36 +02:00
let req: any = null;
if (object !== "attachment") {
2022-01-19 16:45:14 +01:00
if (process.env.BW_SERVE !== "true" && (requestJson == null || requestJson === "")) {
2018-05-17 21:33:36 +02:00
requestJson = await CliUtils.readStdin();
}
2021-12-20 18:04:00 +01:00
2018-05-17 21:33:36 +02:00
if (requestJson == null || requestJson === "") {
return Response.badRequest("`requestJson` was not provided.");
2018-05-15 16:50:06 +02:00
}
2021-12-20 18:04:00 +01:00
2022-01-19 16:45:14 +01:00
if (typeof requestJson !== "string") {
req = requestJson;
} else {
try {
const reqJson = Buffer.from(requestJson, "base64").toString();
req = JSON.parse(reqJson);
} catch (e) {
return Response.badRequest("Error parsing the encoded request data.");
}
2018-05-15 03:19:49 +02:00
}
}
2022-01-19 16:45:14 +01:00
const normalizedOptions = new Options(cmdOptions);
2018-05-15 03:19:49 +02:00
switch (object.toLowerCase()) {
2021-12-20 18:04:00 +01:00
case "item":
2018-05-15 03:19:49 +02:00
return await this.createCipher(req);
2018-05-17 21:33:36 +02:00
case "attachment":
2022-01-19 16:45:14 +01:00
return await this.createAttachment(normalizedOptions, additionalData);
2018-05-15 03:19:49 +02:00
case "folder":
return await this.createFolder(req);
2019-09-25 22:08:56 +02:00
case "org-collection":
2022-01-19 16:45:14 +01:00
return await this.createOrganizationCollection(req, normalizedOptions);
2021-12-20 18:04:00 +01:00
default:
2019-10-01 17:16:24 +02:00
return Response.badRequest("Unknown object.");
2021-12-20 18:04:00 +01:00
}
}
private async createCipher(req: CipherExport) {
const cipher = await this.cipherService.encrypt(CipherExport.toView(req));
2018-05-15 03:19:49 +02:00
try {
await this.cipherService.createWithServer(cipher);
const newCipher = await this.cipherService.get(cipher.id);
const decCipher = await newCipher.decrypt();
const res = new CipherResponse(decCipher);
return Response.success(res);
2018-05-15 03:19:49 +02:00
} catch (e) {
2018-05-15 17:08:55 +02:00
return Response.error(e);
2021-12-20 18:04:00 +01:00
}
}
2022-01-19 16:45:14 +01:00
private async createAttachment(options: Options, additionalData: any) {
if (options.itemId == null || options.itemId === "") {
return Response.badRequest("`itemid` option is required.");
2021-12-20 18:04:00 +01:00
}
2022-01-19 16:45:14 +01:00
let fileBuf: Buffer = null;
let fileName: string = null;
if (process.env.BW_SERVE === "true") {
fileBuf = additionalData.fileBuffer;
fileName = additionalData.fileName;
} else {
if (options.file == null || options.file === "") {
return Response.badRequest("`file` option is required.");
}
const filePath = path.resolve(options.file);
if (!fs.existsSync(options.file)) {
return Response.badRequest("Cannot find file at " + filePath);
}
fileBuf = fs.readFileSync(filePath);
fileName = path.basename(filePath);
}
if (fileBuf == null) {
return Response.badRequest("File not provided.");
2021-12-20 18:04:00 +01:00
}
2022-01-19 16:45:14 +01:00
if (fileName == null || fileName.trim() === "") {
return Response.badRequest("File name not provided.");
2018-05-15 03:19:49 +02:00
}
2021-12-20 18:04:00 +01:00
2022-01-19 16:45:14 +01:00
const itemId = options.itemId.toLowerCase();
2018-05-17 21:55:44 +02:00
const cipher = await this.cipherService.get(itemId);
2018-05-17 21:33:36 +02:00
if (cipher == null) {
return Response.notFound();
2018-05-15 03:19:49 +02:00
}
if (cipher.organizationId == null && !(await this.stateService.getCanAccessPremium())) {
return Response.error("Premium status is required to use this feature.");
2018-05-17 21:33:36 +02:00
}
2018-05-15 18:18:47 +02:00
const encKey = await this.cryptoService.getEncKey();
2018-05-15 03:19:49 +02:00
if (encKey == null) {
2018-05-15 17:08:55 +02:00
return Response.error(
2018-05-18 16:55:50 +02:00
"You must update your encryption key before you can use this feature. " +
"See https://help.bitwarden.com/article/update-encryption-key/"
2018-05-15 17:08:55 +02:00
);
2018-05-15 03:19:49 +02:00
}
2019-09-25 22:08:56 +02:00
2021-12-20 18:04:00 +01:00
try {
Add send to cli (#222) * Add list all sends and filter by search term * Add get send templates * Add AccessUrl to send responses * Add Send to Get command * Add missing command options to login These options are already coded to work in the command, but commander did not know about the options. * Upgrade Commander to 7.0.0 This is needed to enable the subcommand chaining required by Send. This commit also adds get send and send receive functionality. get send will be moved to send get along with send list and any other send commands. * Use api url for send access url * Move send commands to send subcommands * Use webvault access url everywhere Production instances all have api url located at `baseUrl/api`. Receive command will parse the webvault url and alter it to an api url. * Move create and receive commands to send directory * Separate program concerns program holds authentication/general program concerns vault.program holds commands related to the vault send.program holds commands related to Bitwarden Send * Fix up imports and lint items * Add edit command * Use browser-hrtime * Add send examples to help text * Clean up receive help text * correct help text * Add delete command * Code review Cleanup * Scheme on send receive help text * PR review items Move buffer to array buffer to jslib delete with server some formatting fixes * Add remove password command This is the simplest way to enable removing passwords without resorting to weird type parsing of piped in Send JSONs in edit * Default hidden to false like web * Do not allow password updates that aren't strings or are empty * Delete appveyor.yml.flagged-for-delete * Correctly order imports and include tslint rule * fix npm globbing problem https://stackoverflow.com/a/34594501 globs work differently in package.json. Encasing the globs in single quotes expands them in shell rather than in npm * Remove double slash in path * Trigger github rebuild
2021-02-03 18:44:33 +01:00
await this.cipherService.saveAttachmentRawWithServer(
2021-12-20 18:04:00 +01:00
cipher,
2022-01-19 16:45:14 +01:00
fileName,
2018-05-17 21:33:36 +02:00
new Uint8Array(fileBuf).buffer
2021-12-20 18:04:00 +01:00
);
Add send to cli (#222) * Add list all sends and filter by search term * Add get send templates * Add AccessUrl to send responses * Add Send to Get command * Add missing command options to login These options are already coded to work in the command, but commander did not know about the options. * Upgrade Commander to 7.0.0 This is needed to enable the subcommand chaining required by Send. This commit also adds get send and send receive functionality. get send will be moved to send get along with send list and any other send commands. * Use api url for send access url * Move send commands to send subcommands * Use webvault access url everywhere Production instances all have api url located at `baseUrl/api`. Receive command will parse the webvault url and alter it to an api url. * Move create and receive commands to send directory * Separate program concerns program holds authentication/general program concerns vault.program holds commands related to the vault send.program holds commands related to Bitwarden Send * Fix up imports and lint items * Add edit command * Use browser-hrtime * Add send examples to help text * Clean up receive help text * correct help text * Add delete command * Code review Cleanup * Scheme on send receive help text * PR review items Move buffer to array buffer to jslib delete with server some formatting fixes * Add remove password command This is the simplest way to enable removing passwords without resorting to weird type parsing of piped in Send JSONs in edit * Default hidden to false like web * Do not allow password updates that aren't strings or are empty * Delete appveyor.yml.flagged-for-delete * Correctly order imports and include tslint rule * fix npm globbing problem https://stackoverflow.com/a/34594501 globs work differently in package.json. Encasing the globs in single quotes expands them in shell rather than in npm * Remove double slash in path * Trigger github rebuild
2021-02-03 18:44:33 +01:00
const updatedCipher = await this.cipherService.get(cipher.id);
const decCipher = await updatedCipher.decrypt();
return Response.success(new CipherResponse(decCipher));
2018-05-17 21:33:36 +02:00
} catch (e) {
Add send to cli (#222) * Add list all sends and filter by search term * Add get send templates * Add AccessUrl to send responses * Add Send to Get command * Add missing command options to login These options are already coded to work in the command, but commander did not know about the options. * Upgrade Commander to 7.0.0 This is needed to enable the subcommand chaining required by Send. This commit also adds get send and send receive functionality. get send will be moved to send get along with send list and any other send commands. * Use api url for send access url * Move send commands to send subcommands * Use webvault access url everywhere Production instances all have api url located at `baseUrl/api`. Receive command will parse the webvault url and alter it to an api url. * Move create and receive commands to send directory * Separate program concerns program holds authentication/general program concerns vault.program holds commands related to the vault send.program holds commands related to Bitwarden Send * Fix up imports and lint items * Add edit command * Use browser-hrtime * Add send examples to help text * Clean up receive help text * correct help text * Add delete command * Code review Cleanup * Scheme on send receive help text * PR review items Move buffer to array buffer to jslib delete with server some formatting fixes * Add remove password command This is the simplest way to enable removing passwords without resorting to weird type parsing of piped in Send JSONs in edit * Default hidden to false like web * Do not allow password updates that aren't strings or are empty * Delete appveyor.yml.flagged-for-delete * Correctly order imports and include tslint rule * fix npm globbing problem https://stackoverflow.com/a/34594501 globs work differently in package.json. Encasing the globs in single quotes expands them in shell rather than in npm * Remove double slash in path * Trigger github rebuild
2021-02-03 18:44:33 +01:00
return Response.error(e);
2021-12-20 18:04:00 +01:00
}
}
private async createFolder(req: FolderExport) {
const folder = await this.folderService.encrypt(FolderExport.toView(req));
Add send to cli (#222) * Add list all sends and filter by search term * Add get send templates * Add AccessUrl to send responses * Add Send to Get command * Add missing command options to login These options are already coded to work in the command, but commander did not know about the options. * Upgrade Commander to 7.0.0 This is needed to enable the subcommand chaining required by Send. This commit also adds get send and send receive functionality. get send will be moved to send get along with send list and any other send commands. * Use api url for send access url * Move send commands to send subcommands * Use webvault access url everywhere Production instances all have api url located at `baseUrl/api`. Receive command will parse the webvault url and alter it to an api url. * Move create and receive commands to send directory * Separate program concerns program holds authentication/general program concerns vault.program holds commands related to the vault send.program holds commands related to Bitwarden Send * Fix up imports and lint items * Add edit command * Use browser-hrtime * Add send examples to help text * Clean up receive help text * correct help text * Add delete command * Code review Cleanup * Scheme on send receive help text * PR review items Move buffer to array buffer to jslib delete with server some formatting fixes * Add remove password command This is the simplest way to enable removing passwords without resorting to weird type parsing of piped in Send JSONs in edit * Default hidden to false like web * Do not allow password updates that aren't strings or are empty * Delete appveyor.yml.flagged-for-delete * Correctly order imports and include tslint rule * fix npm globbing problem https://stackoverflow.com/a/34594501 globs work differently in package.json. Encasing the globs in single quotes expands them in shell rather than in npm * Remove double slash in path * Trigger github rebuild
2021-02-03 18:44:33 +01:00
try {
await this.folderApiService.save(folder);
Add send to cli (#222) * Add list all sends and filter by search term * Add get send templates * Add AccessUrl to send responses * Add Send to Get command * Add missing command options to login These options are already coded to work in the command, but commander did not know about the options. * Upgrade Commander to 7.0.0 This is needed to enable the subcommand chaining required by Send. This commit also adds get send and send receive functionality. get send will be moved to send get along with send list and any other send commands. * Use api url for send access url * Move send commands to send subcommands * Use webvault access url everywhere Production instances all have api url located at `baseUrl/api`. Receive command will parse the webvault url and alter it to an api url. * Move create and receive commands to send directory * Separate program concerns program holds authentication/general program concerns vault.program holds commands related to the vault send.program holds commands related to Bitwarden Send * Fix up imports and lint items * Add edit command * Use browser-hrtime * Add send examples to help text * Clean up receive help text * correct help text * Add delete command * Code review Cleanup * Scheme on send receive help text * PR review items Move buffer to array buffer to jslib delete with server some formatting fixes * Add remove password command This is the simplest way to enable removing passwords without resorting to weird type parsing of piped in Send JSONs in edit * Default hidden to false like web * Do not allow password updates that aren't strings or are empty * Delete appveyor.yml.flagged-for-delete * Correctly order imports and include tslint rule * fix npm globbing problem https://stackoverflow.com/a/34594501 globs work differently in package.json. Encasing the globs in single quotes expands them in shell rather than in npm * Remove double slash in path * Trigger github rebuild
2021-02-03 18:44:33 +01:00
const newFolder = await this.folderService.get(folder.id);
const decFolder = await newFolder.decrypt();
2019-10-01 17:16:24 +02:00
const res = new FolderResponse(decFolder);
return Response.success(res);
Add send to cli (#222) * Add list all sends and filter by search term * Add get send templates * Add AccessUrl to send responses * Add Send to Get command * Add missing command options to login These options are already coded to work in the command, but commander did not know about the options. * Upgrade Commander to 7.0.0 This is needed to enable the subcommand chaining required by Send. This commit also adds get send and send receive functionality. get send will be moved to send get along with send list and any other send commands. * Use api url for send access url * Move send commands to send subcommands * Use webvault access url everywhere Production instances all have api url located at `baseUrl/api`. Receive command will parse the webvault url and alter it to an api url. * Move create and receive commands to send directory * Separate program concerns program holds authentication/general program concerns vault.program holds commands related to the vault send.program holds commands related to Bitwarden Send * Fix up imports and lint items * Add edit command * Use browser-hrtime * Add send examples to help text * Clean up receive help text * correct help text * Add delete command * Code review Cleanup * Scheme on send receive help text * PR review items Move buffer to array buffer to jslib delete with server some formatting fixes * Add remove password command This is the simplest way to enable removing passwords without resorting to weird type parsing of piped in Send JSONs in edit * Default hidden to false like web * Do not allow password updates that aren't strings or are empty * Delete appveyor.yml.flagged-for-delete * Correctly order imports and include tslint rule * fix npm globbing problem https://stackoverflow.com/a/34594501 globs work differently in package.json. Encasing the globs in single quotes expands them in shell rather than in npm * Remove double slash in path * Trigger github rebuild
2021-02-03 18:44:33 +01:00
} catch (e) {
return Response.error(e);
2021-12-20 18:04:00 +01:00
}
}
2022-01-19 16:45:14 +01:00
private async createOrganizationCollection(req: OrganizationCollectionRequest, options: Options) {
if (options.organizationId == null || options.organizationId === "") {
return Response.badRequest("`organizationid` option is required.");
2021-12-20 18:04:00 +01:00
}
2022-01-19 16:45:14 +01:00
if (!Utils.isGuid(options.organizationId)) {
return Response.badRequest("`" + options.organizationId + "` is not a GUID.");
2019-10-01 17:16:24 +02:00
}
2022-01-19 16:45:14 +01:00
if (options.organizationId !== req.organizationId) {
return Response.badRequest("`organizationid` option does not match request object.");
2021-12-20 18:04:00 +01:00
}
2019-09-25 22:08:56 +02:00
try {
const orgKey = await this.cryptoService.getOrgKey(req.organizationId);
if (orgKey == null) {
throw new Error("No encryption key for this organization.");
}
2021-12-20 18:04:00 +01:00
2019-09-25 22:08:56 +02:00
const groups =
req.groups == null
? null
: req.groups.map((g) => new SelectionReadOnlyRequest(g.id, g.readOnly, g.hidePasswords));
2019-09-25 22:08:56 +02:00
const request = new CollectionRequest();
request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString;
request.externalId = req.externalId;
request.groups = groups;
const response = await this.apiService.postCollection(req.organizationId, request);
const view = CollectionExport.toView(req);
view.id = response.id;
const res = new OrganizationCollectionResponse(view, groups);
2019-09-25 22:08:56 +02:00
return Response.success(res);
} catch (e) {
return Response.error(e);
}
2021-12-20 18:04:00 +01:00
}
2018-05-15 03:19:49 +02:00
}
2022-01-19 16:45:14 +01:00
class Options {
itemId: string;
organizationId: string;
file: string;
constructor(passedOptions: Record<string, any>) {
this.organizationId = passedOptions?.organizationid || passedOptions?.organizationId;
this.itemId = passedOptions?.itemid || passedOptions?.itemId;
this.file = passedOptions?.file;
2022-01-19 16:45:14 +01:00
}
}