From d01d1de0460a259fa0d3ce426b6a908713393883 Mon Sep 17 00:00:00 2001 From: sairajzero Date: Mon, 12 Jun 2023 14:30:32 +0530 Subject: [PATCH] Adding setup files --- args/param-default.json | 37 +++++++++++ args/truncateAll.sql | 18 +++++ setup/configure-settings.js | 129 ++++++++++++++++++++++++++++++++++++ setup/create-schema.js | 45 +++++++++++++ setup/getInput.js | 42 ++++++++++++ setup/help.js | 23 +++++++ setup/post-install.js | 38 +++++++++++ setup/reset-password.js | 94 ++++++++++++++++++++++++++ 8 files changed, 426 insertions(+) create mode 100644 args/param-default.json create mode 100644 args/truncateAll.sql create mode 100644 setup/configure-settings.js create mode 100644 setup/create-schema.js create mode 100644 setup/getInput.js create mode 100644 setup/help.js create mode 100644 setup/post-install.js create mode 100644 setup/reset-password.js diff --git a/args/param-default.json b/args/param-default.json new file mode 100644 index 0000000..6476705 --- /dev/null +++ b/args/param-default.json @@ -0,0 +1,37 @@ +{ + "screen": { + "height": 1160, + "width": 2000, + "colorDepth": 24, + "availHeight": 1080, + "availWidth": 1920, + "pixelDepth": 24 + }, + "navigator": { + "userAgent": "Node/14.17.3 (Linux; aarch64; arm)", + "plugins": [{ + "name": "MySQL", + "filename": "mysql", + "description": "A node.js driver for mysql. It is written in JavaScript, does not require compiling, and is 100% MIT licensed." + }, { + "name": "WebSocket", + "filename": "ws", + "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js" + }, { + "name": "Node fetch", + "filename": "node-fetch", + "description": "A light-weight module that brings window.fetch to node.js" + }], + "mimeTypes": [{ + "description": "", + "type": "application/pdf", + "suffixes": "pdf" + }], + "cookieEnabled": true, + "language": "en-US" + }, + "history": { + "length": 512 + }, + "location": "protocol://subdomain.example.domain/path" +} \ No newline at end of file diff --git a/args/truncateAll.sql b/args/truncateAll.sql new file mode 100644 index 0000000..4945120 --- /dev/null +++ b/args/truncateAll.sql @@ -0,0 +1,18 @@ +/* Node data */ +TRUNCATE _backup; +TRUNCATE _backupCache; +TRUNCATE AuditTrade; +TRUNCATE BuyOrder; +TRUNCATE VaultTransactions; +TRUNCATE PriceHistory; +TRUNCATE RequestLog; +TRUNCATE SellOrder; +TRUNCATE UserBalance; +TRUNCATE UserSession; +TRUNCATE TransferTransactions; +TRUNCATE TradeTransactions; + +/* Blockchain data */ +TRUNCATE LastTx; +TRUNCATE NodeList; +DELETE FROM AssetList; \ No newline at end of file diff --git a/setup/configure-settings.js b/setup/configure-settings.js new file mode 100644 index 0000000..a64a6aa --- /dev/null +++ b/setup/configure-settings.js @@ -0,0 +1,129 @@ +const fs = require('fs'); +const path = require('path'); +const getInput = require('./getInput'); + +let _I = ""; +for (let arg of process.argv) + if (/^-I=/.test(arg)) { + _I = arg.split(/=(.*)/s)[1]; + break; + } + +var config, flag_new; +try { + config = require(`../args/config${_I}.json`); + flag_new = false; +} catch (error) { + config = { + "secret": null, + "port": "8080", + + "sql_user": null, + "sql_pwd": null, + "sql_db": "flobtc", + "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('MySQL 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 randomizeSessionSecret() { + return new Promise((resolve) => { + flaggedYesOrNo('Do you want to randomize the session secret').then(value => { + if (value) { + let N = Math.floor(Math.random() * (64 - 32 + 1)) + 32; + var secret = ''; + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (var i = 0; i < N; i++) + secret += characters.charAt(Math.floor(Math.random() * characters.length)); + config['secret'] = secret; + resolve(true); + } else + resolve(false); + }) + }) +} + +function configure() { + return new Promise((resolve, reject) => { + configurePort().then(port_result => { + randomizeSessionSecret().then(secret_result => { + configureSQL().then(sql_result => { + fs.writeFile(path.resolve(__dirname, '..', 'args', `config${_I}.json`), JSON.stringify(config), 'utf8', (err) => { + if (err) { + console.error(err); + return reject(false); + } + console.log('Configuration successful!'); + /* + if (sql_result) { + getInput.YesOrNo('Do you want to create schema in the database').then(value => { + if (value) { + const createSchema = require('./create-schema'); + createSchema().then(result => resolve(result)) + .catch(error => { + console.log('Retry using: \n' + 'npm run create-schema'); + reject(error); + }); + } else { + console.log('To create schema, use: \n' + 'npm run create-schema'); + resolve(true); + } + }); + } else + */ + 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/create-schema.js b/setup/create-schema.js new file mode 100644 index 0000000..8f7f798 --- /dev/null +++ b/setup/create-schema.js @@ -0,0 +1,45 @@ +const fs = require('fs'); +const path = require('path'); +let DB = require('../src/database'); + +let _I = ""; +for (let arg of process.argv) + if (/^-I=/.test(arg)) { + _I = arg.split(/=(.*)/s)[1]; + break; + } + +function createSchema() { + const config = require(`../args/config${_I}.json`); + return new Promise((resolve, reject) => { + fs.readFile(path.resolve(__dirname, '..', 'args', `schema.sql`), 'utf8', (err, data) => { + if (err) { + console.error(err); + return reject(null); + } + DB.connect(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(_ => { + let txQueries = data.split(';'); + txQueries.pop(); + txQueries = txQueries.map(q => q.trim().replace(/\n/g, ' ')); + //console.log(txQueries); + DB.transaction(txQueries).then(_ => { + console.log('SQL Schema created successfully!'); + resolve(true); + }).catch(error => { + console.error(error.message); + console.log('SQL Schema creation failed! Check user permission'); + reject(true); + }); + }).catch(error => { + console.error(error); + console.log('Unable to connect to MySQL database! Check user permission'); + reject(false); + }); + }); + }); +} + +if (!module.parent) + createSchema().then(_ => null).catch(_ => null).finally(_ => process.exit(0)); +else + module.exports = createSchema; \ 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..d951eee --- /dev/null +++ b/setup/help.js @@ -0,0 +1,23 @@ +let message = ` +Trade market +--------------- + +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 node. +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) Multiple instance can be run/setup on the same dir with different config files by using argument 'I'. + -- -I= + +(Optional) 'console.debug' is now turned off by default. pass argument '--debug' to turn it on +npm start -- -PASSWORD= --debug +`; + +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..e5ce2da --- /dev/null +++ b/setup/post-install.js @@ -0,0 +1,38 @@ +const getInput = require("./getInput"); + +let message = ` +Trade Market 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..dfffd1d --- /dev/null +++ b/setup/reset-password.js @@ -0,0 +1,94 @@ +const fs = require('fs'); +const getInput = require('./getInput'); + +global.floGlobals = require('../docs/scripts/floGlobals'); +require('../src/set_globals'); +require('../docs/scripts/lib'); +const floCrypto = require('../docs/scripts/floCrypto'); +const path = require('path'); + +let _I = ""; +for (let arg of process.argv) + if (/^-I=/.test(arg)) { + _I = arg.split(/=(.*)/s)[1]; + break; + } + +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${_I}.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