From 4d57f44a6944cf4037802388dfdab02dc75b7c37 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 17 Dec 2018 13:21:06 -0500 Subject: [PATCH] bitwarden json importer --- src/importers/bitwardenJsonImporter.ts | 66 ++++++++++++++++++++++++++ src/services/export.service.ts | 3 ++ src/services/import.service.ts | 4 ++ 3 files changed, 73 insertions(+) create mode 100644 src/importers/bitwardenJsonImporter.ts diff --git a/src/importers/bitwardenJsonImporter.ts b/src/importers/bitwardenJsonImporter.ts new file mode 100644 index 0000000000..e4c376940e --- /dev/null +++ b/src/importers/bitwardenJsonImporter.ts @@ -0,0 +1,66 @@ +import { BaseImporter } from './baseImporter'; +import { Importer } from './importer'; + +import { ImportResult } from '../models/domain/importResult'; + +import { CipherWithIds } from '../models/export/cipherWithIds'; +import { CollectionWithId } from '../models/export/collectionWithId'; +import { FolderWithId } from '../models/export/folderWithId'; + +export class BitwardenJsonImporter extends BaseImporter implements Importer { + parse(data: string): ImportResult { + const result = new ImportResult(); + const results = JSON.parse(data); + if (results == null || results.items == null || results.items.length === 0) { + result.success = false; + return result; + } + + const groupingsMap = new Map(); + if (this.organization && results.collections != null) { + results.collections.forEach((c: CollectionWithId) => { + const collection = CollectionWithId.toView(c); + if (collection != null) { + collection.id = null; + collection.organizationId = null; + groupingsMap.set(c.id, result.collections.length); + result.collections.push(collection); + } + }); + } else if (!this.organization && results.folders != null) { + results.folders.forEach((f: FolderWithId) => { + const folder = FolderWithId.toView(f); + if (folder != null) { + folder.id = null; + groupingsMap.set(f.id, result.folders.length); + result.folders.push(folder); + } + }); + } + + results.items.forEach((c: CipherWithIds) => { + const cipher = CipherWithIds.toView(c); + // reset ids incase they were set for some reason + cipher.id = null; + cipher.folderId = null; + cipher.organizationId = null; + cipher.collectionIds = null; + + if (!this.organization && c.folderId != null && groupingsMap.has(c.folderId)) { + result.folderRelationships.push([result.ciphers.length, groupingsMap.get(c.folderId)]); + } else if (this.organization && c.collectionIds != null) { + c.collectionIds.forEach((cId) => { + if (groupingsMap.has(cId)) { + result.collectionRelationships.push([result.ciphers.length, groupingsMap.get(cId)]); + } + }); + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return result; + } +} diff --git a/src/services/export.service.ts b/src/services/export.service.ts index 6492725494..7c5ef3cc83 100644 --- a/src/services/export.service.ts +++ b/src/services/export.service.ts @@ -73,6 +73,9 @@ export class ExportService implements ExportServiceAbstraction { }; decFolders.forEach((f) => { + if (f.id == null) { + return; + } const folder = new FolderExport(); folder.build(f); jsonDoc.folders.push(folder); diff --git a/src/services/import.service.ts b/src/services/import.service.ts index 3e53753ccd..ca32707987 100644 --- a/src/services/import.service.ts +++ b/src/services/import.service.ts @@ -22,6 +22,7 @@ import { CipherView } from '../models/view/cipherView'; import { AscendoCsvImporter } from '../importers/ascendoCsvImporter'; import { AviraCsvImporter } from '../importers/aviraCsvImporter'; import { BitwardenCsvImporter } from '../importers/bitwardenCsvImporter'; +import { BitwardenJsonImporter } from '../importers/bitwardenJsonImporter'; import { BlurCsvImporter } from '../importers/blurCsvImporter'; import { ChromeCsvImporter } from '../importers/chromeCsvImporter'; import { ClipperzHtmlImporter } from '../importers/clipperzHtmlImporter'; @@ -58,6 +59,7 @@ import { ZohoVaultCsvImporter } from '../importers/zohoVaultCsvImporter'; export class ImportService implements ImportServiceAbstraction { featuredImportOptions = [ + { id: 'bitwardenjson', name: 'Bitwarden (json)' }, { id: 'bitwardencsv', name: 'Bitwarden (csv)' }, { id: 'lastpasscsv', name: 'LastPass (csv)' }, { id: 'chromecsv', name: 'Chrome (csv)' }, @@ -148,6 +150,8 @@ export class ImportService implements ImportServiceAbstraction { switch (format) { case 'bitwardencsv': return new BitwardenCsvImporter(); + case 'bitwardenjson': + return new BitwardenJsonImporter(); case 'lastpasscsv': case 'passboltcsv': return new LastPassCsvImporter();