From 2ad739b5a8a5b6aa700648980c7eaa5a534b6708 Mon Sep 17 00:00:00 2001 From: aj-rosado <109146700+aj-rosado@users.noreply.github.com> Date: Fri, 7 Apr 2023 11:23:34 +0100 Subject: [PATCH] [PM-1684] Broken roboform importer (#5137) * PM-1684 - Set null or empty validation on start of processFolder method * PM-1684 - Added tests to roboform-csv-importer --- .../spec/roboform-csv-importer.spec.ts | 37 +++++++++++++++++++ .../test-data/roboform-csv/empty-folders.ts | 6 +++ .../test-data/roboform-csv/with-folders.ts | 6 +++ libs/importer/src/importers/base-importer.ts | 24 ++++++------ 4 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 libs/importer/spec/roboform-csv-importer.spec.ts create mode 100644 libs/importer/spec/test-data/roboform-csv/empty-folders.ts create mode 100644 libs/importer/spec/test-data/roboform-csv/with-folders.ts diff --git a/libs/importer/spec/roboform-csv-importer.spec.ts b/libs/importer/spec/roboform-csv-importer.spec.ts new file mode 100644 index 0000000000..9ec63aadfb --- /dev/null +++ b/libs/importer/spec/roboform-csv-importer.spec.ts @@ -0,0 +1,37 @@ +import { CipherType } from "../../common/src/vault/enums/cipher-type"; +import { RoboFormCsvImporter } from "../src/importers"; + +import { data as dataNoFolder } from "./test-data/roboform-csv/empty-folders"; +import { data as dataFolder } from "./test-data/roboform-csv/with-folders"; + +describe("Roboform CSV Importer", () => { + it("should parse CSV data", async () => { + const importer = new RoboFormCsvImporter(); + const result = await importer.parse(dataNoFolder); + expect(result != null).toBe(true); + + expect(result.folders.length).toBe(0); + expect(result.ciphers.length).toBe(5); + expect(result.ciphers[0].name).toBe("Bitwarden"); + expect(result.ciphers[0].login.username).toBe("user@bitwarden.com"); + expect(result.ciphers[0].login.password).toBe("password"); + }); + + it("should parse CSV data with folders", async () => { + const importer = new RoboFormCsvImporter(); + const result = await importer.parse(dataFolder); + expect(result != null).toBe(true); + + expect(result.folders.length).toBe(3); + expect(result.ciphers.length).toBe(5); + }); + + it("should parse CSV data secure note", async () => { + const importer = new RoboFormCsvImporter(); + const result = await importer.parse(dataNoFolder); + expect(result != null).toBe(true); + expect(result.ciphers[4].type).toBe(CipherType.SecureNote); + expect(result.ciphers[4].notes).toBe("This is a safe note"); + expect(result.ciphers[4].name).toBe("note - 2023-03-31"); + }); +}); diff --git a/libs/importer/spec/test-data/roboform-csv/empty-folders.ts b/libs/importer/spec/test-data/roboform-csv/empty-folders.ts new file mode 100644 index 0000000000..0c90f68470 --- /dev/null +++ b/libs/importer/spec/test-data/roboform-csv/empty-folders.ts @@ -0,0 +1,6 @@ +export const data = `Name,Url,MatchUrl,Login,Pwd,Note,Folder,RfFieldsV2 +Bitwarden,https://bitwarden.com,https://bitwarden.com,user@bitwarden.com,password,,,"User ID$,,,txt,user@bitwarden.com","Password$,,,pwd,password" +Test,https://www.test.com/,https://www.test.com/,test@gmail.com,:testPassword,test,,"User ID$,,,txt,test@gmail.com","Password$,,,pwd,:testPassword" +LoginWebsite,https://login.Website.com/,https://login.Website.com/,test@outlook.com,123password,,,"User ID$,,,txt,test@outlook.com","Password$,,,pwd,123password" +Website,https://signin.website.com/,https://signin.website.com/,user@bitwarden.com,password123,Website ,,"User ID$,,,txt,user@bitwarden.com","Password$,,,pwd,password123" +note - 2023-03-31,,,,,This is a safe note,`; diff --git a/libs/importer/spec/test-data/roboform-csv/with-folders.ts b/libs/importer/spec/test-data/roboform-csv/with-folders.ts new file mode 100644 index 0000000000..e836c6430f --- /dev/null +++ b/libs/importer/spec/test-data/roboform-csv/with-folders.ts @@ -0,0 +1,6 @@ +export const data = `Name,Url,MatchUrl,Login,Pwd,Note,Folder,RfFieldsV2 +Bitwarden,https://bitwarden.com,https://bitwarden.com,user@bitwarden.com,password,,folder1,"User ID$,,,txt,user@bitwarden.com","Password$,,,pwd,password" +Test,https://www.test.com/,https://www.test.com/,test@gmail.com,:testPassword,test,folder1,"User ID$,,,txt,test@gmail.com","Password$,,,pwd,:testPassword" +LoginWebsite,https://login.Website.com/,https://login.Website.com/,test@outlook.com,123password,,folder2,"User ID$,,,txt,test@outlook.com","Password$,,,pwd,123password" +Website,https://signin.website.com/,https://signin.website.com/,user@bitwarden.com,password123,Website ,folder3,"User ID$,,,txt,user@bitwarden.com","Password$,,,pwd,password123" +note - 2023-03-31,,,,,This is a safe note,`; diff --git a/libs/importer/src/importers/base-importer.ts b/libs/importer/src/importers/base-importer.ts index 4aef45f61e..7423f4adba 100644 --- a/libs/importer/src/importers/base-importer.ts +++ b/libs/importer/src/importers/base-importer.ts @@ -411,19 +411,20 @@ export abstract class BaseImporter { } protected processFolder(result: ImportResult, folderName: string) { + if (this.isNullOrWhitespace(folderName)) { + return; + } + let folderIndex = result.folders.length; - const hasFolder = !this.isNullOrWhitespace(folderName); // Replace backslashes with forward slashes, ensuring we create sub-folders folderName = folderName.replace("\\", "/"); - let addFolder = hasFolder; + let addFolder = true; - if (hasFolder) { - for (let i = 0; i < result.folders.length; i++) { - if (result.folders[i].name === folderName) { - addFolder = false; - folderIndex = i; - break; - } + for (let i = 0; i < result.folders.length; i++) { + if (result.folders[i].name === folderName) { + addFolder = false; + folderIndex = i; + break; } } @@ -432,9 +433,8 @@ export abstract class BaseImporter { f.name = folderName; result.folders.push(f); } - if (hasFolder) { - result.folderRelationships.push([result.ciphers.length, folderIndex]); - } + + result.folderRelationships.push([result.ciphers.length, folderIndex]); } protected convertToNoteIfNeeded(cipher: CipherView) {