From c26a6a5252fd33473872c48e9e9796ab5aa4beea Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 25 Jun 2018 11:39:55 -0400 Subject: [PATCH] encrypt and post import to api --- jslib | 2 +- src/app/tools/import.component.ts | 60 +++++++++++++++++++++++++++---- src/locales/en/messages.json | 9 +++++ src/scss/styles.scss | 4 ++- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/jslib b/jslib index ce40a803d85..ca3b1c739c6 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit ce40a803d85f90b5078ecd4d7c374714c43940c8 +Subproject commit ca3b1c739c6a7ef503845a1485cc76643276a259 diff --git a/src/app/tools/import.component.ts b/src/app/tools/import.component.ts index ae0b01183af..d89bd293bde 100644 --- a/src/app/tools/import.component.ts +++ b/src/app/tools/import.component.ts @@ -1,16 +1,26 @@ import { Component, } from '@angular/core'; +import { Router } from '@angular/router'; import { ToasterService } from 'angular2-toaster'; import { Angulartics2 } from 'angulartics2'; +import { ApiService } from 'jslib/abstractions/api.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; +import { CipherRequest } from 'jslib/models/request/cipherRequest'; +import { FolderRequest } from 'jslib/models/request/folderRequest'; +import { ImportCiphersRequest } from 'jslib/models/request/importCiphersRequest'; +import { KvpRequest } from 'jslib/models/request/kvpRequest'; + import { BitwardenCsvImporter } from 'jslib/importers/bitwardenCsvImporter'; import { Importer } from 'jslib/importers/importer'; import { KeePassXCsvImporter } from 'jslib/importers/keepassxCsvImporter'; import { LastPassCsvImporter } from 'jslib/importers/lastpassCsvImporter'; +import { CipherView } from 'jslib/models/view'; @Component({ selector: 'app-import', @@ -22,11 +32,12 @@ export class ImportComponent { format: string = null; fileContents: string; - constructor(private i18nService: I18nService, protected analytics: Angulartics2, - protected toasterService: ToasterService) { - const bw = new BitwardenCsvImporter(); - const lp = new LastPassCsvImporter(); + formPromise: Promise; + constructor(private i18nService: I18nService, private analytics: Angulartics2, + private toasterService: ToasterService, private cipherService: CipherService, + private folderService: FolderService, private apiService: ApiService, + private router: Router) { this.featuredImportOptions = [ { id: null, name: '-- ' + i18nService.t('select') + ' --' }, { id: 'bitwardencsv', name: 'Bitwarden (csv)' }, @@ -113,11 +124,43 @@ export class ImportComponent { } const importResult = await importer.parse(fileContents); - console.log(importResult); if (importResult.success) { + if (importResult.folders.length === 0 && importResult.ciphers.length === 0) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('importNothingError')); + return; + } else if (importResult.ciphers.length > 0) { + const halfway = Math.floor(importResult.ciphers.length / 2); + const last = importResult.ciphers.length - 1; + if (this.badData(importResult.ciphers[0]) && this.badData(importResult.ciphers[halfway]) && + this.badData(importResult.ciphers[last])) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('importFormatError')); + return; + } + } + const request = new ImportCiphersRequest(); + for (let i = 0; i < importResult.ciphers.length; i++) { + const c = await this.cipherService.encrypt(importResult.ciphers[i]); + request.ciphers.push(new CipherRequest(c)); + } + for (let i = 0; i < importResult.folders.length; i++) { + const f = await this.folderService.encrypt(importResult.folders[i]); + request.folders.push(new FolderRequest(f)); + } + importResult.folderRelationships.forEach((v: number, k: number) => + request.folderRelationships.push(new KvpRequest(k, v))); + + try { + this.formPromise = this.apiService.postImportCiphers(request); + await this.formPromise; + this.toasterService.popAsync('success', null, this.i18nService.t('importSuccess')); + this.router.navigate(['vault']); + } catch { } } else { - + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('importFormatError')); } } @@ -162,4 +205,9 @@ export class ImportComponent { return null; } } + + private badData(c: CipherView) { + return (c.name == null || c.name === '--') && + (c.login != null && (c.login.password == null || c.login.password === '')); + } } diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index afb1872e655..9a3640efc27 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -866,6 +866,15 @@ "import": { "message": "Import" }, + "importSuccess": { + "message": "Data has been successfully imported into your vault." + }, + "importFormatError": { + "message": "Data is not formatted correctly. Please check your import file and try again." + }, + "importNothingError": { + "message": "Nothing was imported." + }, "selectFormat": { "message": "Select the format of the import file" }, diff --git a/src/scss/styles.scss b/src/scss/styles.scss index 65547486bef..15d8fcd0763 100644 --- a/src/scss/styles.scss +++ b/src/scss/styles.scss @@ -1,13 +1,15 @@ $primary: #3c8dbc; $primary-accent: #286090; $secondary: #ced4da; +$secondary-alt: #2c3e50; $success: #00a65a; $info: #555555; $warning: #bf7e16; $danger: #dd4b39; $theme-colors: ( - "primary-accent": $primary-accent + "primary-accent": $primary-accent, + "secondary-alt": $secondary-alt, ); $body-bg: #ffffff;