1password 1pif importer: create identity records (#34)
* 1password 1pif importer: create identity records * importer: do not store empty strings replace them with null instead
This commit is contained in:
parent
c17e8b458c
commit
2bd47a19df
|
@ -61,6 +61,284 @@ const TestData: string = '***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n' +
|
||||||
typeName: 'webforms.WebForm',
|
typeName: 'webforms.WebForm',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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', () => {
|
describe('1Password 1Pif Importer', () => {
|
||||||
it('should parse data', async () => {
|
it('should parse data', async () => {
|
||||||
const importer = new Importer();
|
const importer = new Importer();
|
||||||
|
@ -92,4 +370,27 @@ describe('1Password 1Pif Importer', () => {
|
||||||
expect(field.value).toEqual('console-password-123');
|
expect(field.value).toEqual('console-password-123');
|
||||||
expect(field.type).toEqual(FieldType.Hidden);
|
expect(field.type).toEqual(FieldType.Hidden);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should create identity records', async () => {
|
||||||
|
const importer = new Importer();
|
||||||
|
const result = 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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { ImportResult } from '../models/domain/importResult';
|
||||||
|
|
||||||
import { CardView } from '../models/view/cardView';
|
import { CardView } from '../models/view/cardView';
|
||||||
import { CipherView } from '../models/view/cipherView';
|
import { CipherView } from '../models/view/cipherView';
|
||||||
|
import { IdentityView } from '../models/view/identityView';
|
||||||
import { SecureNoteView } from '../models/view/secureNoteView';
|
import { SecureNoteView } from '../models/view/secureNoteView';
|
||||||
|
|
||||||
import { CipherType } from '../enums/cipherType';
|
import { CipherType } from '../enums/cipherType';
|
||||||
|
@ -86,6 +87,9 @@ export class OnePassword1PifImporter extends BaseImporter implements Importer {
|
||||||
} else if (item.typeName === 'wallet.financial.CreditCard') {
|
} else if (item.typeName === 'wallet.financial.CreditCard') {
|
||||||
cipher.type = CipherType.Card;
|
cipher.type = CipherType.Card;
|
||||||
cipher.card = new CardView();
|
cipher.card = new CardView();
|
||||||
|
} else if (item.typeName === 'identities.Identity') {
|
||||||
|
cipher.type = CipherType.Identity;
|
||||||
|
cipher.identity = new IdentityView();
|
||||||
} else {
|
} else {
|
||||||
cipher.login.uris = this.makeUriArray(item.location);
|
cipher.login.uris = this.makeUriArray(item.location);
|
||||||
}
|
}
|
||||||
|
@ -167,6 +171,36 @@ export class OnePassword1PifImporter extends BaseImporter implements Importer {
|
||||||
// Skip since brand was determined from number above
|
// Skip since brand was determined from number above
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (cipher.type === CipherType.Identity) {
|
||||||
|
const identity = cipher.identity;
|
||||||
|
|
||||||
|
if (this.isNullOrWhitespace(identity.firstName) && fieldDesignation === 'firstname') {
|
||||||
|
identity.firstName = fieldValue;
|
||||||
|
return;
|
||||||
|
} else if (this.isNullOrWhitespace(identity.lastName) && fieldDesignation === 'lastname') {
|
||||||
|
identity.lastName = fieldValue;
|
||||||
|
return;
|
||||||
|
} else if (this.isNullOrWhitespace(identity.middleName) && fieldDesignation === 'initial') {
|
||||||
|
identity.middleName = fieldValue;
|
||||||
|
return;
|
||||||
|
} else if (this.isNullOrWhitespace(identity.phone) && fieldDesignation === 'defphone') {
|
||||||
|
identity.phone = fieldValue;
|
||||||
|
return;
|
||||||
|
} else if (this.isNullOrWhitespace(identity.company) && fieldDesignation === 'company') {
|
||||||
|
identity.company = fieldValue;
|
||||||
|
return;
|
||||||
|
} else if (this.isNullOrWhitespace(identity.email) && fieldDesignation === 'email') {
|
||||||
|
identity.email = fieldValue;
|
||||||
|
return;
|
||||||
|
} else if (fieldDesignation === 'address') {
|
||||||
|
// fieldValue is an object casted into a string, so access the plain value instead
|
||||||
|
const { street, city, country, zip } = field[valueKey];
|
||||||
|
identity.address1 = this.getValueOrDefault(street);
|
||||||
|
identity.city = this.getValueOrDefault(city);
|
||||||
|
identity.country = this.getValueOrDefault(country); // lower case iso code
|
||||||
|
identity.postalCode = this.getValueOrDefault(zip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fieldType = field.k === 'concealed' ? FieldType.Hidden : FieldType.Text;
|
const fieldType = field.k === 'concealed' ? FieldType.Hidden : FieldType.Text;
|
||||||
|
|
Loading…
Reference in New Issue