From 81d1274111636040b1f3e40d0bd1547b58a12550 Mon Sep 17 00:00:00 2001 From: Zilong Xue <114327061+ZilongXue@users.noreply.github.com> Date: Fri, 18 Oct 2024 13:37:32 -0500 Subject: [PATCH] Fix: Add TOTP import support to KeePassX CSV importer (#11574) KeePassX CSV importer was missing TOTP field support. Added logic to parse TOTP fields from the CSV and include them in the vault entries. Added unit tests to verify TOTP import functionality. --- .../spec/keepassx-csv-importer.spec.ts | 42 +++++++++++++++++++ .../test-data/keepassx-csv/testdata.csv.ts | 3 ++ .../src/importers/keepassx-csv-importer.ts | 2 + 3 files changed, 47 insertions(+) create mode 100644 libs/importer/spec/keepassx-csv-importer.spec.ts create mode 100644 libs/importer/spec/test-data/keepassx-csv/testdata.csv.ts diff --git a/libs/importer/spec/keepassx-csv-importer.spec.ts b/libs/importer/spec/keepassx-csv-importer.spec.ts new file mode 100644 index 0000000000..0b3d729d9d --- /dev/null +++ b/libs/importer/spec/keepassx-csv-importer.spec.ts @@ -0,0 +1,42 @@ +import { KeePassXCsvImporter } from "../src/importers"; + +import { keepassxTestData } from "./test-data/keepassx-csv/testdata.csv"; + +describe("KeePassX CSV Importer", () => { + let importer: KeePassXCsvImporter; + + beforeEach(() => { + importer = new KeePassXCsvImporter(); + }); + + describe("given login data", () => { + it("should parse login data when provided valid CSV", async () => { + const result = await importer.parse(keepassxTestData); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.name).toEqual("Example Entry"); + expect(cipher.login.username).toEqual("testuser"); + expect(cipher.login.password).toEqual("password123"); + expect(cipher.login.uris.length).toEqual(1); + const uriView = cipher.login.uris.shift(); + expect(uriView.uri).toEqual("https://example.com"); + expect(cipher.notes).toEqual("Some notes"); + }); + + it("should import TOTP when present in the CSV", async () => { + const result = await importer.parse(keepassxTestData); + expect(result != null).toBe(true); + + const cipher = result.ciphers.pop(); + expect(cipher.name).toEqual("Another Entry"); + expect(cipher.login.username).toEqual("anotheruser"); + expect(cipher.login.password).toEqual("anotherpassword"); + expect(cipher.login.uris.length).toEqual(1); + const uriView = cipher.login.uris.shift(); + expect(uriView.uri).toEqual("https://another.com"); + expect(cipher.notes).toEqual("Another set of notes"); + expect(cipher.login.totp).toEqual("otpauth://totp/Another?secret=ABCD1234EFGH5678"); + }); + }); +}); diff --git a/libs/importer/spec/test-data/keepassx-csv/testdata.csv.ts b/libs/importer/spec/test-data/keepassx-csv/testdata.csv.ts new file mode 100644 index 0000000000..99eb99b993 --- /dev/null +++ b/libs/importer/spec/test-data/keepassx-csv/testdata.csv.ts @@ -0,0 +1,3 @@ +export const keepassxTestData = `Title,Username,Password,URL,Notes,TOTP +Example Entry,testuser,password123,https://example.com,Some notes, +Another Entry,anotheruser,anotherpassword,https://another.com,Another set of notes,otpauth://totp/Another?secret=ABCD1234EFGH5678`; diff --git a/libs/importer/src/importers/keepassx-csv-importer.ts b/libs/importer/src/importers/keepassx-csv-importer.ts index 4047a49d57..03aa18cecb 100644 --- a/libs/importer/src/importers/keepassx-csv-importer.ts +++ b/libs/importer/src/importers/keepassx-csv-importer.ts @@ -30,6 +30,8 @@ export class KeePassXCsvImporter extends BaseImporter implements Importer { cipher.login.username = this.getValueOrDefault(value.Username); cipher.login.password = this.getValueOrDefault(value.Password); cipher.login.uris = this.makeUriArray(value.URL); + cipher.login.totp = this.getValueOrDefault(value.TOTP); + this.cleanupCipher(cipher); result.ciphers.push(cipher); });