mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-23 11:56:00 +01:00
a8168d6ee7
* Format the fieldvalue as a LocaleDateString instead of epoch when importing a date from 1P This would be better solved by storing it as a date FieldType instead of Text. But since it is unclear when new field types are added, this solution serves as a fix for now and also guides the solution when new fieldtype exists. * Remove trailing whitespace * Add tests for custom fields of 1pif imported identity * Change representation of 1pif imported dates to UTC string * Changes after running prettier Co-authored-by: Daniel James Smith <djsmith@web.de>
528 lines
13 KiB
TypeScript
528 lines
13 KiB
TypeScript
import { FieldType } from "jslib-common/enums/fieldType";
|
|
import { OnePassword1PifImporter as Importer } from "jslib-common/importers/onepasswordImporters/onepassword1PifImporter";
|
|
|
|
const TestData: string =
|
|
"***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n" +
|
|
JSON.stringify({
|
|
uuid: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
updatedAt: 1486071244,
|
|
securityLevel: "SL5",
|
|
contentsHash: "aaaaaaaa",
|
|
title: "Imported Entry",
|
|
location: "https://www.google.com",
|
|
secureContents: {
|
|
fields: [
|
|
{
|
|
value: "user@test.net",
|
|
id: "email-input",
|
|
name: "email",
|
|
type: "T",
|
|
designation: "username",
|
|
},
|
|
{
|
|
value: "myservicepassword",
|
|
id: "password-input",
|
|
name: "password",
|
|
type: "P",
|
|
designation: "password",
|
|
},
|
|
],
|
|
sections: [
|
|
{
|
|
fields: [
|
|
{
|
|
k: "concealed",
|
|
n: "AAAAAAAAAAAABBBBBBBBBBBCCCCCCCCC",
|
|
v: "console-password-123",
|
|
t: "console password",
|
|
},
|
|
],
|
|
title: "Admin Console",
|
|
name: "admin_console",
|
|
},
|
|
],
|
|
passwordHistory: [
|
|
{
|
|
value: "old-password",
|
|
time: 1447791421,
|
|
},
|
|
],
|
|
},
|
|
URLs: [
|
|
{
|
|
label: "website",
|
|
url: "https://www.google.com",
|
|
},
|
|
],
|
|
txTimestamp: 1508941334,
|
|
createdAt: 1390426636,
|
|
typeName: "webforms.WebForm",
|
|
});
|
|
|
|
const WindowsOpVaultTestData = JSON.stringify({
|
|
category: "001",
|
|
created: 1544823719,
|
|
hmac: "NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=",
|
|
k: "**REMOVED LONG LINE FOR LINTER** -Kyle",
|
|
tx: 1553395669,
|
|
updated: 1553395669,
|
|
uuid: "528AB076FB5F4FBF960884B8E01619AC",
|
|
overview: {
|
|
title: "Google",
|
|
URLs: [
|
|
{
|
|
u: "google.com",
|
|
},
|
|
],
|
|
url: "google.com",
|
|
ps: 26,
|
|
ainfo: "googluser",
|
|
},
|
|
details: {
|
|
passwordHistory: [
|
|
{
|
|
value: "oldpass1",
|
|
time: 1553394449,
|
|
},
|
|
{
|
|
value: "oldpass2",
|
|
time: 1553394457,
|
|
},
|
|
{
|
|
value: "oldpass3",
|
|
time: 1553394458,
|
|
},
|
|
{
|
|
value: "oldpass4",
|
|
time: 1553394459,
|
|
},
|
|
{
|
|
value: "oldpass5",
|
|
time: 1553394460,
|
|
},
|
|
{
|
|
value: "oldpass6",
|
|
time: 1553394461,
|
|
},
|
|
],
|
|
fields: [
|
|
{
|
|
type: "T",
|
|
id: "username",
|
|
name: "username",
|
|
value: "googluser",
|
|
designation: "username",
|
|
},
|
|
{
|
|
type: "P",
|
|
id: "password",
|
|
name: "password",
|
|
value: "12345678901",
|
|
designation: "password",
|
|
},
|
|
],
|
|
notesPlain: "This is a note\r\n\r\nline1\r\nline2",
|
|
sections: [
|
|
{
|
|
title: "test",
|
|
name: "1214FD88CD30405D9EED14BEB4D61B60",
|
|
fields: [
|
|
{
|
|
k: "string",
|
|
n: "6CC3BD77482D4559A4B8BB2D360F821B",
|
|
v: "fgfg",
|
|
t: "fgggf",
|
|
},
|
|
{
|
|
k: "concealed",
|
|
n: "5CFE7BCAA1DF4578BBF7EB508959BFF3",
|
|
v: "dfgdfgfdg",
|
|
t: "pwfield",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const IdentityTestData = JSON.stringify({
|
|
uuid: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
updatedAt: 1553365894,
|
|
securityLevel: "SL5",
|
|
contentsHash: "eeeeeeee",
|
|
title: "Test Identity",
|
|
secureContents: {
|
|
lastname: "Fritzenberger",
|
|
zip: "223344",
|
|
birthdate_dd: "11",
|
|
homephone: "+49 333 222 111",
|
|
company: "Web Inc.",
|
|
firstname: "Frank",
|
|
birthdate_mm: "3",
|
|
country: "de",
|
|
sex: "male",
|
|
sections: [
|
|
{
|
|
fields: [
|
|
{
|
|
k: "string",
|
|
inputTraits: {
|
|
autocapitalization: "Words",
|
|
},
|
|
n: "firstname",
|
|
v: "Frank",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "first name",
|
|
},
|
|
{
|
|
k: "string",
|
|
inputTraits: {
|
|
autocapitalization: "Words",
|
|
},
|
|
n: "initial",
|
|
v: "MD",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "initial",
|
|
},
|
|
{
|
|
k: "string",
|
|
inputTraits: {
|
|
autocapitalization: "Words",
|
|
},
|
|
n: "lastname",
|
|
v: "Fritzenberger",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "last name",
|
|
},
|
|
{
|
|
k: "menu",
|
|
v: "male",
|
|
n: "sex",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "sex",
|
|
},
|
|
{
|
|
k: "date",
|
|
v: 1552305660,
|
|
n: "birthdate",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "birth date",
|
|
},
|
|
{
|
|
k: "string",
|
|
inputTraits: {
|
|
autocapitalization: "Words",
|
|
},
|
|
n: "occupation",
|
|
v: "Engineer",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "occupation",
|
|
},
|
|
{
|
|
k: "string",
|
|
inputTraits: {
|
|
autocapitalization: "Words",
|
|
},
|
|
n: "company",
|
|
v: "Web Inc.",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "company",
|
|
},
|
|
{
|
|
k: "string",
|
|
inputTraits: {
|
|
autocapitalization: "Words",
|
|
},
|
|
n: "department",
|
|
v: "IT",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "department",
|
|
},
|
|
{
|
|
k: "string",
|
|
inputTraits: {
|
|
autocapitalization: "Words",
|
|
},
|
|
n: "jobtitle",
|
|
v: "Developer",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "job title",
|
|
},
|
|
],
|
|
title: "Identification",
|
|
name: "name",
|
|
},
|
|
{
|
|
fields: [
|
|
{
|
|
k: "address",
|
|
inputTraits: {
|
|
autocapitalization: "Sentences",
|
|
},
|
|
n: "address",
|
|
v: {
|
|
street: "Mainstreet 1",
|
|
city: "Berlin",
|
|
country: "de",
|
|
zip: "223344",
|
|
},
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "address",
|
|
},
|
|
{
|
|
k: "phone",
|
|
v: "+49 001 222 333 44",
|
|
n: "defphone",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "default phone",
|
|
},
|
|
{
|
|
k: "phone",
|
|
v: "+49 333 222 111",
|
|
n: "homephone",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "home",
|
|
},
|
|
{
|
|
k: "phone",
|
|
n: "cellphone",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "mobile",
|
|
},
|
|
{
|
|
k: "phone",
|
|
n: "busphone",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "business",
|
|
},
|
|
],
|
|
title: "Address",
|
|
name: "address",
|
|
},
|
|
{
|
|
fields: [
|
|
{
|
|
k: "string",
|
|
n: "username",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "username",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "reminderq",
|
|
t: "reminder question",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "remindera",
|
|
t: "reminder answer",
|
|
},
|
|
{
|
|
k: "string",
|
|
inputTraits: {
|
|
keyboard: "EmailAddress",
|
|
},
|
|
n: "email",
|
|
v: "test@web.de",
|
|
a: {
|
|
guarded: "yes",
|
|
},
|
|
t: "email",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "website",
|
|
inputTraits: {
|
|
keyboard: "URL",
|
|
},
|
|
t: "website",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "icq",
|
|
t: "ICQ",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "skype",
|
|
t: "skype",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "aim",
|
|
t: "AOL/AIM",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "yahoo",
|
|
t: "Yahoo",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "msn",
|
|
t: "MSN",
|
|
},
|
|
{
|
|
k: "string",
|
|
n: "forumsig",
|
|
t: "forum signature",
|
|
},
|
|
],
|
|
title: "Internet Details",
|
|
name: "internet",
|
|
},
|
|
{
|
|
title: "Related Items",
|
|
name: "linked items",
|
|
},
|
|
],
|
|
initial: "MD",
|
|
address1: "Mainstreet 1",
|
|
city: "Berlin",
|
|
jobtitle: "Developer",
|
|
occupation: "Engineer",
|
|
department: "IT",
|
|
email: "test@web.de",
|
|
birthdate_yy: "2019",
|
|
homephone_local: "+49 333 222 111",
|
|
defphone_local: "+49 001 222 333 44",
|
|
defphone: "+49 001 222 333 44",
|
|
},
|
|
txTimestamp: 1553365894,
|
|
createdAt: 1553364679,
|
|
typeName: "identities.Identity",
|
|
});
|
|
|
|
describe("1Password 1Pif Importer", () => {
|
|
it("should parse data", async () => {
|
|
const importer = new Importer();
|
|
const result = await importer.parse(TestData);
|
|
expect(result != null).toBe(true);
|
|
|
|
const cipher = result.ciphers.shift();
|
|
expect(cipher.login.username).toEqual("user@test.net");
|
|
expect(cipher.login.password).toEqual("myservicepassword");
|
|
expect(cipher.login.uris.length).toEqual(1);
|
|
const uriView = cipher.login.uris.shift();
|
|
expect(uriView.uri).toEqual("https://www.google.com");
|
|
});
|
|
|
|
it('should create concealed field as "hidden" type', async () => {
|
|
const importer = new Importer();
|
|
const result = await importer.parse(TestData);
|
|
expect(result != null).toBe(true);
|
|
|
|
const ciphers = result.ciphers;
|
|
expect(ciphers.length).toEqual(1);
|
|
|
|
const cipher = ciphers.shift();
|
|
const fields = cipher.fields;
|
|
expect(fields.length).toEqual(1);
|
|
|
|
const field = fields.shift();
|
|
expect(field.name).toEqual("console password");
|
|
expect(field.value).toEqual("console-password-123");
|
|
expect(field.type).toEqual(FieldType.Hidden);
|
|
});
|
|
|
|
it("should create identity records", async () => {
|
|
const importer = new Importer();
|
|
const result = await importer.parse(IdentityTestData);
|
|
expect(result != null).toBe(true);
|
|
const cipher = result.ciphers.shift();
|
|
expect(cipher.name).toEqual("Test Identity");
|
|
|
|
const identity = cipher.identity;
|
|
expect(identity.firstName).toEqual("Frank");
|
|
expect(identity.middleName).toEqual("MD");
|
|
expect(identity.lastName).toEqual("Fritzenberger");
|
|
expect(identity.company).toEqual("Web Inc.");
|
|
expect(identity.address1).toEqual("Mainstreet 1");
|
|
expect(identity.country).toEqual("DE");
|
|
expect(identity.city).toEqual("Berlin");
|
|
expect(identity.postalCode).toEqual("223344");
|
|
expect(identity.phone).toEqual("+49 001 222 333 44");
|
|
expect(identity.email).toEqual("test@web.de");
|
|
|
|
// remaining fields as custom fields
|
|
expect(cipher.fields.length).toEqual(6);
|
|
const fields = cipher.fields;
|
|
expect(fields[0].name).toEqual("sex");
|
|
expect(fields[0].value).toEqual("male");
|
|
expect(fields[1].name).toEqual("birth date");
|
|
expect(fields[1].value).toEqual("Mon, 11 Mar 2019 12:01:00 GMT");
|
|
expect(fields[2].name).toEqual("occupation");
|
|
expect(fields[2].value).toEqual("Engineer");
|
|
expect(fields[3].name).toEqual("department");
|
|
expect(fields[3].value).toEqual("IT");
|
|
expect(fields[4].name).toEqual("job title");
|
|
expect(fields[4].value).toEqual("Developer");
|
|
expect(fields[5].name).toEqual("home");
|
|
expect(fields[5].value).toEqual("+49 333 222 111");
|
|
});
|
|
|
|
it("should create password history", async () => {
|
|
const importer = new Importer();
|
|
const result = await importer.parse(TestData);
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.passwordHistory.length).toEqual(1);
|
|
const ph = cipher.passwordHistory.shift();
|
|
expect(ph.password).toEqual("old-password");
|
|
expect(ph.lastUsedDate.toISOString()).toEqual("2015-11-17T20:17:01.000Z");
|
|
});
|
|
|
|
it("should create password history from windows opvault 1pif format", async () => {
|
|
const importer = new Importer();
|
|
const result = await importer.parse(WindowsOpVaultTestData);
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.passwordHistory.length).toEqual(5);
|
|
let ph = cipher.passwordHistory.shift();
|
|
expect(ph.password).toEqual("oldpass6");
|
|
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:41.000Z");
|
|
ph = cipher.passwordHistory.shift();
|
|
expect(ph.password).toEqual("oldpass5");
|
|
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:40.000Z");
|
|
ph = cipher.passwordHistory.shift();
|
|
expect(ph.password).toEqual("oldpass4");
|
|
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:39.000Z");
|
|
ph = cipher.passwordHistory.shift();
|
|
expect(ph.password).toEqual("oldpass3");
|
|
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:38.000Z");
|
|
ph = cipher.passwordHistory.shift();
|
|
expect(ph.password).toEqual("oldpass2");
|
|
expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:37.000Z");
|
|
});
|
|
});
|