import { ApiService } from "../abstractions/api.service" ; import { CipherService } from "../abstractions/cipher.service" ; import { CollectionService } from "../abstractions/collection.service" ; import { CryptoService } from "../abstractions/crypto.service" ; import { FolderService } from "../abstractions/folder.service" ; import { I18nService } from "../abstractions/i18n.service" ; import { ImportOption , ImportService as ImportServiceAbstraction , } from "../abstractions/import.service" ; import { PlatformUtilsService } from "../abstractions/platformUtils.service" ; import { ImportResult } from "../models/domain/importResult" ; import { CipherType } from "../enums/cipherType" ; import { Utils } from "../misc/utils" ; import { CipherRequest } from "../models/request/cipherRequest" ; import { CollectionRequest } from "../models/request/collectionRequest" ; import { FolderRequest } from "../models/request/folderRequest" ; import { ImportCiphersRequest } from "../models/request/importCiphersRequest" ; import { ImportOrganizationCiphersRequest } from "../models/request/importOrganizationCiphersRequest" ; import { KvpRequest } from "../models/request/kvpRequest" ; import { ErrorResponse } from "../models/response/errorResponse" ; import { CipherView } from "../models/view/cipherView" ; import { AscendoCsvImporter } from "../importers/ascendoCsvImporter" ; import { AvastCsvImporter } from "../importers/avastCsvImporter" ; import { AvastJsonImporter } from "../importers/avastJsonImporter" ; import { AviraCsvImporter } from "../importers/aviraCsvImporter" ; import { BitwardenCsvImporter } from "../importers/bitwardenCsvImporter" ; import { BitwardenJsonImporter } from "../importers/bitwardenJsonImporter" ; import { BlackBerryCsvImporter } from "../importers/blackBerryCsvImporter" ; import { BlurCsvImporter } from "../importers/blurCsvImporter" ; import { ButtercupCsvImporter } from "../importers/buttercupCsvImporter" ; import { ChromeCsvImporter } from "../importers/chromeCsvImporter" ; import { ClipperzHtmlImporter } from "../importers/clipperzHtmlImporter" ; import { CodebookCsvImporter } from "../importers/codebookCsvImporter" ; import { DashlaneJsonImporter } from "../importers/dashlaneJsonImporter" ; import { EncryptrCsvImporter } from "../importers/encryptrCsvImporter" ; import { EnpassCsvImporter } from "../importers/enpassCsvImporter" ; import { EnpassJsonImporter } from "../importers/enpassJsonImporter" ; import { FirefoxCsvImporter } from "../importers/firefoxCsvImporter" ; import { FSecureFskImporter } from "../importers/fsecureFskImporter" ; import { GnomeJsonImporter } from "../importers/gnomeJsonImporter" ; import { Importer } from "../importers/importer" ; import { KasperskyTxtImporter } from "../importers/kasperskyTxtImporter" ; import { KeePass2XmlImporter } from "../importers/keepass2XmlImporter" ; import { KeePassXCsvImporter } from "../importers/keepassxCsvImporter" ; import { KeeperCsvImporter } from "../importers/keeperCsvImporter" ; import { LastPassCsvImporter } from "../importers/lastpassCsvImporter" ; import { LogMeOnceCsvImporter } from "../importers/logMeOnceCsvImporter" ; import { MeldiumCsvImporter } from "../importers/meldiumCsvImporter" ; import { MSecureCsvImporter } from "../importers/msecureCsvImporter" ; import { MykiCsvImporter } from "../importers/mykiCsvImporter" ; import { NordPassCsvImporter } from "../importers/nordpassCsvImporter" ; import { OnePassword1PifImporter } from "../importers/onepasswordImporters/onepassword1PifImporter" ; import { OnePasswordMacCsvImporter } from "../importers/onepasswordImporters/onepasswordMacCsvImporter" ; import { OnePasswordWinCsvImporter } from "../importers/onepasswordImporters/onepasswordWinCsvImporter" ; import { PadlockCsvImporter } from "../importers/padlockCsvImporter" ; import { PassKeepCsvImporter } from "../importers/passkeepCsvImporter" ; import { PassmanJsonImporter } from "../importers/passmanJsonImporter" ; import { PasspackCsvImporter } from "../importers/passpackCsvImporter" ; import { PasswordAgentCsvImporter } from "../importers/passwordAgentCsvImporter" ; import { PasswordBossJsonImporter } from "../importers/passwordBossJsonImporter" ; import { PasswordDragonXmlImporter } from "../importers/passwordDragonXmlImporter" ; import { PasswordSafeXmlImporter } from "../importers/passwordSafeXmlImporter" ; import { PasswordWalletTxtImporter } from "../importers/passwordWalletTxtImporter" ; import { RememBearCsvImporter } from "../importers/rememBearCsvImporter" ; import { RoboFormCsvImporter } from "../importers/roboformCsvImporter" ; import { SafariCsvImporter } from "../importers/safariCsvImporter" ; import { SafeInCloudXmlImporter } from "../importers/safeInCloudXmlImporter" ; import { SaferPassCsvImporter } from "../importers/saferpassCsvImport" ; import { SecureSafeCsvImporter } from "../importers/secureSafeCsvImporter" ; import { SplashIdCsvImporter } from "../importers/splashIdCsvImporter" ; import { StickyPasswordXmlImporter } from "../importers/stickyPasswordXmlImporter" ; import { TrueKeyCsvImporter } from "../importers/truekeyCsvImporter" ; import { UpmCsvImporter } from "../importers/upmCsvImporter" ; import { YotiCsvImporter } from "../importers/yotiCsvImporter" ; import { ZohoVaultCsvImporter } from "../importers/zohoVaultCsvImporter" ; export class ImportService implements ImportServiceAbstraction { featuredImportOptions = [ { id : "bitwardenjson" , name : "Bitwarden (json)" } , { id : "bitwardencsv" , name : "Bitwarden (csv)" } , { id : "chromecsv" , name : "Chrome (csv)" } , { id : "dashlanejson" , name : "Dashlane (json)" } , { id : "firefoxcsv" , name : "Firefox (csv)" } , { id : "keepass2xml" , name : "KeePass 2 (xml)" } , { id : "lastpasscsv" , name : "LastPass (csv)" } , { id : "safaricsv" , name : "Safari and macOS (csv)" } , { id : "1password1pif" , name : "1Password (1pif)" } , ] ; regularImportOptions : ImportOption [ ] = [ { id : "keepassxcsv" , name : "KeePassX (csv)" } , { id : "1passwordwincsv" , name : "1Password 6 and 7 Windows (csv)" } , { id : "1passwordmaccsv" , name : "1Password 6 and 7 Mac (csv)" } , { id : "roboformcsv" , name : "RoboForm (csv)" } , { id : "keepercsv" , name : "Keeper (csv)" } , { id : "enpasscsv" , name : "Enpass (csv)" } , { id : "enpassjson" , name : "Enpass (json)" } , { id : "safeincloudxml" , name : "SafeInCloud (xml)" } , { id : "pwsafexml" , name : "Password Safe (xml)" } , { id : "stickypasswordxml" , name : "Sticky Password (xml)" } , { id : "msecurecsv" , name : "mSecure (csv)" } , { id : "truekeycsv" , name : "True Key (csv)" } , { id : "passwordbossjson" , name : "Password Boss (json)" } , { id : "zohovaultcsv" , name : "Zoho Vault (csv)" } , { id : "splashidcsv" , name : "SplashID (csv)" } , { id : "passworddragonxml" , name : "Password Dragon (xml)" } , { id : "padlockcsv" , name : "Padlock (csv)" } , { id : "passboltcsv" , name : "Passbolt (csv)" } , { id : "clipperzhtml" , name : "Clipperz (html)" } , { id : "aviracsv" , name : "Avira (csv)" } , { id : "saferpasscsv" , name : "SaferPass (csv)" } , { id : "upmcsv" , name : "Universal Password Manager (csv)" } , { id : "ascendocsv" , name : "Ascendo DataVault (csv)" } , { id : "meldiumcsv" , name : "Meldium (csv)" } , { id : "passkeepcsv" , name : "PassKeep (csv)" } , { id : "operacsv" , name : "Opera (csv)" } , { id : "vivaldicsv" , name : "Vivaldi (csv)" } , { id : "gnomejson" , name : "GNOME Passwords and Keys/Seahorse (json)" } , { id : "blurcsv" , name : "Blur (csv)" } , { id : "passwordagentcsv" , name : "Password Agent (csv)" } , { id : "passpackcsv" , name : "Passpack (csv)" } , { id : "passmanjson" , name : "Passman (json)" } , { id : "avastcsv" , name : "Avast Passwords (csv)" } , { id : "avastjson" , name : "Avast Passwords (json)" } , { id : "fsecurefsk" , name : "F-Secure KEY (fsk)" } , { id : "kasperskytxt" , name : "Kaspersky Password Manager (txt)" } , { id : "remembearcsv" , name : "RememBear (csv)" } , { id : "passwordwallettxt" , name : "PasswordWallet (txt)" } , { id : "mykicsv" , name : "Myki (csv)" } , { id : "securesafecsv" , name : "SecureSafe (csv)" } , { id : "logmeoncecsv" , name : "LogMeOnce (csv)" } , { id : "blackberrycsv" , name : "BlackBerry Password Keeper (csv)" } , { id : "buttercupcsv" , name : "Buttercup (csv)" } , { id : "codebookcsv" , name : "Codebook (csv)" } , { id : "encryptrcsv" , name : "Encryptr (csv)" } , { id : "yoticsv" , name : "Yoti (csv)" } , { id : "nordpasscsv" , name : "Nordpass (csv)" } , ] ; constructor ( private cipherService , private folderService , private apiService , private i18nService , private collectionService , private platformUtilsService , private cryptoService ) { } getImportOptions ( ) { return this . featuredImportOptions . concat ( this . regularImportOptions ) ; } async import ( importer , fileContents , organizationId = null ) { const importResult = await importer . parse ( fileContents ) ; if ( importResult . success ) { if ( importResult . folders . length === 0 && importResult . ciphers . length === 0 ) { return new Error ( this . i18nService . t ( "importNothingError" ) ) ; } 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 ] ) ) { return new Error ( this . i18nService . t ( "importFormatError" ) ) ; } } try { await this . postImport ( importResult , organizationId ) ; } catch ( error ) { const errorResponse = new ErrorResponse ( error , 400 ) ; return this . handleServerError ( errorResponse , importResult ) ; } return null ; } else { if ( ! Utils . isNullOrWhitespace ( importResult . errorMessage ) ) { return new Error ( importResult . errorMessage ) ; } else { return new Error ( this . i18nService . t ( "importFormatError" ) ) ; } } } getImporter ( format , organizationId = null ) { const importer = this . getImporterInstance ( format ) ; if ( importer == null ) { return null ; } importer . organizationId = organizationId ; return importer ; } private getImporterInstance ( format ) { if ( format == null || format === "" ) { return null ; } switch ( format ) { case "bitwardencsv" : return new BitwardenCsvImporter ( ) ; case "bitwardenjson" : return new BitwardenJsonImporter ( this . cryptoService , this . i18nService ) ; case "lastpasscsv" : case "passboltcsv" : return new LastPassCsvImporter ( ) ; case "keepassxcsv" : return new KeePassXCsvImporter ( ) ; case "aviracsv" : return new AviraCsvImporter ( ) ; case "blurcsv" : return new BlurCsvImporter ( ) ; case "safeincloudxml" : return new SafeInCloudXmlImporter ( ) ; case "padlockcsv" : return new PadlockCsvImporter ( ) ; case "keepass2xml" : return new KeePass2XmlImporter ( ) ; case "chromecsv" : case "operacsv" : case "vivaldicsv" : return new ChromeCsvImporter ( ) ; case "firefoxcsv" : return new FirefoxCsvImporter ( ) ; case "upmcsv" : return new UpmCsvImporter ( ) ; case "saferpasscsv" : return new SaferPassCsvImporter ( ) ; case "safaricsv" : return new SafariCsvImporter ( ) ; case "meldiumcsv" : return new MeldiumCsvImporter ( ) ; case "1password1pif" : return new OnePassword1PifImporter ( ) ; case "1passwordwincsv" : return new OnePasswordWinCsvImporter ( ) ; case "1passwordmaccsv" : return new OnePasswordMacCsvImporter ( ) ; case "keepercsv" : return new KeeperCsvImporter ( ) ; case "passworddragonxml" : return new PasswordDragonXmlImporter ( ) ; case "enpasscsv" : return new EnpassCsvImporter ( ) ; case "enpassjson" : return new EnpassJsonImporter ( ) ; case "pwsafexml" : return new PasswordSafeXmlImporter ( ) ; case "dashlanejson" : return new DashlaneJsonImporter ( ) ; case "msecurecsv" : return new MSecureCsvImporter ( ) ; case "stickypasswordxml" : return new StickyPasswordXmlImporter ( ) ; case "truekeycsv" : return new TrueKeyCsvImporter ( ) ; case "clipperzhtml" : return new ClipperzHtmlImporter ( ) ; case "roboformcsv" : return new RoboFormCsvImporter ( ) ; case "ascendocsv" : return new AscendoCsvImporter ( ) ; case "passwordbossjson" : return new PasswordBossJsonImporter ( ) ; case "zohovaultcsv" : return new ZohoVaultCsvImporter ( ) ; case "splashidcsv" : return new SplashIdCsvImporter ( ) ; case "passkeepcsv" : return new PassKeepCsvImporter ( ) ; case "gnomejson" : return new GnomeJsonImporter ( ) ; case "passwordagentcsv" : return new PasswordAgentCsvImporter ( ) ; case "passpackcsv" : return new PasspackCsvImporter ( ) ; case "passmanjson" : return new PassmanJsonImporter ( ) ; case "avastcsv" : return new AvastCsvImporter ( ) ; case "avastjson" : return new AvastJsonImporter ( ) ; case "fsecurefsk" : return new FSecureFskImporter ( ) ; case "kasperskytxt" : return new KasperskyTxtImporter ( ) ; case "remembearcsv" : return new RememBearCsvImporter ( ) ; case "passwordwallettxt" : return new PasswordWalletTxtImporter ( ) ; case "mykicsv" : return new MykiCsvImporter ( ) ; case "securesafecsv" : return new SecureSafeCsvImporter ( ) ; case "logmeoncecsv" : return new LogMeOnceCsvImporter ( ) ; case "blackberrycsv" : return new BlackBerryCsvImporter ( ) ; case "buttercupcsv" : return new ButtercupCsvImporter ( ) ; case "codebookcsv" : return new CodebookCsvImporter ( ) ; case "encryptrcsv" : return new EncryptrCsvImporter ( ) ; case "yoticsv" : return new YotiCsvImporter ( ) ; case "nordpasscsv" : return new NordPassCsvImporter ( ) ; default : return null ; } } private async postImport ( importResult , organizationId = null ) { if ( organizationId == null ) { 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 ) ) ; } if ( importResult . folders != null ) { for ( let i = 0 ; i < importResult . folders . length ; i ++ ) { const f = await this . folderService . encrypt ( importResult . folders [ i ] ) ; request . folders . push ( new FolderRequest ( f ) ) ; } } if ( importResult . folderRelationships != null ) { importResult . folderRelationships . forEach ( ( r ) => request . folderRelationships . push ( new KvpRequest ( r [ 0 ] , r [ 1 ] ) ) ) ; } return await this . apiService . postImportCiphers ( request ) ; } else { const request = new ImportOrganizationCiphersRequest ( ) ; for ( let i = 0 ; i < importResult . ciphers . length ; i ++ ) { importResult . ciphers [ i ] . organizationId = organizationId ; const c = await this . cipherService . encrypt ( importResult . ciphers [ i ] ) ; request . ciphers . push ( new CipherRequest ( c ) ) ; } if ( importResult . collections != null ) { for ( let i = 0 ; i < importResult . collections . length ; i ++ ) { importResult . collections [ i ] . organizationId = organizationId ; const c = await this . collectionService . encrypt ( importResult . collections [ i ] ) ; request . collections . push ( new CollectionRequest ( c ) ) ; } } if ( importResult . collectionRelationships != null ) { importResult . collectionRelationships . forEach ( ( r ) => request . collectionRelationships . push ( new KvpRequest ( r [ 0 ] , r [ 1 ] ) ) ) ; } return await this . apiService . postImportOrganizationCiphers ( organizationId , request ) ; } } private badData ( c ) { return ( ( c . name == null || c . name === "--" ) && c . type === CipherType . Login && c . login != null && Utils . isNullOrWhitespace ( c . login . password ) ) ; } private handleServerError ( errorResponse , importResult ) { if ( errorResponse . validationErrors == null ) { return new Error ( errorResponse . message ) ; } let errorMessage = "" ; Object . entries ( errorResponse . validationErrors ) . forEach ( ( [ key , value ] , index ) => { let item ; let itemType ; const i = Number ( key . match ( /[0-9]+/ ) [ 0 ] ) ; switch ( key . match ( /^\w+/ ) [ 0 ] ) { case "Ciphers" : item = importResult . ciphers [ i ] ; itemType = CipherType [ item . type ] ; break ; case "Folders" : item = importResult . folders [ i ] ; itemType = "Folder" ; break ; case "Collections" : item = importResult . collections [ i ] ; itemType = "Collection" ; break ; default : return ; } if ( index > 0 ) { errorMessage += "\n\n" ; } if ( itemType !== "Folder" && itemType !== "Collection" ) { errorMessage += "[" + ( i + 1 ) + "] " ; } errorMessage += "[" + itemType + '] "' + item . name + '": ' + value ; } ) ; return new Error ( errorMessage ) ; } }