diff --git a/.gitignore b/.gitignore index d7be72d..0a1034c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /package-lock.json /args/config.json /args/param.json +/args/keys.json /log.txt /bash_start* *test* diff --git a/args/config-sample.json b/args/config-sample.json deleted file mode 100644 index 34ab909..0000000 --- a/args/config-sample.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "privateKey": "FLO_Private_Key_of_SuperNode", - "port": "8080", - - "sql_user": "mySQL_user", - "sql_pwd": "mySQL_password", - "sql_db": "supernode", - "sql_host": "localhost" -} \ No newline at end of file diff --git a/args/post-install.js b/args/post-install.js deleted file mode 100644 index 25b9fb2..0000000 --- a/args/post-install.js +++ /dev/null @@ -1,11 +0,0 @@ -let message = -`SupernodeStorage is installed. - -To complete the setup: -1. Copy args/config-sample.json to args/config.json and Edit the values as required -2. (Optional) Open args/gen-param.html and Download param.json to args/ directory - -To start the node, Run: -npm start -`; -console.log(message); \ No newline at end of file diff --git a/package.json b/package.json index 7d48682..c761d1a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,11 @@ }, "devDependencies": {}, "scripts": { - "postinstall": "node args/post-install.js", + "postinstall": "node setup/post-install.js", + "help": "node setup/help.js", + "setup": "node setup/post-install.js", + "configure": "node setup/configure-settings.js", + "reset-password": "node setup/reset-password.js", "start": "node start.js" }, "repository": { @@ -29,4 +33,4 @@ "url": "https://github.com/ranchimall/SuperNodeStorage/issues" }, "homepage": "https://github.com/ranchimall/SuperNodeStorage#readme" -} +} \ No newline at end of file diff --git a/setup/configure-settings.js b/setup/configure-settings.js new file mode 100644 index 0000000..7ce7df2 --- /dev/null +++ b/setup/configure-settings.js @@ -0,0 +1,85 @@ +const fs = require('fs'); +const path = require('path'); +const getInput = require('./getInput'); + +var config, flag_new; +try { + config = require(`../args/config.json`); + flag_new = false; +} catch (error) { + config = { + "port": "8080", + + "sql_user": "mySQL_user", + "sql_pwd": "mySQL_password", + "sql_db": "supernode", + "sql_host": "localhost" + }; + flag_new = true; +} + +function flaggedYesOrNo(text) { + return new Promise((resolve) => { + if (flag_new) + resolve(true); + else + getInput.YesOrNo(text) + .then(result => resolve(result)) + .catch(error => reject(error)) + }) +} + +function configurePort() { + return new Promise(resolve => { + getInput.Text('Enter port', config["port"]).then(port => { + config["port"] = port; + resolve(true); + }) + }) +} + +function configureSQL() { + return new Promise(resolve => { + flaggedYesOrNo('Do you want to re-configure mySQL connection').then(value => { + if (value) { + console.log('Enter mySQL connection values: ') + getInput.Text('Host', config['sql_host']).then(host => { + config['sql_host'] = host; + getInput.Text('Database name', config['sql_db']).then(dbname => { + config['sql_db'] = dbname; + getInput.Text('MySQL username', config['sql_user']).then(sql_user => { + config['sql_user'] = sql_user; + getInput.Text('Mysql password', config['sql_pwd']).then(sql_pwd => { + config['sql_pwd'] = sql_pwd; + resolve(true); + }) + }) + }) + }) + } else + resolve(false); + }) + }) +} + +function configure() { + return new Promise((resolve, reject) => { + configurePort().then(port_result => { + configureSQL().then(sql_result => { + fs.writeFile(path.resolve(__dirname, '..', 'args', `config.json`), JSON.stringify(config), 'utf8', (err) => { + if (err) { + console.error(err); + return reject(false); + } + console.log('Configuration successful!'); + resolve(true); + }) + }) + }); + }) +} + +if (!module.parent) + configure().then(_ => null).catch(error => console.error(error)).finally(_ => process.exit(0)); +else + module.exports = configure; \ No newline at end of file diff --git a/setup/getInput.js b/setup/getInput.js new file mode 100644 index 0000000..c0fc277 --- /dev/null +++ b/setup/getInput.js @@ -0,0 +1,42 @@ +const readline = require('readline'); + +const getInput = { + Text: function(text, current = null) { + return new Promise((resolve) => { + let r = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + r.question(`${text} :` + (current ? `(${current})` : ''), value => { + r.close(); + value = value || current; + if (value === null) { + console.log("Please enter a value!"); + this.Text(text, current).then(result => resolve(result)); + } else + resolve(value); + }); + }) + }, + + YesOrNo: function(text, def_value = "YES") { + return new Promise((resolve) => { + let r = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + r.question(`${text}? [YES/NO] : (${def_value})`, value => { + r.close(); + value = (value || def_value).toLowerCase(); + value = ['yes', 'y'].includes(value) ? true : ['no', 'n'].includes(value) ? false : null; + if (value === null) { + console.log("Please enter a valid value!"); + this.YesOrNo(text, def_value).then(result => resolve(result)); + } else + resolve(value); + }); + }) + } +} + +module.exports = getInput; \ No newline at end of file diff --git a/setup/help.js b/setup/help.js new file mode 100644 index 0000000..9ba1c3d --- /dev/null +++ b/setup/help.js @@ -0,0 +1,22 @@ +let message = ` +SuperNode Storage +----------------- + +npm install - Install the app and node modules. +npm run help - List all commands. +npm run setup - Finish the setup (configure and reset password). +npm run configure - Configure the app. +npm run reset-password - Reset the password (for private-key). + +npm start - Start the application (main). + +NOTE: argument 'PASSWORD' required for 'npm start' +npm start -- -PASSWORD= + +(Optional) 'console.debug' is now turned off by default. pass argument '--debug' to turn it on +npm start -- -PASSWORD= --debug + +(Optional) Open args/gen-param.html and Download param.json to args/ directory +`; + +console.log(message); \ No newline at end of file diff --git a/setup/post-install.js b/setup/post-install.js new file mode 100644 index 0000000..89ad839 --- /dev/null +++ b/setup/post-install.js @@ -0,0 +1,38 @@ +const getInput = require("./getInput"); + +let message = ` +SuperNode Storage is installed +To list all commands, use: +npm run help +`; +console.log(message); + +getInput.YesOrNo('Do you want to finish the setup now').then(value => { + if (value) { + let configureSettings = require('./configure-settings'); + configureSettings() + .then(_ => console.log('To Re-configure, use:')) + .catch(_ => console.log('Finish the configuration later using: ')) + .finally(_ => { + console.log('npm run configure'); + getInput.YesOrNo('Do you want to Reset password for private key now').then(value => { + if (value) { + let resetPassword = require('./reset-password'); + resetPassword() + .then(_ => console.log('To reset the password again, use: ')) + .catch(_ => console.log('Reset the password later using: ')) + .finally(_ => { + console.log('npm run reset-password'); + process.exit(0); + }) + } else { + console.log('Reset the password later using:\n' + 'npm run reset-password'); + process.exit(0); + } + }) + }) + } else { + console.log('Finish the setup later using:\n' + 'npm run setup'); + process.exit(0); + } +}) \ No newline at end of file diff --git a/setup/reset-password.js b/setup/reset-password.js new file mode 100644 index 0000000..19e2089 --- /dev/null +++ b/setup/reset-password.js @@ -0,0 +1,87 @@ +const fs = require('fs'); +const getInput = require('./getInput'); + +global.floGlobals = require('../src/floGlobals'); +require('../src/set_globals'); +require('../src/lib'); +const floCrypto = require('../src/floCrypto'); +const path = require('path'); + +function validateKey(privKey) { + return new Promise((resolve, reject) => { + try { + if (!privKey || privKey === "") + throw 'Private Key cannot be empty!'; + let floID = floCrypto.getFloID(privKey); + if (!floID || !floCrypto.verifyPrivKey(privKey, floID)) + throw 'Invalid Private Key!'; + return resolve(privKey); + } catch (error) { + getInput.Text(error + ' Re-Enter: (Cancel)', 'Cancel').then(value => { + if (value === 'Cancel') + return reject(true); + validateKey(value) + .then(result => resolve(result)) + .catch(error => reject(error)) + }); + } + }) +} + +function getPassword() { + return new Promise((resolve, reject) => { + getInput.Text(`Enter a password [Minimum 8 characters]`, 'Cancel').then(value1 => { + if (value1 === 'Cancel') + return reject(true); + else if (value1.length < 8) { + console.log('Password length must be minimum of 8 characters'); + getPassword() + .then(result => resolve(result)) + .catch(error => reject(error)) + } else { + getInput.Text(`Re-enter password`).then(value2 => { + if (value1 !== value2) { + console.log('Passwords doesnot match! Try again.'); + getPassword() + .then(result => resolve(result)) + .catch(error => reject(error)) + } else + resolve(value1); + }) + } + }); + }) +} + +function resetPassword() { + return new Promise((resolve, reject) => { + getInput.Text(`Enter private key`).then(value => { + validateKey(value).then(privKey => { + getPassword().then(password => { + let encrypted = Crypto.AES.encrypt(privKey, password); + let randNum = floCrypto.randInt(10, 15); + let splitShares = floCrypto.createShamirsSecretShares(encrypted, randNum, randNum); + fs.writeFile(path.resolve(__dirname, '..', 'args', `keys.json`), JSON.stringify(splitShares), 'utf8', (err) => { + if (err) { + console.error(err); + return reject(false); + } + console.log('Password reset successful!'); + resolve(true); + }) + }).catch(error => { + console.log('Password reset cancelled!'); + reject(true); + }) + }).catch(error => { + console.log('Password reset cancelled!'); + reject(true); + }) + }) + }) +} + +if (!module.parent) + resetPassword().then(_ => null).catch(_ => null).finally(_ => process.exit(0)); +else + module.exports = resetPassword; \ No newline at end of file diff --git a/src/set_globals.js b/src/set_globals.js index b743c93..849932e 100644 --- a/src/set_globals.js +++ b/src/set_globals.js @@ -11,4 +11,7 @@ try { } finally { for (let p in param) global[p] = param[p]; -} \ No newline at end of file +} + +if (!process.argv.includes("--debug")) + global.console.debug = () => null; \ No newline at end of file