SEARCH-154 & SEARCH-116

1. Getting the key and the userId from the client app
2. Creating a encrypted file as soon as the batch indexes are merged
3. Deleting the data folder when the quits
4. Few changes in the encryption and decryption
This commit is contained in:
Keerthi Niranjan 2017-08-28 12:13:58 +05:30 committed by Keerthi Niranjan
parent 8d73e930ed
commit c8b45e091e
4 changed files with 74 additions and 76 deletions

View File

@ -99,7 +99,7 @@
</div> </div>
<script> <script>
var search = new ssf.Search("user_data"); var search = new ssf.Search("7078106230763", "7078106230763");
var buttonEl = document.getElementById('search'); var buttonEl = document.getElementById('search');
var merge = document.getElementById('merge'); var merge = document.getElementById('merge');
var buttonIndex = document.getElementById('index'); var buttonIndex = document.getElementById('index');
@ -193,8 +193,11 @@
}); });
merge.addEventListener('click', function () { merge.addEventListener('click', function () {
search.mergeIndexBatches(); search.mergeIndexBatches().then(function () {
resultsEl.innerHTML = 'Merged'; search.encryptIndex();
}).catch(function (err) {
resultsEl.innerHTML = 'Error: ' + err;
});
}); });
timestamp.addEventListener('click', function () { timestamp.addEventListener('click', function () {

View File

@ -4,30 +4,26 @@ const app = electron.app;
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const archiver = require('archiver'); const archiver = require('archiver');
const zipArchive = archiver('zip');
const extract = require('extract-zip'); const extract = require('extract-zip');
const isDevEnv = require('../utils/misc.js').isDevEnv; const isDevEnv = require('../utils/misc.js').isDevEnv;
const crypto = require('./crypto'); const crypto = require('./crypto');
const userData = path.join(app.getPath('userData')); const userData = path.join(app.getPath('userData'));
const DATA_FOLDER = isDevEnv ? './data' : path.join(userData, 'data');
const INDEX_DATA_FOLDER = isDevEnv ? './data/search_index' : path.join(userData, 'data/search_index'); const INDEX_DATA_FOLDER = isDevEnv ? './data/search_index' : path.join(userData, 'data/search_index');
const TEMPORARY_PATH = isDevEnv ? path.join(__dirname, '..', '..') : userData; const TEMPORARY_PATH = isDevEnv ? path.join(__dirname, '..', '..') : userData;
class Crypto { class Crypto {
// TODO: Need to pass key for encryption and decryption constructor(userId, key) {
constructor() {
// will be handling after implementing in client app
let userId = 'user_data';
let INDEX_VERSION = 'v1'; let INDEX_VERSION = 'v1';
// will be handling after implementing in client app
this.indexDataFolder = INDEX_DATA_FOLDER + '_' + userId + '_' + INDEX_VERSION; this.indexDataFolder = INDEX_DATA_FOLDER + '_' + userId + '_' + INDEX_VERSION;
this.permanentIndexFolderName = 'search_index_' + userId + '_' + INDEX_VERSION; this.permanentIndexFolderName = 'search_index_' + userId + '_' + INDEX_VERSION;
this.dump = TEMPORARY_PATH; this.dump = TEMPORARY_PATH;
this.key = key;
this.extractToPath = `${TEMPORARY_PATH}/data/${this.permanentIndexFolderName}`; this.extractToPath = `${TEMPORARY_PATH}/data/${this.permanentIndexFolderName}`;
this.encryptedIndex = `${INDEX_DATA_FOLDER + '_' + userId + '_' + INDEX_VERSION}.enc`; this.encryptedIndex = `${TEMPORARY_PATH}/${this.permanentIndexFolderName}.enc`;
this.dataFolder = DATA_FOLDER;
this.zipErrored = false; this.zipErrored = false;
} }
@ -36,7 +32,7 @@ class Crypto {
* removing the data folder and the dump files * removing the data folder and the dump files
* @returns {Promise} * @returns {Promise}
*/ */
encryption(key) { encryption() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!fs.existsSync(this.indexDataFolder)){ if (!fs.existsSync(this.indexDataFolder)){
@ -45,6 +41,7 @@ class Crypto {
return; return;
} }
const zipArchive = archiver('zip');
let output = fs.createWriteStream(`${this.dump}/${this.permanentIndexFolderName}.zip`); let output = fs.createWriteStream(`${this.dump}/${this.permanentIndexFolderName}.zip`);
@ -59,23 +56,17 @@ class Crypto {
const input = fs.createReadStream(`${this.dump}/${this.permanentIndexFolderName}.zip`); const input = fs.createReadStream(`${this.dump}/${this.permanentIndexFolderName}.zip`);
const outputEncryption = fs.createWriteStream(this.encryptedIndex); const outputEncryption = fs.createWriteStream(this.encryptedIndex);
let config = { let config = {
key: key key: this.key
}; };
const encrypt = crypto.encrypt(config); const encrypt = crypto.encrypt(config);
input.pipe(encrypt).pipe(outputEncryption).on('finish', (err, res) => { input.pipe(encrypt).pipe(outputEncryption).on('finish', (err) => {
if (err) { if (err) {
reject(new Error(err)); reject(new Error(err));
} }
if (!this.zipErrored) { if (!this.zipErrored) {
fs.unlinkSync(`${this.dump}/${this.permanentIndexFolderName}.zip`); fs.unlinkSync(`${this.dump}/${this.permanentIndexFolderName}.zip`);
Crypto.deleteFolderRecursive(this.indexDataFolder) resolve('Success');
.then(function () {
resolve(res);
})
.catch(function (error) {
reject(new Error(error))
});
} }
}); });
}); });
@ -98,7 +89,7 @@ class Crypto {
* removing the .enc file and the dump files * removing the .enc file and the dump files
* @returns {Promise} * @returns {Promise}
*/ */
decryption(key) { decryption() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!fs.existsSync(this.encryptedIndex)){ if (!fs.existsSync(this.encryptedIndex)){
@ -110,7 +101,7 @@ class Crypto {
const input = fs.createReadStream(this.encryptedIndex); const input = fs.createReadStream(this.encryptedIndex);
const output = fs.createWriteStream(`${this.dump}/decrypted.zip`); const output = fs.createWriteStream(`${this.dump}/decrypted.zip`);
let config = { let config = {
key: key key: this.key
}; };
const decrypt = crypto.decrypt(config); const decrypt = crypto.decrypt(config);
@ -141,36 +132,37 @@ class Crypto {
reject(new Error(err)); reject(new Error(err));
} }
fs.unlink(`${this.dump}/decrypted.zip`, () => { fs.unlink(`${this.dump}/decrypted.zip`, () => {
fs.unlink(this.encryptedIndex, () => { resolve('success');
resolve('success');
})
}); });
}) })
} }
}); });
} }
/**
* Deleting the data index folder
* when the app is closed
*/
deleteFolders() {
Crypto.deleteFolderRecursive(this.dataFolder);
}
/** /**
* Removing all the folders and files inside the data folder * Removing all the folders and files inside the data folder
* @param {String} location * @param location
* @returns {Promise}
*/ */
static deleteFolderRecursive(location) { static deleteFolderRecursive(location) {
return new Promise((resolve, reject) => { if (fs.existsSync(location)) {
if (fs.existsSync(location)) { fs.readdirSync(location).forEach((file) => {
fs.readdirSync(location).forEach((file) => { let curPath = location + "/" + file;
let curPath = location + "/" + file; if (fs.lstatSync(curPath).isDirectory()) {
if (fs.lstatSync(curPath).isDirectory()) { Crypto.deleteFolderRecursive(curPath);
Crypto.deleteFolderRecursive(curPath); } else {
} else { fs.unlinkSync(curPath);
fs.unlinkSync(curPath); }
} });
}); fs.rmdirSync(location);
resolve(fs.rmdirSync(location)); }
} else {
reject('no file');
}
});
} }
} }

View File

@ -92,23 +92,8 @@ app.on('activate', function () {
app.on('will-quit', function (e) { app.on('will-quit', function (e) {
e.preventDefault(); e.preventDefault();
crypto.deleteFolders();
/** app.exit();
* This is for demo purpose only
* will be removing this after implementing
* in client-app
*/
// Will be handling this in SEARCH-206
let key = "XrwVgWR4czB1a9scwvgRUNbXiN3W0oWq7oUBenyq7bo="; // temporary only
crypto.encryption(key)
.then(function () {
// will be handling after implementing in client app
app.exit();
})
.catch(function () {
// will be handling after implementing client app
app.exit();
});
}); });
// adds 'symphony' as a protocol // adds 'symphony' as a protocol

View File

@ -13,8 +13,7 @@ const isMac = require('../utils/misc.js').isMac;
const libSymphonySearch = require('./searchLibrary'); const libSymphonySearch = require('./searchLibrary');
// Crypto Library // Crypto Library
const Cryotp = require('../cryptoLib'); const Crypto = require('../cryptoLib');
const crypto = new Cryotp();
// Path for the exec file and the user data folder // Path for the exec file and the user data folder
const userData = path.join(app.getPath('userData')); const userData = path.join(app.getPath('userData'));
@ -23,9 +22,12 @@ const execPath = path.dirname(app.getPath('exe'));
// Constants paths for temp indexing folders // Constants paths for temp indexing folders
const TEMP_BATCH_INDEX_FOLDER = isDevEnv ? './data/temp_batch_indexes' : path.join(userData, 'data/temp_batch_indexes'); const TEMP_BATCH_INDEX_FOLDER = isDevEnv ? './data/temp_batch_indexes' : path.join(userData, 'data/temp_batch_indexes');
const TEMP_REAL_TIME_INDEX = isDevEnv ? './data/temp_realtime_index' : path.join(userData, 'data/temp_realtime_index'); const TEMP_REAL_TIME_INDEX = isDevEnv ? './data/temp_realtime_index' : path.join(userData, 'data/temp_realtime_index');
// Main User Index path
const INDEX_PREFIX = isDevEnv ? './data/search_index' : path.join(userData, 'data/search_index'); const INDEX_PREFIX = isDevEnv ? './data/search_index' : path.join(userData, 'data/search_index');
// Folder contains real time, batch and user index
const INDEX_DATA_FOLDER = isDevEnv ? './data' : path.join(userData, 'data'); const INDEX_DATA_FOLDER = isDevEnv ? './data' : path.join(userData, 'data');
const SEARCH_PERIOD_SUBTRACTOR = 3 * 31 * 24 * 60 * 60 * 1000;//3 months //3 Months
const SEARCH_PERIOD_SUBTRACTOR = 3 * 31 * 24 * 60 * 60 * 1000;
const MINIMUM_DATE = '0000000000000'; const MINIMUM_DATE = '0000000000000';
const MAXIMUM_DATE = '9999999999999'; const MAXIMUM_DATE = '9999999999999';
const INDEX_VERSION = 'v1'; const INDEX_VERSION = 'v1';
@ -49,23 +51,23 @@ class Search {
/** /**
* Constructor for the SymphonySearchEngine library * Constructor for the SymphonySearchEngine library
* @param userId (for the index folder name) * @param userId (for the index folder name)
* @param key
*/ */
constructor(userId) { constructor(userId, key) {
this.isInitialized = false; this.isInitialized = false;
this.userId = 'user_data'; this.userId = userId;
// Will be handling this in SEARCH-206 this.key = key;
this.key = "XrwVgWR4czB1a9scwvgRUNbXiN3W0oWq7oUBenyq7bo="; // temporary only this.indexFolderName = INDEX_PREFIX + '_' + this.userId + '_' + INDEX_VERSION;
this.startIndexingFromDate = (new Date().getTime() - SEARCH_PERIOD_SUBTRACTOR).toString();
this.indexFolderName = INDEX_PREFIX + '_' + userId + '_' + INDEX_VERSION;
this.dataFolder = INDEX_DATA_FOLDER; this.dataFolder = INDEX_DATA_FOLDER;
this.realTimeIndex = TEMP_REAL_TIME_INDEX; this.realTimeIndex = TEMP_REAL_TIME_INDEX;
this.batchIndex = TEMP_BATCH_INDEX_FOLDER; this.batchIndex = TEMP_BATCH_INDEX_FOLDER;
this.messageData = []; this.messageData = [];
this.crypto = new Crypto(userId, key);
this.decryptAndInit(); this.decryptAndInit();
} }
decryptAndInit() { decryptAndInit() {
crypto.decryption(this.key).then(() => { this.crypto.decryption().then(() => {
this.init(); this.init();
}).catch(() => { }).catch(() => {
this.init(); this.init();
@ -93,6 +95,7 @@ class Search {
Search.indexValidator(this.indexFolderName); Search.indexValidator(this.indexFolderName);
Search.indexValidator(this.realTimeIndex); Search.indexValidator(this.realTimeIndex);
let indexDateStartFrom = new Date().getTime() - SEARCH_PERIOD_SUBTRACTOR; let indexDateStartFrom = new Date().getTime() - SEARCH_PERIOD_SUBTRACTOR;
// Deleting all the messages except 3 Months from now
libSymphonySearch.symSEDeleteMessages(this.indexFolderName, null, libSymphonySearch.symSEDeleteMessages(this.indexFolderName, null,
MINIMUM_DATE, indexDateStartFrom.toString()); MINIMUM_DATE, indexDateStartFrom.toString());
this.isInitialized = true; this.isInitialized = true;
@ -131,11 +134,14 @@ class Search {
* created from indexBatch() * created from indexBatch()
*/ */
mergeIndexBatches() { mergeIndexBatches() {
libSymphonySearch.symSEMergePartialIndexAsync(this.indexFolderName, this.batchIndex, (err) => { return new Promise((resolve, reject) => {
if (err) { libSymphonySearch.symSEMergePartialIndexAsync(this.indexFolderName, this.batchIndex, (err, res) => {
throw new Error(err); if (err) {
} reject(new Error(err));
libSymphonySearch.symSERemoveFolder(this.batchIndex) }
libSymphonySearch.symSERemoveFolder(this.batchIndex);
resolve(res);
});
}); });
} }
@ -186,6 +192,18 @@ class Search {
}); });
} }
/**
* Encrypting the index after the merging the index
* to the main user index
*/
encryptIndex() {
this.crypto.encryption().then(() => {
return 'Success'
}).catch((e) => {
throw new Error(e)
});
}
/** /**
* This returns the search results * This returns the search results
* which returns a char * * which returns a char *