UNPKG

firmament-vita

Version:

Firmament module for automating VITA tasks

122 lines (112 loc) 4.74 kB
import {injectable, inject} from 'inversify'; import {spawn} from 'child_process'; import {VitaDecryptUnTar} from "../interfaces/vita-decrypt-untar"; import {DecryptAndUnTarOptions, DecryptAndUnTarResult, DecryptAndUnTarStatus} from "../interfaces/vita-options-results"; import {ForceErrorImpl, CommandUtil} from "firmament-yargs"; import {VitaFileUtil} from "../interfaces/vita-file-util"; import {VitaSpawn} from "../interfaces/vita-spawn"; const fs = require('fs'); const path = require('path'); const async = require('async'); const mkdirp = require('mkdirp'); const through2Filter = require('through2-filter'); const _ = require('lodash'); @injectable() export class VitaDecryptUnTarImpl extends ForceErrorImpl implements VitaDecryptUnTar { constructor(@inject('VitaSpawn') private vitaSpawn: VitaSpawn, @inject('CommandUtil') private commandUtil: CommandUtil, @inject('VitaFileUtil') private vitaFileUtil: VitaFileUtil) { super(); } process(options: DecryptAndUnTarOptions, cbStatus: (err: Error, decryptAndUnTarStatus: DecryptAndUnTarStatus) => void, cbFinal: (err: Error, decryptAndUnTarResults: DecryptAndUnTarResult[]) => void) { cbFinal = this.checkCallback(cbFinal); cbStatus = this.checkCallback(cbStatus); let fnArray = []; options.targetFolder = options.targetFolder || null; options.encryptedFiles = options.encryptedFiles || []; options.encryptedFilePattern = options.encryptedFilePattern || /\.enc$/; options.foldersOfEncryptedFiles = options.foldersOfEncryptedFiles || []; options.encryptedFiles = this.vitaFileUtil.findFilesSync({ pattern: options.encryptedFilePattern, files: options.encryptedFiles, folders: options.foldersOfEncryptedFiles }); options.encryptedFiles.forEach(file => { fnArray.push(async.apply(this.spawnDecryptAndUnTarOperation.bind(this), file, options.password, options.targetFolder, (err: Error, decryptAndUnTarStatus: DecryptAndUnTarStatus) => { decryptAndUnTarStatus.decryptAndUnTarOptions = <DecryptAndUnTarOptions>_.omit(options, ['password', 'encryptedFilePattern']); cbStatus(err, decryptAndUnTarStatus); } )); }); async.parallelLimit(fnArray, 3, cbFinal); } private spawnDecryptAndUnTarOperation(inFile: string, password: string, targetFolder: string, cbStatus: (err: Error, decryptAndUnTarStatus: DecryptAndUnTarStatus) => void, cbFinal: (err: Error, decryptAndUnTarResult: DecryptAndUnTarResult) => void) { cbStatus = this.checkCallback(cbStatus); cbFinal = this.checkCallback(cbFinal); if (!targetFolder) { //Put decrypted file in same folder as encrypted file targetFolder = path.dirname(inFile); } mkdirp(targetFolder, err => { if (this.commandUtil.callbackIfError(cbFinal, err)) { return; } let inputFileSize = fs.statSync(inFile)['size']; let totalBytesStreamed = 0; let openSslProcessExited = false; let tarProcessExited = false; let tarArgs = [ 'x', '--strip-components=3', '-C', targetFolder ]; let tarProcess = spawn('tar', tarArgs); let openSslArgs = [ 'aes-256-cbc', '-d', '-in', inFile, '-k', password]; let openSslProcess = spawn('openssl', openSslArgs); tarProcess.on('close', (code: number, signal: string) => { tarProcessExited = true; if (openSslProcessExited) { this.callbackFromDecryptAndUnTarFiles(cbFinal, targetFolder); } }); openSslProcess.on('close', (code: number, signal: string) => { openSslProcessExited = true; if (tarProcessExited) { this.callbackFromDecryptAndUnTarFiles(cbFinal, targetFolder); } }); openSslProcess.stdout.pipe( through2Filter((dataChunk) => { totalBytesStreamed += dataChunk.length; let taskName = `Decrypting [${path.basename(inFile)}] `; let current = totalBytesStreamed; let total = inputFileSize; cbStatus(null, {taskName, current, total}); return true; })).pipe(tarProcess.stdin); }); } private callbackFromDecryptAndUnTarFiles(cb: (err: Error, decryptAndUnTarResult: DecryptAndUnTarResult) => void, folder: string) { this.vitaFileUtil.findFiles({pattern: /\.gz$/, folders: [folder]}, (err, files) => { cb(err, {exportDir: folder, zipFiles: files}); }); } }