Setup files
- Adding setup files to configure, set password. - Private key will now be stored in encrypted shares. Password will be required for running the server. - Automated creation of MySQL schema. - Making floGlobals common for both server and client. - Fixed a minor bug in database.js
This commit is contained in:
parent
8a014405f4
commit
96b9d3b6e9
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,4 +2,5 @@
|
|||||||
/package-lock.json
|
/package-lock.json
|
||||||
/args/config.json
|
/args/config.json
|
||||||
/args/param.json
|
/args/param.json
|
||||||
|
/args/keys.json
|
||||||
*test*
|
*test*
|
||||||
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"secret": "Secret_For_Session__Enter_A_Strong_String(Text/Password)",
|
|
||||||
"blockchain_id": "FLO_ID_of_the_admin",
|
|
||||||
"blockchain_private": "Private_Key_of_the_Admin",
|
|
||||||
"port": "8080",
|
|
||||||
|
|
||||||
"sql_user": "mySQL_user",
|
|
||||||
"sql_pwd": "mySQL_password",
|
|
||||||
"sql_db": "supernode",
|
|
||||||
"sql_host": "localhost"
|
|
||||||
}
|
|
||||||
@ -8,6 +8,7 @@ const floGlobals = {
|
|||||||
FLO: ['https://livenet.flocha.in/', 'https://flosight.duckdns.org/'],
|
FLO: ['https://livenet.flocha.in/', 'https://flosight.duckdns.org/'],
|
||||||
FLO_TEST: ['https://testnet-flosight.duckdns.org', 'https://testnet.flocha.in/']
|
FLO_TEST: ['https://testnet-flosight.duckdns.org', 'https://testnet.flocha.in/']
|
||||||
},
|
},
|
||||||
|
adminID: "FKAEdnPfjXLHSYwrXQu377ugN4tXU7VGdf",
|
||||||
sendAmt: 0.001,
|
sendAmt: 0.001,
|
||||||
fee: 0.0005,
|
fee: 0.0005,
|
||||||
tokenURL: "https://ranchimallflo.duckdns.org/",
|
tokenURL: "https://ranchimallflo.duckdns.org/",
|
||||||
@ -7,28 +7,7 @@
|
|||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script src="floGlobals.js"></script>
|
||||||
|
|
||||||
</script>
|
|
||||||
<script id="floGlobals">
|
|
||||||
/* Constants for FLO blockchain operations !!Make sure to add this at begining!! */
|
|
||||||
const floGlobals = {
|
|
||||||
|
|
||||||
//Required for all
|
|
||||||
blockchain: "FLO",
|
|
||||||
|
|
||||||
//Required for blockchain API operators
|
|
||||||
apiURL: {
|
|
||||||
FLO: ['https://livenet.flocha.in/', 'https://flosight.duckdns.org/'],
|
|
||||||
FLO_TEST: ['https://testnet-flosight.duckdns.org/', 'https://testnet.flocha.in/']
|
|
||||||
},
|
|
||||||
tokenURL: "https://ranchimallflo.duckdns.org/",
|
|
||||||
token: "rupee",
|
|
||||||
adminID: "FKAEdnPfjXLHSYwrXQu377ugN4tXU7VGdf",
|
|
||||||
sendAmt: 0.001,
|
|
||||||
fee: 0.0005,
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="https://sairajzero.github.io/Standard_Operations/cdn/floCrypto.js"></script>
|
<script src="https://sairajzero.github.io/Standard_Operations/cdn/floCrypto.js"></script>
|
||||||
<script src="https://github.com/sairajzero/Standard_Operations/releases/download/test/floBlockchainAPI.js"></script>
|
<script src="https://github.com/sairajzero/Standard_Operations/releases/download/test/floBlockchainAPI.js"></script>
|
||||||
<script src="fn.js"></script>
|
<script src="fn.js"></script>
|
||||||
|
|||||||
90
setup/configure-settings.js
Normal file
90
setup/configure-settings.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const getInput = require('./getInput');
|
||||||
|
|
||||||
|
var config, flag = false;
|
||||||
|
try {
|
||||||
|
config = require('./args/config.json');
|
||||||
|
flag = true;
|
||||||
|
} catch (error) {
|
||||||
|
config = {
|
||||||
|
"secret": null,
|
||||||
|
"blockchain_id": null,
|
||||||
|
"blockchain_private": null,
|
||||||
|
"port": "8080",
|
||||||
|
|
||||||
|
"sql_user": null,
|
||||||
|
"sql_pwd": null,
|
||||||
|
"sql_db": "exchange",
|
||||||
|
"sql_host": "localhost"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
getInput.YesOrNo('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(__dirname + '/../args/config.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(_ => null);
|
||||||
|
else
|
||||||
|
module.exports = configure;
|
||||||
37
setup/create-schema.js
Normal file
37
setup/create-schema.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const config = require('./args/config.json');
|
||||||
|
let Database = require('./src/database');
|
||||||
|
|
||||||
|
function createSchema() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fs.readFile(__dirname + '/../args/schema.sql', 'utf8', (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
return reject(null);
|
||||||
|
}
|
||||||
|
Database(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(DB => {
|
||||||
|
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);
|
||||||
|
else
|
||||||
|
module.exports = createSchema;
|
||||||
42
setup/getInput.js
Normal file
42
setup/getInput.js
Normal file
@ -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;
|
||||||
11
setup/help.js
Normal file
11
setup/help.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
let message = `
|
||||||
|
Exchange market
|
||||||
|
|
||||||
|
npm install - Install the app and node modules.
|
||||||
|
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 run create-schema - Create the schema in MySQL database.
|
||||||
|
npm run help - List all commands.
|
||||||
|
npm start - Start the application.
|
||||||
|
`;
|
||||||
33
setup/post-install.js
Normal file
33
setup/post-install.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
const getInput = require("./getInput");
|
||||||
|
|
||||||
|
let message = `
|
||||||
|
Exchange 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');
|
||||||
|
})
|
||||||
|
} else
|
||||||
|
console.log('Reset the password later using:\n' + 'npm run reset-password');
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else
|
||||||
|
console.log('Finish the setup later using:\n' + 'npm run setup');
|
||||||
|
})
|
||||||
83
setup/reset-password.js
Normal file
83
setup/reset-password.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const getInput = require('./getInput');
|
||||||
|
|
||||||
|
const floGlobals = require('../public/floGlobals');
|
||||||
|
require('../src/set_globals');
|
||||||
|
require('../src/lib');
|
||||||
|
require('../src/floCrypto');
|
||||||
|
|
||||||
|
console.log(__dirname);
|
||||||
|
|
||||||
|
function validateKey(privKey) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (floCrypto.verifyPrivKey(privKey, floGlobals.adminID))
|
||||||
|
return resolve(privKey);
|
||||||
|
else {
|
||||||
|
getInput.Text('Incorrect Private Key! 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 for adminID (${floGlobals.adminID})`).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(__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(error => console.error(error));
|
||||||
|
else
|
||||||
|
module.exports = resetPassword;
|
||||||
@ -66,6 +66,8 @@ function Database(user, password, dbname, host = 'localhost') {
|
|||||||
queryFn(result);
|
queryFn(result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (!Array.isArray(q_i))
|
||||||
|
q_i = [q_i];
|
||||||
if (q_i[1])
|
if (q_i[1])
|
||||||
conn.query(q_i[0], q_i[1], callback);
|
conn.query(q_i[0], q_i[1], callback);
|
||||||
else
|
else
|
||||||
|
|||||||
31
src/main.js
31
src/main.js
@ -1,5 +1,5 @@
|
|||||||
const config = require('../args/config.json');
|
const config = require('../args/config.json');
|
||||||
global.floGlobals = require("./floGlobals");
|
global.floGlobals = require('../public/floGlobals');
|
||||||
require('./set_globals');
|
require('./set_globals');
|
||||||
require('./lib');
|
require('./lib');
|
||||||
require('./floCrypto');
|
require('./floCrypto');
|
||||||
@ -7,21 +7,30 @@ require('./floBlockchainAPI');
|
|||||||
|
|
||||||
const Database = require("./database");
|
const Database = require("./database");
|
||||||
const App = require('./app');
|
const App = require('./app');
|
||||||
|
const floGlobals = require('../public/floGlobals');
|
||||||
const PORT = config['port'];
|
const PORT = config['port'];
|
||||||
|
|
||||||
module.exports = function startServer(public_dir) {
|
module.exports = function startServer(public_dir) {
|
||||||
|
try {
|
||||||
global.myPrivKey = config["blockchain_private"];
|
var _tmp = require('../args/keys.json');
|
||||||
global.myPubKey = floCrypto.getPubKeyHex(global.myPrivKey);
|
_tmp = floCrypto.retrieveShamirSecret(_tmp);
|
||||||
global.myFloID = floCrypto.getFloID(global.myPubKey);
|
var _pass = process.env.password;
|
||||||
|
_tmp = Crypto.AES.decrypt(_tmp, _pass);
|
||||||
if (global.myFloID !== config["blockchain_id"] || !floCrypto.verifyPrivKey(global.myPrivKey, global.myFloID)) {
|
if (floCrypto.verifyPrivKey(_tmp, floGlobals.adminID)) {
|
||||||
console.error("Invalid Private Key for adminID");
|
global.myPrivKey = _tmp;
|
||||||
return;
|
global.myPubKey = floCrypto.getPubKeyHex(global.myPrivKey);
|
||||||
|
global.myFloID = floCrypto.getFloID(global.myPubKey);
|
||||||
|
} else {
|
||||||
|
console.error('Loaded wrong private key!');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Unable to load private key!');
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
floGlobals.adminID = config["blockchain_id"];
|
|
||||||
global.PUBLIC_DIR = public_dir;
|
global.PUBLIC_DIR = public_dir;
|
||||||
console.log(PUBLIC_DIR, global.myFloID);
|
console.debug(PUBLIC_DIR, global.myFloID);
|
||||||
|
|
||||||
Database(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(DB => {
|
Database(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(DB => {
|
||||||
const app = App(config['secret'], DB);
|
const app = App(config['secret'], DB);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user