2017-08-10 04:00:04 -05:00
|
|
|
'use strict';
|
|
|
|
const electron = require('electron');
|
|
|
|
const app = electron.app;
|
|
|
|
const path = require('path');
|
2017-08-14 00:17:01 -05:00
|
|
|
const fs = require('fs');
|
|
|
|
const archiver = require('archiver');
|
|
|
|
const extract = require('extract-zip');
|
2017-08-10 04:00:04 -05:00
|
|
|
const isDevEnv = require('../utils/misc.js').isDevEnv;
|
2017-08-18 04:18:22 -05:00
|
|
|
const crypto = require('./crypto');
|
2017-08-10 04:00:04 -05:00
|
|
|
|
|
|
|
const userData = path.join(app.getPath('userData'));
|
2017-08-28 01:43:58 -05:00
|
|
|
const DATA_FOLDER = isDevEnv ? './data' : path.join(userData, 'data');
|
2017-08-18 06:58:30 -05:00
|
|
|
const INDEX_DATA_FOLDER = isDevEnv ? './data/search_index' : path.join(userData, 'data/search_index');
|
2017-08-18 04:18:22 -05:00
|
|
|
const TEMPORARY_PATH = isDevEnv ? path.join(__dirname, '..', '..') : userData;
|
2017-08-10 04:00:04 -05:00
|
|
|
|
|
|
|
class Crypto {
|
|
|
|
|
2017-08-28 01:43:58 -05:00
|
|
|
constructor(userId, key) {
|
2017-08-18 06:58:30 -05:00
|
|
|
let INDEX_VERSION = 'v1';
|
|
|
|
this.indexDataFolder = INDEX_DATA_FOLDER + '_' + userId + '_' + INDEX_VERSION;
|
2017-08-21 03:09:07 -05:00
|
|
|
this.permanentIndexFolderName = 'search_index_' + userId + '_' + INDEX_VERSION;
|
2017-08-18 04:18:22 -05:00
|
|
|
this.dump = TEMPORARY_PATH;
|
2017-08-28 01:43:58 -05:00
|
|
|
this.key = key;
|
2017-08-22 02:15:06 -05:00
|
|
|
this.extractToPath = `${TEMPORARY_PATH}/data/${this.permanentIndexFolderName}`;
|
2017-08-28 01:43:58 -05:00
|
|
|
this.encryptedIndex = `${TEMPORARY_PATH}/${this.permanentIndexFolderName}.enc`;
|
|
|
|
this.dataFolder = DATA_FOLDER;
|
2017-08-14 00:17:01 -05:00
|
|
|
this.zipErrored = false;
|
2017-08-10 04:00:04 -05:00
|
|
|
}
|
|
|
|
|
2017-08-18 04:18:22 -05:00
|
|
|
/**
|
|
|
|
* Creates a zip of the data folder and encrypting
|
|
|
|
* removing the data folder and the dump files
|
|
|
|
* @returns {Promise}
|
|
|
|
*/
|
2017-08-28 01:43:58 -05:00
|
|
|
encryption() {
|
2017-08-18 02:26:48 -05:00
|
|
|
return new Promise((resolve, reject) => {
|
2017-08-14 00:17:01 -05:00
|
|
|
|
2017-08-18 06:58:30 -05:00
|
|
|
if (!fs.existsSync(this.indexDataFolder)){
|
|
|
|
// will be handling after implementing in client app
|
|
|
|
reject();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-28 01:43:58 -05:00
|
|
|
const zipArchive = archiver('zip');
|
2017-08-21 03:09:07 -05:00
|
|
|
let output = fs.createWriteStream(`${this.dump}/${this.permanentIndexFolderName}.zip`);
|
2017-08-14 00:17:01 -05:00
|
|
|
|
2017-08-18 06:58:30 -05:00
|
|
|
|
|
|
|
zipArchive.on('end', () => {
|
|
|
|
|
2017-08-21 03:09:07 -05:00
|
|
|
if (!fs.existsSync(`${this.dump}/${this.permanentIndexFolderName}.zip`)){
|
2017-08-18 06:58:30 -05:00
|
|
|
// will be handling after implementing in client app
|
|
|
|
reject();
|
|
|
|
return;
|
|
|
|
}
|
2017-08-14 00:17:01 -05:00
|
|
|
|
2017-08-21 03:09:07 -05:00
|
|
|
const input = fs.createReadStream(`${this.dump}/${this.permanentIndexFolderName}.zip`);
|
2017-08-18 02:26:48 -05:00
|
|
|
const outputEncryption = fs.createWriteStream(this.encryptedIndex);
|
2017-08-18 04:18:22 -05:00
|
|
|
let config = {
|
2017-08-28 01:43:58 -05:00
|
|
|
key: this.key
|
2017-08-18 04:18:22 -05:00
|
|
|
};
|
|
|
|
const encrypt = crypto.encrypt(config);
|
2017-08-14 00:17:01 -05:00
|
|
|
|
2017-08-28 01:43:58 -05:00
|
|
|
input.pipe(encrypt).pipe(outputEncryption).on('finish', (err) => {
|
2017-08-14 00:17:01 -05:00
|
|
|
if (err) {
|
|
|
|
reject(new Error(err));
|
|
|
|
}
|
2017-08-18 02:26:48 -05:00
|
|
|
if (!this.zipErrored) {
|
2017-08-21 03:09:07 -05:00
|
|
|
fs.unlinkSync(`${this.dump}/${this.permanentIndexFolderName}.zip`);
|
2017-08-28 01:43:58 -05:00
|
|
|
resolve('Success');
|
2017-08-14 00:17:01 -05:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
zipArchive.pipe(output);
|
|
|
|
|
2017-08-22 02:15:06 -05:00
|
|
|
zipArchive.directory(this.indexDataFolder + '/', false);
|
2017-08-14 00:17:01 -05:00
|
|
|
|
2017-08-18 02:26:48 -05:00
|
|
|
zipArchive.finalize((err) => {
|
2017-08-14 00:17:01 -05:00
|
|
|
if (err) {
|
2017-08-18 02:26:48 -05:00
|
|
|
this.zipErrored = true;
|
2017-08-14 00:17:01 -05:00
|
|
|
reject(new Error(err));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2017-08-10 04:00:04 -05:00
|
|
|
}
|
|
|
|
|
2017-08-18 04:18:22 -05:00
|
|
|
/**
|
|
|
|
* Decrypting the .enc file and unzipping
|
|
|
|
* removing the .enc file and the dump files
|
|
|
|
* @returns {Promise}
|
|
|
|
*/
|
2017-08-28 01:43:58 -05:00
|
|
|
decryption() {
|
2017-08-18 02:26:48 -05:00
|
|
|
return new Promise((resolve, reject) => {
|
2017-08-18 06:58:30 -05:00
|
|
|
|
|
|
|
if (!fs.existsSync(this.encryptedIndex)){
|
|
|
|
// will be handling after implementing in client app
|
|
|
|
reject();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-18 02:26:48 -05:00
|
|
|
const input = fs.createReadStream(this.encryptedIndex);
|
|
|
|
const output = fs.createWriteStream(`${this.dump}/decrypted.zip`);
|
2017-08-18 04:18:22 -05:00
|
|
|
let config = {
|
2017-08-28 01:43:58 -05:00
|
|
|
key: this.key
|
2017-08-18 04:18:22 -05:00
|
|
|
};
|
|
|
|
const decrypt = crypto.decrypt(config);
|
2017-08-14 00:17:01 -05:00
|
|
|
|
2017-08-18 04:18:22 -05:00
|
|
|
input.pipe(decrypt).pipe(output).on('finish', () => {
|
2017-08-18 06:58:30 -05:00
|
|
|
|
|
|
|
if (!fs.existsSync(`${this.dump}/decrypted.zip`)){
|
|
|
|
// will be handling after implementing in client app
|
|
|
|
reject();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-18 02:26:48 -05:00
|
|
|
let readStream = fs.createReadStream(`${this.dump}/decrypted.zip`);
|
2017-08-14 00:17:01 -05:00
|
|
|
readStream
|
2017-08-18 02:26:48 -05:00
|
|
|
.on('data', (data) => {
|
|
|
|
if (!data) {
|
|
|
|
reject(new Error("error reading zip"));
|
|
|
|
}
|
2017-08-18 06:58:30 -05:00
|
|
|
extractZip();
|
2017-08-14 00:17:01 -05:00
|
|
|
})
|
2017-08-18 02:26:48 -05:00
|
|
|
.on('error', (error) => {
|
|
|
|
reject(new Error(error.message));
|
2017-08-14 00:17:01 -05:00
|
|
|
});
|
|
|
|
});
|
2017-08-18 02:26:48 -05:00
|
|
|
|
2017-08-18 06:58:30 -05:00
|
|
|
let extractZip = () => {
|
2017-08-22 02:15:06 -05:00
|
|
|
extract(`${this.dump}/decrypted.zip`, {dir: `${this.extractToPath}`}, (err) => {
|
2017-08-18 02:26:48 -05:00
|
|
|
if (err) {
|
|
|
|
reject(new Error(err));
|
|
|
|
}
|
|
|
|
fs.unlink(`${this.dump}/decrypted.zip`, () => {
|
2017-08-28 01:43:58 -05:00
|
|
|
resolve('success');
|
2017-08-18 02:26:48 -05:00
|
|
|
});
|
|
|
|
})
|
2017-08-18 04:18:22 -05:00
|
|
|
}
|
2017-08-14 00:17:01 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-08-28 01:43:58 -05:00
|
|
|
/**
|
|
|
|
* Deleting the data index folder
|
|
|
|
* when the app is closed
|
|
|
|
*/
|
|
|
|
deleteFolders() {
|
|
|
|
Crypto.deleteFolderRecursive(this.dataFolder);
|
|
|
|
}
|
|
|
|
|
2017-08-18 04:18:22 -05:00
|
|
|
/**
|
|
|
|
* Removing all the folders and files inside the data folder
|
2017-08-28 01:43:58 -05:00
|
|
|
* @param location
|
2017-08-18 04:18:22 -05:00
|
|
|
*/
|
|
|
|
static deleteFolderRecursive(location) {
|
2017-08-28 01:43:58 -05:00
|
|
|
if (fs.existsSync(location)) {
|
|
|
|
fs.readdirSync(location).forEach((file) => {
|
|
|
|
let curPath = location + "/" + file;
|
|
|
|
if (fs.lstatSync(curPath).isDirectory()) {
|
|
|
|
Crypto.deleteFolderRecursive(curPath);
|
|
|
|
} else {
|
|
|
|
fs.unlinkSync(curPath);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
fs.rmdirSync(location);
|
|
|
|
}
|
2017-08-10 04:00:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = Crypto;
|