sort and limit password history parsing
This commit is contained in:
parent
8ed27eeeec
commit
58c34b896c
|
@ -12,62 +12,62 @@ if (Utils.isNode) {
|
||||||
|
|
||||||
const TestData: string = '***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n' +
|
const TestData: string = '***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n' +
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||||
updatedAt: 1486071244,
|
updatedAt: 1486071244,
|
||||||
securityLevel: 'SL5',
|
securityLevel: 'SL5',
|
||||||
contentsHash: 'aaaaaaaa',
|
contentsHash: 'aaaaaaaa',
|
||||||
title: 'Imported Entry',
|
title: 'Imported Entry',
|
||||||
location: 'https://www.google.com',
|
location: 'https://www.google.com',
|
||||||
secureContents: {
|
secureContents: {
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
value: 'user@test.net',
|
value: 'user@test.net',
|
||||||
id: 'email-input',
|
id: 'email-input',
|
||||||
name: 'email',
|
name: 'email',
|
||||||
type: 'T',
|
type: 'T',
|
||||||
designation: 'username',
|
designation: 'username',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'myservicepassword',
|
value: 'myservicepassword',
|
||||||
id: 'password-input',
|
id: 'password-input',
|
||||||
name: 'password',
|
name: 'password',
|
||||||
type: 'P',
|
type: 'P',
|
||||||
designation: 'password',
|
designation: 'password',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
k: 'concealed',
|
k: 'concealed',
|
||||||
n: 'AAAAAAAAAAAABBBBBBBBBBBCCCCCCCCC',
|
n: 'AAAAAAAAAAAABBBBBBBBBBBCCCCCCCCC',
|
||||||
v: 'console-password-123',
|
v: 'console-password-123',
|
||||||
t: 'console password',
|
t: 'console password',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
title: 'Admin Console',
|
title: 'Admin Console',
|
||||||
name: 'admin_console',
|
name: 'admin_console',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
passwordHistory: [
|
passwordHistory: [
|
||||||
{
|
{
|
||||||
value: 'old-password',
|
value: 'old-password',
|
||||||
time: 1447791421,
|
time: 1447791421,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
|
||||||
URLs: [
|
|
||||||
{
|
|
||||||
label: 'website',
|
|
||||||
url: 'https://www.google.com',
|
|
||||||
},
|
},
|
||||||
],
|
URLs: [
|
||||||
txTimestamp: 1508941334,
|
{
|
||||||
createdAt: 1390426636,
|
label: 'website',
|
||||||
typeName: 'webforms.WebForm',
|
url: 'https://www.google.com',
|
||||||
});
|
},
|
||||||
|
],
|
||||||
|
txTimestamp: 1508941334,
|
||||||
|
createdAt: 1390426636,
|
||||||
|
typeName: 'webforms.WebForm',
|
||||||
|
});
|
||||||
|
|
||||||
const WindowsTestData = JSON.stringify({
|
const WindowsOpVaultTestData = JSON.stringify({
|
||||||
category: '001',
|
category: '001',
|
||||||
created: 1544823719,
|
created: 1544823719,
|
||||||
hmac: 'NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=',
|
hmac: 'NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=',
|
||||||
|
@ -89,13 +89,29 @@ const WindowsTestData = JSON.stringify({
|
||||||
details: {
|
details: {
|
||||||
passwordHistory: [
|
passwordHistory: [
|
||||||
{
|
{
|
||||||
value: 'oldpass2',
|
value: 'oldpass1',
|
||||||
time: 1553394449,
|
time: 1553394449,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'oldpass1',
|
value: 'oldpass2',
|
||||||
time: 1553394457,
|
time: 1553394457,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: 'oldpass3',
|
||||||
|
time: 1553394458,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'oldpass4',
|
||||||
|
time: 1553394459,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'oldpass5',
|
||||||
|
time: 1553394460,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'oldpass6',
|
||||||
|
time: 1553394461,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
|
@ -481,18 +497,26 @@ describe('1Password 1Pif Importer', () => {
|
||||||
expect(ph.lastUsedDate.toISOString()).toEqual('2015-11-17T20:17:01.000Z');
|
expect(ph.lastUsedDate.toISOString()).toEqual('2015-11-17T20:17:01.000Z');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create password history from windows 1pif format', async () => {
|
it('should create password history from windows opvault 1pif format', async () => {
|
||||||
const importer = new Importer();
|
const importer = new Importer();
|
||||||
const result = importer.parse(WindowsTestData);
|
const result = importer.parse(WindowsOpVaultTestData);
|
||||||
const cipher = result.ciphers.shift();
|
const cipher = result.ciphers.shift();
|
||||||
|
|
||||||
expect(cipher.passwordHistory.length).toEqual(2);
|
expect(cipher.passwordHistory.length).toEqual(5);
|
||||||
let ph = cipher.passwordHistory.shift();
|
let ph = cipher.passwordHistory.shift();
|
||||||
expect(ph.password).toEqual('oldpass2');
|
expect(ph.password).toEqual('oldpass6');
|
||||||
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:29.000Z');
|
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:41.000Z');
|
||||||
|
|
||||||
ph = cipher.passwordHistory.shift();
|
ph = cipher.passwordHistory.shift();
|
||||||
expect(ph.password).toEqual('oldpass1');
|
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');
|
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:37.000Z');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -79,21 +79,11 @@ export class OnePassword1PifImporter extends BaseImporter implements Importer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (item.details.passwordHistory != null) {
|
if (item.details.passwordHistory != null) {
|
||||||
this.processPasswordHistory(item.details.passwordHistory, cipher);
|
this.parsePasswordHistory(item.details.passwordHistory, cipher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private processPasswordHistory(items: any[], cipher: CipherView) {
|
|
||||||
cipher.passwordHistory = cipher.passwordHistory || [];
|
|
||||||
items.forEach((entry: any) => {
|
|
||||||
const phv = new PasswordHistoryView();
|
|
||||||
phv.password = entry.value;
|
|
||||||
phv.lastUsedDate = new Date(entry.time * 1000);
|
|
||||||
cipher.passwordHistory.push(phv);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private processStandardItem(item: any, cipher: CipherView) {
|
private processStandardItem(item: any, cipher: CipherView) {
|
||||||
cipher.favorite = item.openContents && item.openContents.faveIndex ? true : false;
|
cipher.favorite = item.openContents && item.openContents.faveIndex ? true : false;
|
||||||
cipher.name = this.getValueOrDefault(item.title);
|
cipher.name = this.getValueOrDefault(item.title);
|
||||||
|
@ -143,11 +133,21 @@ export class OnePassword1PifImporter extends BaseImporter implements Importer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (item.secureContents.passwordHistory != null) {
|
if (item.secureContents.passwordHistory != null) {
|
||||||
this.processPasswordHistory(item.secureContents.passwordHistory, cipher);
|
this.parsePasswordHistory(item.secureContents.passwordHistory, cipher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private parsePasswordHistory(items: any[], cipher: CipherView) {
|
||||||
|
const maxSize = items.length > 5 ? 5 : items.length;
|
||||||
|
cipher.passwordHistory = items.sort((a, b) => b.time - a.time).slice(0, maxSize).map((entry: any) => {
|
||||||
|
const ph = new PasswordHistoryView();
|
||||||
|
ph.password = entry.value;
|
||||||
|
ph.lastUsedDate = new Date(entry.time * 1000);
|
||||||
|
return ph;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private parseFields(fields: any[], cipher: CipherView, designationKey: string, valueKey: string, nameKey: string) {
|
private parseFields(fields: any[], cipher: CipherView, designationKey: string, valueKey: string, nameKey: string) {
|
||||||
fields.forEach((field: any) => {
|
fields.forEach((field: any) => {
|
||||||
if (field[valueKey] == null || field[valueKey].toString().trim() === '') {
|
if (field[valueKey] == null || field[valueKey].toString().trim() === '') {
|
||||||
|
|
Loading…
Reference in New Issue