2023-11-27 21:59:44 +01:00
|
|
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
2022-03-07 19:21:23 +01:00
|
|
|
|
2023-03-23 11:43:27 +01:00
|
|
|
import { DashlaneCsvImporter } from "../src/importers";
|
|
|
|
|
2022-11-11 16:20:03 +01:00
|
|
|
import { credentialsData } from "./test-data/dashlane-csv/credentials.csv";
|
|
|
|
import { identityData } from "./test-data/dashlane-csv/id.csv";
|
|
|
|
import { multiplePersonalInfoData } from "./test-data/dashlane-csv/multiple-personal-info.csv";
|
|
|
|
import { paymentsData } from "./test-data/dashlane-csv/payments.csv";
|
|
|
|
import { personalInfoData } from "./test-data/dashlane-csv/personal-info.csv";
|
|
|
|
import { secureNoteData } from "./test-data/dashlane-csv/securenotes.csv";
|
2022-03-07 19:21:23 +01:00
|
|
|
|
|
|
|
describe("Dashlane CSV Importer", () => {
|
2023-03-23 11:43:27 +01:00
|
|
|
let importer: DashlaneCsvImporter;
|
2022-03-07 19:21:23 +01:00
|
|
|
beforeEach(() => {
|
2023-03-23 11:43:27 +01:00
|
|
|
importer = new DashlaneCsvImporter();
|
2022-03-07 19:21:23 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it("should parse login records", async () => {
|
|
|
|
const result = await importer.parse(credentialsData);
|
|
|
|
expect(result != null).toBe(true);
|
|
|
|
|
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.name).toEqual("example.com");
|
|
|
|
expect(cipher.login.username).toEqual("jdoe");
|
|
|
|
expect(cipher.login.password).toEqual("somePassword");
|
|
|
|
expect(cipher.login.totp).toEqual("someTOTPSeed");
|
|
|
|
expect(cipher.login.uris.length).toEqual(1);
|
|
|
|
const uriView = cipher.login.uris.shift();
|
|
|
|
expect(uriView.uri).toEqual("https://www.example.com");
|
|
|
|
expect(cipher.notes).toEqual("some note for example.com");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should parse an item and create a folder", async () => {
|
|
|
|
const result = await importer.parse(credentialsData);
|
|
|
|
|
|
|
|
expect(result).not.toBeNull();
|
|
|
|
expect(result.success).toBe(true);
|
|
|
|
expect(result.folders.length).toBe(1);
|
|
|
|
expect(result.folders[0].name).toBe("Entertainment");
|
|
|
|
expect(result.folderRelationships[0]).toEqual([0, 0]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should parse payment records", async () => {
|
|
|
|
const result = await importer.parse(paymentsData);
|
|
|
|
|
|
|
|
expect(result).not.toBeNull();
|
|
|
|
expect(result.success).toBe(true);
|
|
|
|
expect(result.ciphers.length).toBe(2);
|
|
|
|
|
|
|
|
// Account
|
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.type).toBe(CipherType.Card);
|
|
|
|
expect(cipher.name).toBe("John's savings account");
|
|
|
|
expect(cipher.card.brand).toBeNull();
|
|
|
|
expect(cipher.card.cardholderName).toBe("John Doe");
|
|
|
|
expect(cipher.card.number).toBe("accountNumber");
|
|
|
|
expect(cipher.card.code).toBeNull();
|
|
|
|
expect(cipher.card.expMonth).toBeNull();
|
|
|
|
expect(cipher.card.expYear).toBeNull();
|
|
|
|
|
|
|
|
expect(cipher.fields.length).toBe(4);
|
|
|
|
|
|
|
|
expect(cipher.fields[0].name).toBe("type");
|
|
|
|
expect(cipher.fields[0].value).toBe("bank");
|
|
|
|
|
|
|
|
expect(cipher.fields[1].name).toBe("routing_number");
|
|
|
|
expect(cipher.fields[1].value).toBe("routingNumber");
|
|
|
|
|
|
|
|
expect(cipher.fields[2].name).toBe("country");
|
|
|
|
expect(cipher.fields[2].value).toBe("US");
|
|
|
|
|
|
|
|
expect(cipher.fields[3].name).toBe("issuing_bank");
|
|
|
|
expect(cipher.fields[3].value).toBe("US-ALLY");
|
|
|
|
|
|
|
|
// CreditCard
|
|
|
|
const cipher2 = result.ciphers.shift();
|
|
|
|
expect(cipher2.type).toBe(CipherType.Card);
|
|
|
|
expect(cipher2.name).toBe("John Doe");
|
|
|
|
expect(cipher2.card.brand).toBe("Visa");
|
|
|
|
expect(cipher2.card.cardholderName).toBe("John Doe");
|
|
|
|
expect(cipher2.card.number).toBe("41111111111111111");
|
|
|
|
expect(cipher2.card.code).toBe("123");
|
2023-01-23 15:52:38 +01:00
|
|
|
expect(cipher2.card.expMonth).toBe("1");
|
|
|
|
expect(cipher2.card.expYear).toBe("2023");
|
2022-03-07 19:21:23 +01:00
|
|
|
|
|
|
|
expect(cipher2.fields.length).toBe(2);
|
|
|
|
|
|
|
|
expect(cipher2.fields[0].name).toBe("type");
|
|
|
|
expect(cipher2.fields[0].value).toBe("credit_card");
|
|
|
|
|
|
|
|
expect(cipher2.fields[1].name).toBe("country");
|
|
|
|
expect(cipher2.fields[1].value).toBe("US");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should parse ids records", async () => {
|
|
|
|
const result = await importer.parse(identityData);
|
|
|
|
|
|
|
|
expect(result).not.toBeNull();
|
|
|
|
expect(result.success).toBe(true);
|
|
|
|
|
|
|
|
// Type card
|
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.type).toBe(CipherType.Identity);
|
|
|
|
expect(cipher.name).toBe("John Doe card");
|
|
|
|
expect(cipher.identity.fullName).toBe("John Doe");
|
|
|
|
expect(cipher.identity.firstName).toBe("John");
|
|
|
|
expect(cipher.identity.middleName).toBeNull();
|
|
|
|
expect(cipher.identity.lastName).toBe("Doe");
|
|
|
|
expect(cipher.identity.licenseNumber).toBe("123123123");
|
|
|
|
|
|
|
|
expect(cipher.fields.length).toBe(3);
|
|
|
|
|
|
|
|
expect(cipher.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher.fields[0].value).toEqual("card");
|
|
|
|
|
|
|
|
expect(cipher.fields[1].name).toEqual("issue_date");
|
|
|
|
expect(cipher.fields[1].value).toEqual("2022-1-30");
|
|
|
|
|
|
|
|
expect(cipher.fields[2].name).toEqual("expiration_date");
|
|
|
|
expect(cipher.fields[2].value).toEqual("2032-1-30");
|
|
|
|
|
|
|
|
// Type passport
|
|
|
|
const cipher2 = result.ciphers.shift();
|
|
|
|
expect(cipher2.type).toBe(CipherType.Identity);
|
|
|
|
expect(cipher2.name).toBe("John Doe passport");
|
|
|
|
expect(cipher2.identity.fullName).toBe("John Doe");
|
|
|
|
expect(cipher2.identity.firstName).toBe("John");
|
|
|
|
expect(cipher2.identity.middleName).toBeNull();
|
|
|
|
expect(cipher2.identity.lastName).toBe("Doe");
|
|
|
|
expect(cipher2.identity.passportNumber).toBe("123123123");
|
|
|
|
|
|
|
|
expect(cipher2.fields.length).toBe(4);
|
|
|
|
|
|
|
|
expect(cipher2.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher2.fields[0].value).toEqual("passport");
|
|
|
|
expect(cipher2.fields[1].name).toEqual("issue_date");
|
|
|
|
expect(cipher2.fields[1].value).toEqual("2022-1-30");
|
|
|
|
expect(cipher2.fields[2].name).toEqual("expiration_date");
|
|
|
|
expect(cipher2.fields[2].value).toEqual("2032-1-30");
|
|
|
|
expect(cipher2.fields[3].name).toEqual("place_of_issue");
|
|
|
|
expect(cipher2.fields[3].value).toEqual("somewhere in Germany");
|
|
|
|
|
|
|
|
// Type license
|
|
|
|
const cipher3 = result.ciphers.shift();
|
|
|
|
expect(cipher3.type).toBe(CipherType.Identity);
|
|
|
|
expect(cipher3.name).toBe("John Doe license");
|
|
|
|
expect(cipher3.identity.fullName).toBe("John Doe");
|
|
|
|
expect(cipher3.identity.firstName).toBe("John");
|
|
|
|
expect(cipher3.identity.middleName).toBeNull();
|
|
|
|
expect(cipher3.identity.lastName).toBe("Doe");
|
|
|
|
expect(cipher3.identity.licenseNumber).toBe("1234556");
|
|
|
|
expect(cipher3.identity.state).toBe("DC");
|
|
|
|
|
|
|
|
expect(cipher3.fields.length).toBe(3);
|
|
|
|
expect(cipher3.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher3.fields[0].value).toEqual("license");
|
|
|
|
expect(cipher3.fields[1].name).toEqual("issue_date");
|
|
|
|
expect(cipher3.fields[1].value).toEqual("2022-8-10");
|
|
|
|
expect(cipher3.fields[2].name).toEqual("expiration_date");
|
|
|
|
expect(cipher3.fields[2].value).toEqual("2022-10-10");
|
|
|
|
|
|
|
|
// Type social_security
|
|
|
|
const cipher4 = result.ciphers.shift();
|
|
|
|
expect(cipher4.type).toBe(CipherType.Identity);
|
|
|
|
expect(cipher4.name).toBe("John Doe social_security");
|
|
|
|
expect(cipher4.identity.fullName).toBe("John Doe");
|
|
|
|
expect(cipher4.identity.firstName).toBe("John");
|
|
|
|
expect(cipher4.identity.middleName).toBeNull();
|
|
|
|
expect(cipher4.identity.lastName).toBe("Doe");
|
|
|
|
expect(cipher4.identity.ssn).toBe("123123123");
|
|
|
|
|
|
|
|
expect(cipher4.fields.length).toBe(1);
|
|
|
|
expect(cipher4.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher4.fields[0].value).toEqual("social_security");
|
|
|
|
|
|
|
|
// Type tax_number
|
|
|
|
const cipher5 = result.ciphers.shift();
|
|
|
|
expect(cipher5.type).toBe(CipherType.Identity);
|
|
|
|
expect(cipher5.name).toBe("tax_number");
|
|
|
|
expect(cipher5.identity.licenseNumber).toBe("123123123");
|
|
|
|
|
|
|
|
expect(cipher5.fields.length).toBe(1);
|
|
|
|
expect(cipher5.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher5.fields[0].value).toEqual("tax_number");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should parse secureNote records", async () => {
|
|
|
|
const result = await importer.parse(secureNoteData);
|
|
|
|
|
|
|
|
expect(result).not.toBeNull();
|
|
|
|
expect(result.success).toBe(true);
|
|
|
|
expect(result.ciphers.length).toBe(1);
|
|
|
|
|
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.type).toBe(CipherType.SecureNote);
|
|
|
|
expect(cipher.name).toBe("01");
|
|
|
|
expect(cipher.notes).toBe("test");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should parse personal information records (multiple identities)", async () => {
|
|
|
|
const result = await importer.parse(multiplePersonalInfoData);
|
|
|
|
|
|
|
|
expect(result).not.toBeNull();
|
|
|
|
expect(result.success).toBe(true);
|
|
|
|
expect(result.ciphers.length).toBe(6);
|
|
|
|
|
|
|
|
// name
|
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.type).toBe(CipherType.SecureNote);
|
|
|
|
expect(cipher.name).toBe("MR John Doe");
|
|
|
|
|
|
|
|
expect(cipher.fields.length).toBe(7);
|
|
|
|
expect(cipher.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher.fields[0].value).toEqual("name");
|
|
|
|
expect(cipher.fields[1].name).toEqual("title");
|
|
|
|
expect(cipher.fields[1].value).toEqual("MR");
|
|
|
|
expect(cipher.fields[2].name).toEqual("first_name");
|
|
|
|
expect(cipher.fields[2].value).toEqual("John");
|
|
|
|
expect(cipher.fields[3].name).toEqual("last_name");
|
|
|
|
expect(cipher.fields[3].value).toEqual("Doe");
|
|
|
|
expect(cipher.fields[4].name).toEqual("login");
|
|
|
|
expect(cipher.fields[4].value).toEqual("jdoe");
|
|
|
|
expect(cipher.fields[5].name).toEqual("date_of_birth");
|
|
|
|
expect(cipher.fields[5].value).toEqual("2022-01-30");
|
|
|
|
expect(cipher.fields[6].name).toEqual("place_of_birth");
|
|
|
|
expect(cipher.fields[6].value).toEqual("world");
|
|
|
|
|
|
|
|
// email
|
|
|
|
const cipher2 = result.ciphers.shift();
|
|
|
|
expect(cipher2.type).toBe(CipherType.SecureNote);
|
|
|
|
expect(cipher2.name).toBe("Johns email");
|
|
|
|
|
|
|
|
expect(cipher2.fields.length).toBe(4);
|
|
|
|
expect(cipher2.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher2.fields[0].value).toEqual("email");
|
|
|
|
expect(cipher2.fields[1].name).toEqual("email");
|
|
|
|
expect(cipher2.fields[1].value).toEqual("jdoe@example.com");
|
|
|
|
expect(cipher2.fields[2].name).toEqual("email_type");
|
|
|
|
expect(cipher2.fields[2].value).toEqual("personal");
|
|
|
|
expect(cipher2.fields[3].name).toEqual("item_name");
|
|
|
|
expect(cipher2.fields[3].value).toEqual("Johns email");
|
|
|
|
|
|
|
|
// number
|
|
|
|
const cipher3 = result.ciphers.shift();
|
|
|
|
expect(cipher3.type).toBe(CipherType.SecureNote);
|
|
|
|
expect(cipher3.name).toBe("John's number");
|
|
|
|
|
|
|
|
expect(cipher3.fields.length).toBe(3);
|
|
|
|
expect(cipher3.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher3.fields[0].value).toEqual("number");
|
|
|
|
expect(cipher3.fields[1].name).toEqual("item_name");
|
|
|
|
expect(cipher3.fields[1].value).toEqual("John's number");
|
|
|
|
expect(cipher3.fields[2].name).toEqual("phone_number");
|
|
|
|
expect(cipher3.fields[2].value).toEqual("+49123123123");
|
|
|
|
|
|
|
|
// address
|
|
|
|
const cipher4 = result.ciphers.shift();
|
|
|
|
expect(cipher4.type).toBe(CipherType.SecureNote);
|
|
|
|
expect(cipher4.name).toBe("John's home address");
|
|
|
|
|
|
|
|
expect(cipher4.fields.length).toBe(12);
|
|
|
|
expect(cipher4.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher4.fields[0].value).toEqual("address");
|
|
|
|
expect(cipher4.fields[1].name).toEqual("item_name");
|
|
|
|
expect(cipher4.fields[1].value).toEqual("John's home address");
|
|
|
|
expect(cipher4.fields[2].name).toEqual("address");
|
|
|
|
expect(cipher4.fields[2].value).toEqual("1 some street");
|
|
|
|
expect(cipher4.fields[3].name).toEqual("country");
|
|
|
|
expect(cipher4.fields[3].value).toEqual("de");
|
|
|
|
expect(cipher4.fields[4].name).toEqual("state");
|
|
|
|
expect(cipher4.fields[4].value).toEqual("DE-0-NW");
|
|
|
|
expect(cipher4.fields[5].name).toEqual("city");
|
|
|
|
expect(cipher4.fields[5].value).toEqual("some city");
|
|
|
|
expect(cipher4.fields[6].name).toEqual("zip");
|
|
|
|
expect(cipher4.fields[6].value).toEqual("123123");
|
|
|
|
expect(cipher4.fields[7].name).toEqual("address_recipient");
|
|
|
|
expect(cipher4.fields[7].value).toEqual("John");
|
|
|
|
expect(cipher4.fields[8].name).toEqual("address_building");
|
|
|
|
expect(cipher4.fields[8].value).toEqual("1");
|
|
|
|
expect(cipher4.fields[9].name).toEqual("address_apartment");
|
|
|
|
expect(cipher4.fields[9].value).toEqual("1");
|
|
|
|
expect(cipher4.fields[10].name).toEqual("address_floor");
|
|
|
|
expect(cipher4.fields[10].value).toEqual("1");
|
|
|
|
expect(cipher4.fields[11].name).toEqual("address_door_code");
|
|
|
|
expect(cipher4.fields[11].value).toEqual("123");
|
|
|
|
|
|
|
|
// website
|
|
|
|
const cipher5 = result.ciphers.shift();
|
|
|
|
expect(cipher5.type).toBe(CipherType.SecureNote);
|
|
|
|
expect(cipher5.name).toBe("Website");
|
|
|
|
|
|
|
|
expect(cipher5.fields.length).toBe(3);
|
|
|
|
expect(cipher5.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher5.fields[0].value).toEqual("website");
|
|
|
|
expect(cipher5.fields[1].name).toEqual("item_name");
|
|
|
|
expect(cipher5.fields[1].value).toEqual("Website");
|
|
|
|
expect(cipher5.fields[2].name).toEqual("url");
|
|
|
|
expect(cipher5.fields[2].value).toEqual("website.com");
|
|
|
|
|
|
|
|
// 2nd name/identity
|
|
|
|
const cipher6 = result.ciphers.shift();
|
|
|
|
expect(cipher6.type).toBe(CipherType.SecureNote);
|
|
|
|
expect(cipher6.name).toBe("Mrs Jane Doe");
|
|
|
|
|
|
|
|
expect(cipher6.fields.length).toBe(7);
|
|
|
|
expect(cipher6.fields[0].name).toEqual("type");
|
|
|
|
expect(cipher6.fields[0].value).toEqual("name");
|
|
|
|
expect(cipher6.fields[1].name).toEqual("title");
|
|
|
|
expect(cipher6.fields[1].value).toEqual("Mrs");
|
|
|
|
expect(cipher6.fields[2].name).toEqual("first_name");
|
|
|
|
expect(cipher6.fields[2].value).toEqual("Jane");
|
|
|
|
expect(cipher6.fields[3].name).toEqual("last_name");
|
|
|
|
expect(cipher6.fields[3].value).toEqual("Doe");
|
|
|
|
expect(cipher6.fields[4].name).toEqual("login");
|
|
|
|
expect(cipher6.fields[4].value).toEqual("jdoe");
|
|
|
|
expect(cipher6.fields[5].name).toEqual("date_of_birth");
|
|
|
|
expect(cipher6.fields[5].value).toEqual("2022-01-30");
|
|
|
|
expect(cipher6.fields[6].name).toEqual("place_of_birth");
|
|
|
|
expect(cipher6.fields[6].value).toEqual("earth");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should combine personal information records to one identity if only one identity present", async () => {
|
|
|
|
const result = await importer.parse(personalInfoData);
|
|
|
|
|
|
|
|
expect(result).not.toBeNull();
|
|
|
|
expect(result.success).toBe(true);
|
|
|
|
|
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.type).toBe(CipherType.Identity);
|
|
|
|
expect(cipher.name).toBe("MR John Doe");
|
|
|
|
expect(cipher.identity.fullName).toBe("MR John Doe");
|
|
|
|
expect(cipher.identity.title).toBe("MR");
|
|
|
|
expect(cipher.identity.firstName).toBe("John");
|
|
|
|
expect(cipher.identity.middleName).toBeNull();
|
|
|
|
expect(cipher.identity.lastName).toBe("Doe");
|
|
|
|
expect(cipher.identity.username).toBe("jdoe");
|
|
|
|
expect(cipher.identity.email).toBe("jdoe@example.com");
|
|
|
|
expect(cipher.identity.phone).toBe("+49123123123");
|
|
|
|
|
|
|
|
expect(cipher.fields.length).toBe(9);
|
|
|
|
expect(cipher.fields[0].name).toBe("date_of_birth");
|
|
|
|
expect(cipher.fields[0].value).toBe("2022-01-30");
|
|
|
|
|
|
|
|
expect(cipher.fields[1].name).toBe("place_of_birth");
|
|
|
|
expect(cipher.fields[1].value).toBe("world");
|
|
|
|
|
|
|
|
expect(cipher.fields[2].name).toBe("email_type");
|
|
|
|
expect(cipher.fields[2].value).toBe("personal");
|
|
|
|
|
|
|
|
expect(cipher.fields[3].name).toBe("address_recipient");
|
|
|
|
expect(cipher.fields[3].value).toBe("John");
|
|
|
|
|
|
|
|
expect(cipher.fields[4].name).toBe("address_building");
|
|
|
|
expect(cipher.fields[4].value).toBe("1");
|
|
|
|
|
|
|
|
expect(cipher.fields[5].name).toBe("address_apartment");
|
|
|
|
expect(cipher.fields[5].value).toBe("1");
|
|
|
|
|
|
|
|
expect(cipher.fields[6].name).toBe("address_floor");
|
|
|
|
expect(cipher.fields[6].value).toBe("1");
|
|
|
|
|
|
|
|
expect(cipher.fields[7].name).toBe("address_door_code");
|
|
|
|
expect(cipher.fields[7].value).toBe("123");
|
|
|
|
|
|
|
|
expect(cipher.fields[8].name).toBe("url");
|
|
|
|
expect(cipher.fields[8].value).toBe("website.com");
|
|
|
|
});
|
|
|
|
});
|