importer organization support

This commit is contained in:
Kyle Spearrin 2018-07-05 17:29:35 -04:00
parent 91081d9232
commit 56cf068acd
5 changed files with 85 additions and 42 deletions

View File

@ -1,5 +1,8 @@
import * as papa from 'papaparse'; import * as papa from 'papaparse';
import { ImportResult } from '../models/domain/importResult';
import { CollectionView } from '../models/view/collectionView';
import { LoginUriView } from '../models/view/loginUriView'; import { LoginUriView } from '../models/view/loginUriView';
import { Utils } from '../misc/utils'; import { Utils } from '../misc/utils';
@ -194,4 +197,15 @@ export abstract class BaseImporter {
return null; return null;
} }
protected moveFoldersToCollections(result: ImportResult) {
result.folderRelationships.forEach((value, key) => result.collectionRelationships.set(key, value));
result.collections = result.folders.map((f) => {
const collection = new CollectionView();
collection.name = f.name;
return collection;
});
result.folderRelationships = new Map<number, number>();
result.folders = [];
}
} }

View File

@ -4,6 +4,7 @@ import { Importer } from './importer';
import { ImportResult } from '../models/domain/importResult'; import { ImportResult } from '../models/domain/importResult';
import { CipherView } from '../models/view/cipherView'; import { CipherView } from '../models/view/cipherView';
import { CollectionView } from '../models/view/collectionView';
import { FieldView } from '../models/view/fieldView'; import { FieldView } from '../models/view/fieldView';
import { FolderView } from '../models/view/folderView'; import { FolderView } from '../models/view/folderView';
import { LoginView } from '../models/view/loginView'; import { LoginView } from '../models/view/loginView';
@ -14,7 +15,7 @@ import { FieldType } from '../enums/fieldType';
import { SecureNoteType } from '../enums/secureNoteType'; import { SecureNoteType } from '../enums/secureNoteType';
export class BitwardenCsvImporter extends BaseImporter implements Importer { export class BitwardenCsvImporter extends BaseImporter implements Importer {
parse(data: string): ImportResult { parse(data: string, organization = false): ImportResult {
const result = new ImportResult(); const result = new ImportResult();
const results = this.parseCsv(data, true); const results = this.parseCsv(data, true);
if (results == null) { if (results == null) {
@ -23,9 +24,31 @@ export class BitwardenCsvImporter extends BaseImporter implements Importer {
} }
results.forEach((value) => { results.forEach((value) => {
if (organization && !this.isNullOrWhitespace(value.collections)) {
const collections = (value.collections as string).split(',');
collections.forEach((col) => {
let addCollection = true;
let collectionIndex = result.collections.length;
for (let i = 0; i < result.collections.length; i++) {
if (result.collections[i].name === col) {
addCollection = false;
collectionIndex = i;
break;
}
}
if (addCollection) {
const collection = new CollectionView();
collection.name = col;
result.collections.push(collection);
}
result.collectionRelationships.set(result.ciphers.length, collectionIndex);
});
} else if (!organization) {
let folderIndex = result.folders.length; let folderIndex = result.folders.length;
const cipherIndex = result.ciphers.length; const hasFolder = !organization && !this.isNullOrWhitespace(value.folder);
const hasFolder = !this.isNullOrWhitespace(value.folder);
let addFolder = hasFolder; let addFolder = hasFolder;
if (hasFolder) { if (hasFolder) {
@ -38,9 +61,20 @@ export class BitwardenCsvImporter extends BaseImporter implements Importer {
} }
} }
if (addFolder) {
const f = new FolderView();
f.name = value.folder;
result.folders.push(f);
}
if (hasFolder) {
result.folderRelationships.set(result.ciphers.length, folderIndex);
}
}
const cipher = new CipherView(); const cipher = new CipherView();
cipher.favorite = !organization && this.getValueOrDefault(value.favorite, '0') !== '0' ? true : false;
cipher.type = CipherType.Login; cipher.type = CipherType.Login;
cipher.favorite = this.getValueOrDefault(value.favorite, '0') !== '0' ? true : false;
cipher.notes = this.getValueOrDefault(value.notes); cipher.notes = this.getValueOrDefault(value.notes);
cipher.name = this.getValueOrDefault(value.name, '--'); cipher.name = this.getValueOrDefault(value.name, '--');
@ -93,15 +127,6 @@ export class BitwardenCsvImporter extends BaseImporter implements Importer {
} }
result.ciphers.push(cipher); result.ciphers.push(cipher);
if (addFolder) {
const f = new FolderView();
f.name = value.folder;
result.folders.push(f);
}
if (hasFolder) {
result.folderRelationships.set(cipherIndex, folderIndex);
}
}); });
result.success = true; result.success = true;

View File

@ -1,5 +1,5 @@
import { ImportResult } from '../models/domain/importResult'; import { ImportResult } from '../models/domain/importResult';
export interface Importer { export interface Importer {
parse(data: string): ImportResult; parse(data: string, organization?: boolean): ImportResult;
} }

View File

@ -19,12 +19,15 @@ export class KeePassXCsvImporter extends BaseImporter implements Importer {
} }
results.forEach((value) => { results.forEach((value) => {
if (this.isNullOrWhitespace(value.Title)) {
return;
}
value.Group = !this.isNullOrWhitespace(value.Group) && value.Group.startsWith('Root/') ? value.Group = !this.isNullOrWhitespace(value.Group) && value.Group.startsWith('Root/') ?
value.Group.replace('Root/', '') : value.Group; value.Group.replace('Root/', '') : value.Group;
const groupName = !this.isNullOrWhitespace(value.Group) ? value.Group.split('/').join(' > ') : null; const groupName = !this.isNullOrWhitespace(value.Group) ? value.Group.split('/').join(' > ') : null;
let folderIndex = result.folders.length; let folderIndex = result.folders.length;
const cipherIndex = result.ciphers.length;
const hasFolder = groupName != null; const hasFolder = groupName != null;
let addFolder = hasFolder; let addFolder = hasFolder;
@ -38,6 +41,15 @@ export class KeePassXCsvImporter extends BaseImporter implements Importer {
} }
} }
if (addFolder) {
const f = new FolderView();
f.name = groupName;
result.folders.push(f);
}
if (hasFolder) {
result.folderRelationships.set(result.ciphers.length, folderIndex);
}
const cipher = new CipherView(); const cipher = new CipherView();
cipher.type = CipherType.Login; cipher.type = CipherType.Login;
cipher.favorite = false; cipher.favorite = false;
@ -47,19 +59,7 @@ export class KeePassXCsvImporter extends BaseImporter implements Importer {
cipher.login.username = this.getValueOrDefault(value.Username); cipher.login.username = this.getValueOrDefault(value.Username);
cipher.login.password = this.getValueOrDefault(value.Password); cipher.login.password = this.getValueOrDefault(value.Password);
cipher.login.uris = this.makeUriArray(value.URL); cipher.login.uris = this.makeUriArray(value.URL);
if (!this.isNullOrWhitespace(value.Title)) {
result.ciphers.push(cipher); result.ciphers.push(cipher);
}
if (addFolder) {
const f = new FolderView();
f.name = groupName;
result.folders.push(f);
}
if (hasFolder) {
result.folderRelationships.set(cipherIndex, folderIndex);
}
}); });
result.success = true; result.success = true;

View File

@ -14,7 +14,7 @@ import { CipherType } from '../enums/cipherType';
import { SecureNoteType } from '../enums/secureNoteType'; import { SecureNoteType } from '../enums/secureNoteType';
export class LastPassCsvImporter extends BaseImporter implements Importer { export class LastPassCsvImporter extends BaseImporter implements Importer {
parse(data: string): ImportResult { parse(data: string, organization = false): ImportResult {
const result = new ImportResult(); const result = new ImportResult();
const results = this.parseCsv(data, true); const results = this.parseCsv(data, true);
if (results == null) { if (results == null) {
@ -23,8 +23,8 @@ export class LastPassCsvImporter extends BaseImporter implements Importer {
} }
results.forEach((value, index) => { results.forEach((value, index) => {
let folderIndex = result.folders.length;
const cipherIndex = result.ciphers.length; const cipherIndex = result.ciphers.length;
let folderIndex = result.folders.length;
const hasFolder = this.getValueOrDefault(value.grouping, '(none)') !== '(none)'; const hasFolder = this.getValueOrDefault(value.grouping, '(none)') !== '(none)';
let addFolder = hasFolder; let addFolder = hasFolder;
@ -38,7 +38,7 @@ export class LastPassCsvImporter extends BaseImporter implements Importer {
} }
} }
const cipher = this.buildBaseCipher(value); const cipher = this.buildBaseCipher(value, organization);
if (cipher.name === '--' && results.length > 2 && index >= (results.length - 2)) { if (cipher.name === '--' && results.length > 2 && index >= (results.length - 2)) {
// LastPass file traditionally has two empty lines at the end // LastPass file traditionally has two empty lines at the end
return; return;
@ -60,7 +60,7 @@ export class LastPassCsvImporter extends BaseImporter implements Importer {
cipher.notes = this.getValueOrDefault(value.notes); cipher.notes = this.getValueOrDefault(value.notes);
if (!this.isNullOrWhitespace(value.ccnum)) { if (!this.isNullOrWhitespace(value.ccnum)) {
// there is a card on this identity too // there is a card on this identity too
const cardCipher = this.buildBaseCipher(value); const cardCipher = this.buildBaseCipher(value, organization);
cardCipher.identity = null; cardCipher.identity = null;
cardCipher.type = CipherType.Card; cardCipher.type = CipherType.Card;
cardCipher.card = this.parseCard(value); cardCipher.card = this.parseCard(value);
@ -80,11 +80,15 @@ export class LastPassCsvImporter extends BaseImporter implements Importer {
} }
}); });
if (organization) {
this.moveFoldersToCollections(result);
}
result.success = true; result.success = true;
return result; return result;
} }
private buildBaseCipher(value: any) { private buildBaseCipher(value: any, organization: boolean) {
const cipher = new CipherView(); const cipher = new CipherView();
if (value.hasOwnProperty('profilename') && value.hasOwnProperty('profilelanguage')) { if (value.hasOwnProperty('profilename') && value.hasOwnProperty('profilelanguage')) {
// form fill // form fill
@ -100,7 +104,7 @@ export class LastPassCsvImporter extends BaseImporter implements Importer {
} }
} else { } else {
// site or secure note // site or secure note
cipher.favorite = this.getValueOrDefault(value.fav, '0') === '1'; // TODO: if org, always false cipher.favorite = !organization && this.getValueOrDefault(value.fav, '0') === '1';
cipher.name = this.getValueOrDefault(value.name, '--'); cipher.name = this.getValueOrDefault(value.name, '--');
cipher.type = value.url === 'http://sn' ? CipherType.SecureNote : CipherType.Login; cipher.type = value.url === 'http://sn' ? CipherType.SecureNote : CipherType.Login;
} }