mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-01-03 12:47:13 -06:00
Merge pull request #262 from keerthi16/SEARCH-539
SEARCH-539 & SEARCH-206 (Encryption-Key and Disk Space)
This commit is contained in:
commit
18182df07a
@ -87,6 +87,30 @@
|
||||
<div>
|
||||
<label for="batchNumber">Get Latest Message Timestamp</label>
|
||||
<button id='getLatestMessageTimestamp'>Click</button>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label>Check Free Space: </label>
|
||||
<button id='checkFreeSpace'>Click</button>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label>View User Config</label>
|
||||
<button id='viewUserConfig'>Click</button>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<div>
|
||||
<label>Update User Config</label>
|
||||
</div>
|
||||
<br>
|
||||
<label for="rotationId">Rotation Id: </label><input placeholder="Ex: 0, 1" id="rotationId">
|
||||
<br>
|
||||
<label for="version">Version: </label><input placeholder="Ex: 1, 2" id="version">
|
||||
<br>
|
||||
<button id='updateUserConfig'>Save</button>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p>Results:</p>
|
||||
<p id="results"></p>
|
||||
@ -103,7 +127,8 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var search = new ssf.Search("16149077034436", "RSDFOiuVqF3WmY1pC4MP145qPOpUP6A4if27WG9y3fY=");
|
||||
var search = new ssf.Search("12345678910112", "jjjehdnctsjyieoalskcjdhsnahsadndfnusdfsdfsd=");
|
||||
var searchUtils = new ssf.SearchUtils();
|
||||
var buttonEl = document.getElementById('search');
|
||||
var merge = document.getElementById('merge');
|
||||
var buttonIndex = document.getElementById('index');
|
||||
@ -122,6 +147,11 @@
|
||||
var batchNumber = document.getElementById('batchNumber');
|
||||
var timestamp = document.getElementById('getLatestMessageTimestamp');
|
||||
var has = document.getElementById('has');
|
||||
var checkFreeSpace = document.getElementById('checkFreeSpace');
|
||||
var viewUserConfig = document.getElementById('viewUserConfig');
|
||||
var version = document.getElementById('version');
|
||||
var rotationId = document.getElementById('rotationId');
|
||||
var updateUserConfig = document.getElementById('updateUserConfig');
|
||||
|
||||
|
||||
buttonIndex.addEventListener('click', function () {
|
||||
@ -201,8 +231,12 @@
|
||||
|
||||
merge.addEventListener('click', function () {
|
||||
search.mergeIndexBatches().then(function () {
|
||||
search.encryptIndex().then(function () {
|
||||
resultsEl.innerHTML = "Merging and Encrypting index completed"
|
||||
search.encryptIndex('jjjehdnctsjyieoalskcjdhsnahsadndfnusdfsdfsd=').then(function () {
|
||||
searchUtils.updateUserConfig(12345678910112, {rotationId:0, version: 1}).then(function (res) {
|
||||
resultsEl.innerHTML = JSON.stringify(res);
|
||||
}).catch(function (err) {
|
||||
resultsEl.innerHTML = JSON.stringify(err);
|
||||
});
|
||||
});
|
||||
}).catch(function (err) {
|
||||
resultsEl.innerHTML = 'Error: ' + err;
|
||||
@ -216,6 +250,34 @@
|
||||
resultsEl.innerHTML = 'Error: ' + err;
|
||||
});
|
||||
});
|
||||
|
||||
checkFreeSpace.addEventListener('click', function () {
|
||||
searchUtils.checkFreeSpace().then(function (res) {
|
||||
resultsEl.innerHTML = res ? "Free Disk Space Available" : "Insufficient Disk Space";
|
||||
}).catch(function (err) {
|
||||
resultsEl.innerHTML = err;
|
||||
});
|
||||
});
|
||||
|
||||
viewUserConfig.addEventListener('click', function () {
|
||||
searchUtils.getSearchUserConfig(12345678910112).then(function (res) {
|
||||
resultsEl.innerHTML = JSON.stringify(res);
|
||||
}).catch(function (err) {
|
||||
resultsEl.innerHTML = JSON.stringify(err);
|
||||
});
|
||||
});
|
||||
|
||||
updateUserConfig.addEventListener('click', function () {
|
||||
var data = {
|
||||
rotationId: rotationId.value || 0,
|
||||
version: version.value || 1
|
||||
};
|
||||
searchUtils.updateUserConfig(12345678910112, data).then(function (res) {
|
||||
resultsEl.innerHTML = JSON.stringify(res);
|
||||
}).catch(function (err) {
|
||||
resultsEl.innerHTML = JSON.stringify(err);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -160,7 +160,7 @@ DecryptionStream.prototype._flush = function(cb) {
|
||||
try {
|
||||
this._decipher.final();
|
||||
} catch (e) {
|
||||
return cb(e);
|
||||
return cb();
|
||||
}
|
||||
decrypted.forEach(function(item) {
|
||||
this.push(item);
|
||||
|
@ -12,6 +12,11 @@ const DUMP_PATH = isDevEnv ? path.join(__dirname, '..', '..') : searchConfig.FOL
|
||||
|
||||
class Crypto {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param userId
|
||||
* @param key
|
||||
*/
|
||||
constructor(userId, key) {
|
||||
this.indexDataFolder = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME_PATH}_${userId}_${searchConfig.INDEX_VERSION}`;
|
||||
this.permanentIndexName = `${searchConfig.FOLDERS_CONSTANTS.PREFIX_NAME}_${userId}_${searchConfig.INDEX_VERSION}`;
|
||||
@ -26,7 +31,7 @@ class Crypto {
|
||||
* encrypting it
|
||||
* @returns {Promise}
|
||||
*/
|
||||
encryption() {
|
||||
encryption(key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
if (!fs.existsSync(this.indexDataFolder)){
|
||||
@ -49,7 +54,7 @@ class Crypto {
|
||||
const input = fs.createReadStream(`${this.dump}/${this.permanentIndexName}${searchConfig.TAR_LZ4_EXT}`);
|
||||
const outputEncryption = fs.createWriteStream(this.encryptedIndex);
|
||||
let config = {
|
||||
key: this.key
|
||||
key: key
|
||||
};
|
||||
const encrypt = crypto.encrypt(config);
|
||||
|
||||
|
@ -136,6 +136,13 @@ function createAPI() {
|
||||
*/
|
||||
Search: remote.require('./search/search.js').Search,
|
||||
|
||||
/**
|
||||
* Provides api for search module utils
|
||||
* like checking free space / search user config data to the client app
|
||||
* details in ./search/searchUtils.js & ./search/searchConfig.js
|
||||
*/
|
||||
SearchUtils: remote.require('./search/searchUtils.js').SearchUtils,
|
||||
|
||||
/**
|
||||
* Function to clear the user index data
|
||||
*/
|
||||
|
@ -234,13 +234,8 @@ class Search {
|
||||
* Encrypting the index after the merging the index
|
||||
* to the main user index
|
||||
*/
|
||||
encryptIndex() {
|
||||
return this.crypto.encryption().then(() => {
|
||||
return 'Success'
|
||||
}).catch((e) => {
|
||||
log.send(logLevels.ERROR, 'Encrypting the index folder failed ->' + e);
|
||||
return (new Error(e));
|
||||
});
|
||||
encryptIndex(key) {
|
||||
return this.crypto.encryption(key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,8 +3,7 @@ const app = electron.app;
|
||||
const path = require('path');
|
||||
const userData = path.join(app.getPath('userData'));
|
||||
const execPath = path.dirname(app.getPath('exe'));
|
||||
const isDevEnv = require('../utils/misc.js').isDevEnv;
|
||||
const isMac = require('../utils/misc.js').isMac;
|
||||
const { isDevEnv, isMac } = require('../utils/misc.js');
|
||||
|
||||
const INDEX_FOLDER_NAME = 'data';
|
||||
|
||||
@ -24,6 +23,9 @@ const indexFolderPath = isDevEnv ? `./${INDEX_FOLDER_NAME}` : path.join(userData
|
||||
const winSearchLibArchPath = arch ? 'libsymphonysearch-x86.dll' : 'libsymphonysearch-x64.dll';
|
||||
const libraryPath = isMac ? path.join(macLibraryPath, 'libsymphonysearch.dylib') : path.join(winLibraryPath, winSearchLibArchPath);
|
||||
|
||||
const userConfigFileName = 'search_users_config.json';
|
||||
const userConfigFile = isDevEnv ? path.join(__dirname, '..', '..', userConfigFileName) : path.join(userData, userConfigFileName);
|
||||
|
||||
const libraryPaths = {
|
||||
INDEX_VALIDATOR: indexValidatorPath,
|
||||
LZ4_PATH: lz4Path,
|
||||
@ -40,7 +42,8 @@ const folderPaths = {
|
||||
PREFIX_NAME_PATH: indexFolderPath + '/search_index',
|
||||
EXEC_PATH: execPath,
|
||||
USER_DATA_PATH: userData,
|
||||
INDEX_FOLDER_NAME: INDEX_FOLDER_NAME
|
||||
INDEX_FOLDER_NAME: INDEX_FOLDER_NAME,
|
||||
USER_CONFIG_FILE: userConfigFile
|
||||
};
|
||||
|
||||
const searchConfig = {
|
||||
@ -53,7 +56,8 @@ const searchConfig = {
|
||||
BATCH_RANDOM_INDEX_PATH_LENGTH: 20,
|
||||
LIBRARY_CONSTANTS: libraryPaths,
|
||||
FOLDERS_CONSTANTS: folderPaths,
|
||||
TAR_LZ4_EXT: '.tar.lz4'
|
||||
TAR_LZ4_EXT: '.tar.lz4',
|
||||
MINIMUM_DISK_SPACE: 300000000 // in bytes
|
||||
};
|
||||
|
||||
module.exports = searchConfig;
|
||||
|
166
js/search/searchUtils.js
Normal file
166
js/search/searchUtils.js
Normal file
@ -0,0 +1,166 @@
|
||||
const fs = require('fs');
|
||||
const { checkDiskSpace } = require('./utils/checkDiskSpace.js');
|
||||
const searchConfig = require('./searchConfig.js');
|
||||
const { isMac } = require('../utils/misc.js');
|
||||
|
||||
/**
|
||||
* Utils to validate users config data and
|
||||
* available disk space to enable electron search
|
||||
*/
|
||||
class SearchUtils {
|
||||
|
||||
constructor() {
|
||||
this.path = searchConfig.FOLDERS_CONSTANTS.USER_DATA_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns true if the available disk space
|
||||
* is more than the constant MINIMUM_DISK_SPACE
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
checkFreeSpace() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!isMac) {
|
||||
this.path = this.path.substring(0, 2);
|
||||
}
|
||||
checkDiskSpace(this.path, function (error, res) {
|
||||
|
||||
if (error) {
|
||||
return reject(new Error(error));
|
||||
}
|
||||
|
||||
return resolve(res >= searchConfig.MINIMUM_DISK_SPACE);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function return the user search config
|
||||
* @param userId
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
getSearchUserConfig(userId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
readFile.call(this, userId, resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function updates the user config file
|
||||
* with the provided data
|
||||
* @param userId
|
||||
* @param data
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
updateUserConfig(userId, data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
updateConfig.call(this, userId, data, resolve, reject);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function reads the search user config file and
|
||||
* return the object
|
||||
* @param userId
|
||||
* @param resolve
|
||||
* @param reject
|
||||
*/
|
||||
function readFile(userId, resolve, reject) {
|
||||
if (fs.existsSync(`${searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE}`)) {
|
||||
fs.readFile(`${searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE}`, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
return reject(new Error('Error reading the '))
|
||||
}
|
||||
let usersConfig = [];
|
||||
try {
|
||||
usersConfig = JSON.parse(data);
|
||||
} catch (e) {
|
||||
createUserConfigFile(userId);
|
||||
return reject('can not parse user config file data: ' + data + ', error: ' + e);
|
||||
}
|
||||
if (!usersConfig[userId]) {
|
||||
createUser(userId, usersConfig);
|
||||
return reject(null);
|
||||
}
|
||||
return resolve(usersConfig[userId]);
|
||||
})
|
||||
} else {
|
||||
createUserConfigFile(userId);
|
||||
resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the config has no object for the provided userId this function
|
||||
* creates an empty object with the key as the userId
|
||||
* @param userId
|
||||
* @param oldConfig
|
||||
*/
|
||||
function createUser(userId, oldConfig) {
|
||||
let configPath = searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE;
|
||||
let newConfig = Object.assign({}, oldConfig);
|
||||
newConfig[userId] = {};
|
||||
|
||||
let jsonNewConfig = JSON.stringify(newConfig, null, ' ');
|
||||
|
||||
fs.writeFile(configPath, jsonNewConfig, 'utf8', (err) => {
|
||||
if (err) {
|
||||
throw new err;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function creates the config
|
||||
* file if not present
|
||||
* @param userId
|
||||
* @param data
|
||||
*/
|
||||
function createUserConfigFile(userId, data) {
|
||||
let createStream = fs.createWriteStream(searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE);
|
||||
if (data) {
|
||||
createStream.write(`{"${userId}": ${JSON.stringify(data)}}`);
|
||||
} else {
|
||||
createStream.write(`{"${userId}": {}}`);
|
||||
}
|
||||
createStream.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to update user config data
|
||||
* @param userId
|
||||
* @param data
|
||||
* @param resolve
|
||||
* @param reject
|
||||
* @returns {*}
|
||||
*/
|
||||
function updateConfig(userId, data, resolve, reject) {
|
||||
let configPath = searchConfig.FOLDERS_CONSTANTS.USER_CONFIG_FILE;
|
||||
if (!fs.existsSync(configPath)) {
|
||||
createUserConfigFile(userId, data);
|
||||
return reject(null);
|
||||
}
|
||||
|
||||
let oldConfig;
|
||||
let oldData = fs.readFileSync(configPath, 'utf8');
|
||||
|
||||
try {
|
||||
oldConfig = JSON.parse(oldData);
|
||||
} catch (e) {
|
||||
createUserConfigFile(userId, data);
|
||||
return reject('can not parse user config file data: ' + e);
|
||||
}
|
||||
|
||||
let newConfig = Object.assign({}, oldConfig);
|
||||
newConfig[userId] = data;
|
||||
|
||||
let jsonNewConfig = JSON.stringify(newConfig, null, ' ');
|
||||
|
||||
fs.writeFileSync(configPath, jsonNewConfig, 'utf8');
|
||||
return resolve(newConfig[userId]);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SearchUtils: SearchUtils
|
||||
};
|
44
js/search/utils/checkDiskSpace.js
Normal file
44
js/search/utils/checkDiskSpace.js
Normal file
@ -0,0 +1,44 @@
|
||||
const { exec } = require('child_process');
|
||||
const { isMac } = require('../../utils/misc');
|
||||
|
||||
function checkDiskSpace(path, callback) {
|
||||
if (!path) {
|
||||
return "Please provide path"
|
||||
}
|
||||
|
||||
if (isMac) {
|
||||
exec("df -k '" + path.replace(/'/g,"'\\''") + "'", (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
if (stderr.indexOf("No such file or directory") !== -1) {
|
||||
return callback("No such file or directory : " + error)
|
||||
}
|
||||
return callback("Error : " + error)
|
||||
}
|
||||
|
||||
let data = stdout.trim().split("\n");
|
||||
|
||||
let disk_info_str = data[data.length - 1].replace( /[\s\n\r]+/g,' ');
|
||||
let freeSpace = disk_info_str.split(' ');
|
||||
return callback(null, freeSpace[3] * 1024);
|
||||
});
|
||||
} else {
|
||||
exec(`fsutil volume diskfree ${path}`, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
if (stderr.indexOf("No such file or directory") !== -1) {
|
||||
return callback("No such file or directory : " + error)
|
||||
}
|
||||
return callback("Error : " + error)
|
||||
}
|
||||
let data = stdout.trim().split("\n");
|
||||
|
||||
let disk_info_str = data[data.length - 1].split(':');
|
||||
return callback(null, disk_info_str[1]);
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
checkDiskSpace: checkDiskSpace
|
||||
};
|
Loading…
Reference in New Issue
Block a user