diff --git a/.gitignore b/.gitignore index 4ff1827..b6ee8df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ /node_modules/ /package-lock.json -/args/app-config.json -/args/backup-config.json +/args/config*.json /args/param.json -/args/keys.json +/args/keys*.json *test* \ No newline at end of file diff --git a/args/schema.sql b/args/schema.sql index ed8d0d5..9945813 100644 --- a/args/schema.sql +++ b/args/schema.sql @@ -113,6 +113,12 @@ PRIMARY KEY(id), FOREIGN KEY (floID) REFERENCES Users(floID) ); +CREATE TABLE lastTx( +floID CHAR(34) NOT NULL, +num INT, +PRIMARY KEY(floID) +); + CREATE TABLE nodeList( floID CHAR(34) NOT NULL, uri TINYTEXT, @@ -121,11 +127,11 @@ PRIMARY KEY(floID) CREATE TABLE trustedList( floID CHAR(34) NOT NULL, -FOREIGN KEY (floID) REFERENCES Users(floID), +PRIMARY KEY(floID), +FOREIGN KEY (floID) REFERENCES Users(floID) ); CREATE TABLE TagList ( -id INT NOT NULL AUTO_INCREMENT, tag VARCHAR(50) NOT NULL, sellPriority INT, buyPriority INT, @@ -171,7 +177,7 @@ CREATE TABLE sinkShares( floID CHAR(34) NOT NULL, share TEXT, time_ DATETIME DEFAULT CURRENT_TIMESTAMP, -PRIMARY KEY(floID, share) +PRIMARY KEY(floID) ); /* Backup feature (Table and Triggers) */ diff --git a/package.json b/package.json index 9d6279a..00adc71 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,6 @@ "configure": "node setup/configure-settings.js", "reset-password": "node setup/reset-password.js", "create-schema": "node setup/create-schema.js", - "configure-backup": "node setup/configure-backup.js", - "create-backup-schema": "node setup/create-backup-schema.js", - "backup": "node src/backup/storage.js", "start": "node start.js" }, "repository": { diff --git a/src/backup/KBucket.js b/public/KBucket.js similarity index 98% rename from src/backup/KBucket.js rename to public/KBucket.js index 51932b7..247896a 100644 --- a/src/backup/KBucket.js +++ b/public/KBucket.js @@ -1,5 +1,6 @@ 'use strict'; +(function(){ /*Kademlia DHT K-bucket implementation as a binary tree.*/ /** * Implementation of a Kademlia DHT k-bucket used for storing @@ -7,7 +8,7 @@ * * @extends EventEmitter */ -function BuildKBucket(options = {}) { + function BuildKBucket(options = {}) { /** * `options`: * `distance`: Function @@ -401,7 +402,7 @@ function BuildKBucket(options = {}) { } } -module.exports = function K_Bucket(masterID, backupList) { +function K_Bucket(masterID, backupList) { const decodeID = function(floID) { let k = bitjs.Base58.decode(floID); k.shift(); @@ -457,4 +458,6 @@ module.exports = function K_Bucket(masterID, backupList) { return (N == 1 ? nNodes[0] : nNodes); }; -} \ No newline at end of file +}; +('object' === typeof module) ? module.exports = K_Bucket : window.K_Bucket = K_Bucket; +})(); \ No newline at end of file diff --git a/public/fn.js b/public/fn.js index 85b8678..1b59c26 100644 --- a/public/fn.js +++ b/public/fn.js @@ -6,10 +6,9 @@ function exchangeAPI(api, options) { let curPos = exchangeAPI.curPos || 0; if (curPos >= nodeList.length) return resolve('No Nodes online'); - let url = nodeURL[nodeList[curPos]]; + let url = "http://" + nodeURL[nodeList[curPos]]; (options ? fetch(url + api, options) : fetch(url + api)) .then(result => resolve(result)).catch(error => { - console.debug(error); console.warn(nodeList[curPos], 'is offline'); //try next node exchangeAPI.curPos = curPos + 1; @@ -102,7 +101,7 @@ function getAccount(floID, proxySecret) { }; request.sign = signRequest({ type: "get_account", - timestamp: data.timestamp + timestamp: request.timestamp }, proxySecret); console.debug(request); @@ -168,7 +167,7 @@ function signRequest(request, privKey) { function getLoginCode() { return new Promise((resolve, reject) => { - exchangeAPI('/list-buyorders') + exchangeAPI('/get-login-code') .then(result => responseParse(result) .then(result => resolve(result)) .catch(error => reject(error))) @@ -249,7 +248,7 @@ function logout(floID, proxySecret) { }; request.sign = signRequest({ type: "logout", - timestamp: data.timestamp + timestamp: request.timestamp }, proxySecret); console.debug(request); @@ -543,8 +542,8 @@ function refreshDataFromBlockchain() { return new Promise((resolve, reject) => { let nodes, lastTx; try { - nodes = JSON.parse(localStorage.getItems('exhange-nodes')); - if (typeof nodes !== 'object') + nodes = JSON.parse(localStorage.getItem('exchange-nodes')); + if (typeof nodes !== 'object' || nodes === null) throw Error('nodes must be an object') else lastTx = parseInt(localStorage.getItem('exchange-lastTx')) || 0; @@ -569,8 +568,8 @@ function refreshDataFromBlockchain() { nodes[n] = content.Nodes.add[n]; } }); - localStorage.setItem('exhange-lastTx', result.totalTxs); - localStorage.setItem('exhange-nodes', JSON.stringify(nodes)); + localStorage.setItem('exchange-lastTx', result.totalTxs); + localStorage.setItem('exchange-nodes', JSON.stringify(nodes)); nodeURL = nodes; nodeKBucket = new K_Bucket(floGlobals.adminID, Object.keys(nodeURL)); nodeList = nodeKBucket.order; diff --git a/public/home.html b/public/home.html index fbec54b..5a978f0 100644 --- a/public/home.html +++ b/public/home.html @@ -12,27 +12,10 @@ - + + @@ -1068,9 +1051,9 @@ showProcess('trade_button_wrapper') try { if (tradeType === 'buy') { - await buy(quantity, price, await proxy.secret) + await buy(quantity, price, proxy.userID, await proxy.secret) } else { - await sell(quantity, price, await proxy.secret) + await sell(quantity, price, proxy.userID, await proxy.secret) } getRef('trade_button_wrapper').append(getRef('success_template').content.cloneNode(true)) notify(`Placed ${tradeType} order`, 'success') @@ -1218,9 +1201,9 @@ showWalletResult('success', `Sent ${asset} deposit request`, 'This may take upto 30 mins to reflect in your wallet.') } else { if (asset === 'FLO') { - await withdrawFLO(quantity, proxySecret) + await withdrawFLO(quantity, proxy.userID, proxySecret) } else { - await withdrawRupee(quantity, proxySecret) + await withdrawRupee(quantity, proxy.userID, proxySecret) } showWalletResult('success', `Sent ${asset} withdraw request`, 'This may take upto 30 mins to reflect in your wallet.') } @@ -1363,7 +1346,7 @@ const target = e.target.closest('.order-card') const id = target.dataset.id const type = target.dataset.type - cancelOrder(type, id, await proxy.secret) + cancelOrder(type, id, proxy.userID, await proxy.secret) .then(() => { notify('Order cancelled', 'success') target.animate([ @@ -1415,7 +1398,7 @@ if (res) { try { const proxy_secret = await proxy.secret; - const promises = [...selectedOrders].map(([id, type]) => cancelOrder(type, id, proxy_secret)) + const promises = [...selectedOrders].map(([id, type]) => cancelOrder(type, id, proxy.userID, proxy_secret)) await Promise.all(promises) selectedOrders.clear() hideMyOrdersOptions() @@ -1687,7 +1670,7 @@ const balance = {} let accountDetails = {} - function account() { + async function account() { getAccount(proxy.userID, await proxy.secret).then(acc => { getRef("login_form").classList.add('hide-completely') getRef('home').classList.add('signed-in') @@ -1778,7 +1761,7 @@ refreshDataFromBlockchain().then(nodes => { console.log(nodes); refresh(true); - }).catch(error => reject(error)) + }).catch(error => console.error(error)) }) diff --git a/setup/configure-backup.js b/setup/configure-backup.js deleted file mode 100644 index 04f4d20..0000000 --- a/setup/configure-backup.js +++ /dev/null @@ -1,100 +0,0 @@ -const fs = require('fs'); -const getInput = require('./getInput'); - -var config, flag_new; -try { - config = require('../args/backup-config.json'); - flag_new = false; -} catch (error) { - config = { - "sql_user": null, - "sql_pwd": null, - "sql_db": "exchange", - "sql_host": "localhost", - - "main_server_url": null, - "private_key": null - }; - 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 configureMainServerURL() { - return new Promise(resolve => { - getInput.Text('Enter URL of main server', config["main_server_url"]).then(url => { - config["main_server_url"] = url; - 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) => { - configureMainServerURL().then(port_result => { - configureSQL().then(sql_result => { - fs.writeFile(__dirname + '/../args/backup-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(false).then(result => resolve(result)) - .catch(error => { - console.log('Retry using: \n' + 'npm run create-backup-schema'); - reject(error); - }); - } else { - console.log('To create schema, use: \n' + 'npm run create-backup-schema'); - resolve(true); - } - }); - } else - resolve(true); - }) - }) - }); - }) -} - -if (!module.parent) - configure().then(_ => null).catch(_ => null); -else - module.exports = configure; \ No newline at end of file diff --git a/setup/configure-settings.js b/setup/configure-settings.js index 4d7d0a5..abc1673 100644 --- a/setup/configure-settings.js +++ b/setup/configure-settings.js @@ -3,7 +3,7 @@ const getInput = require('./getInput'); var config, flag_new; try { - config = require('../args/app-config.json'); + config = require(`../args/config${process.env.I || ""}.json`); flag_new = false; } catch (error) { config = { @@ -13,12 +13,7 @@ try { "sql_user": null, "sql_pwd": null, "sql_db": "exchange", - "sql_host": "localhost", - - "backup-port": "8081", - "backup-floIDs": [], - - "trusted-floIDs": [] + "sql_host": "localhost" }; flag_new = true; } @@ -34,97 +29,11 @@ function flaggedYesOrNo(text) { }) } -function get_IDs(ids) { - return new Promise((resolve, reject) => { - getInput.Text("", "continue").then(id => { - if (id === "continue") - resolve(Array.from(new Set(ids))); - else { - ids.push(id); - get_IDs(ids) - .then(result => resolve(result)) - .catch(error => reject(error)); - } - }) - }) -} - -function configureBackup() { - return new Promise(resolve => { - getInput.Text('Enter backup port (N = No backup)', config["backup-port"]).then(backup_port => { - config["backup-port"] = (backup_port === 'N' || backup_port === 'n') ? null : backup_port; - if (!config["backup-port"]) - return resolve(true); - getInput.YesOrNo('Do you want to add/remove backup floIDs?').then(value => { - if (value) { - console.log("Enter floIDs to add as backup: "); - get_IDs(config["backup-floIDs"]).then(ids => { - //delete backup IDs - let tmp_obj = {}; - for (let i in ids) { - console.log(i + 1, ":", ids[i]); - tmp_obj[i + 1] = ids[i]; - } - getInput.Text("Enter numbers to delete (seperated by comma)", "continue").then(ri => { - if (ri === "continue") - config["backup-floIDs"] = ids; - else { - for (let i of ri.split(",")) - delete tmp_obj[parseInt(i)]; - let tmp_array = []; - for (let id of tmp_obj) - tmp_array.push(id); - config["backup-floIDs"] = tmp_array; - } - resolve(true); - }) - }) - } else - resolve(true); - }) - }) - }) -} - -function configureTrustedIDs() { - return new Promise((resolve, reject) => { - getInput.YesOrNo('Do you want to add/remove trusted floIDs?').then(value => { - if (value) { - console.log("Enter floIDs to add as trusted: "); - get_IDs(config["trusted-floIDs"]).then(ids => { - //delete trusted IDs - let tmp_obj = {}; - for (let i in ids) { - console.log(i + 1, ":", ids[i]); - tmp_obj[i + 1] = ids[i]; - } - getInput.Text("Enter numbers to delete (seperated by comma)", "continue").then(ri => { - if (ri === "continue") - config["trusted-floIDs"] = ids; - else { - for (let i of ri.split(",")) - delete tmp_obj[parseInt(i)]; - let tmp_array = []; - for (let id of tmp_obj) - tmp_array.push(id); - config["trusted-floIDs"] = tmp_array; - } - resolve(true); - }) - }) - } else - resolve(true); - }) - }) -} - function configurePort() { return new Promise(resolve => { getInput.Text('Enter port', config["port"]).then(port => { config["port"] = port; - configureBackup() - .then(_ => configureTrustedIDs() - .then(_ => resolve(true))); + resolve(true); }) }) } @@ -175,7 +84,7 @@ function configure() { configurePort().then(port_result => { randomizeSessionSecret().then(secret_result => { configureSQL().then(sql_result => { - fs.writeFile(__dirname + '/../args/app-config.json', JSON.stringify(config), 'utf8', (err) => { + fs.writeFile(__dirname + `/../args/config${process.env.I || ""}.json`, JSON.stringify(config), 'utf8', (err) => { if (err) { console.error(err); return reject(false); @@ -205,6 +114,6 @@ function configure() { } if (!module.parent) - configure().then(_ => null).catch(_ => null); + configure().then(_ => null).catch(error => console.error(error)); else module.exports = configure; \ No newline at end of file diff --git a/setup/create-backup-schema.js b/setup/create-backup-schema.js deleted file mode 100644 index ba67ef6..0000000 --- a/setup/create-backup-schema.js +++ /dev/null @@ -1,2 +0,0 @@ -const createSchema = require('./create-schema'); -createSchema(false); \ No newline at end of file diff --git a/setup/create-schema.js b/setup/create-schema.js index b8758e3..7bcea36 100644 --- a/setup/create-schema.js +++ b/setup/create-schema.js @@ -1,8 +1,8 @@ const fs = require('fs'); let Database = require('../src/database'); -function createSchema(app = true) { - const config = require('../args/' + (app ? 'app' : 'backup') + "-config.json"); +function createSchema() { + const config = require(`../args/config${process.env.I || ""}.json`); return new Promise((resolve, reject) => { fs.readFile(__dirname + '/../args/schema.sql', 'utf8', (err, data) => { if (err) { diff --git a/setup/reset-password.js b/setup/reset-password.js index be76064..6583a88 100644 --- a/setup/reset-password.js +++ b/setup/reset-password.js @@ -10,10 +10,15 @@ console.log(__dirname); function validateKey(privKey) { return new Promise((resolve, reject) => { - if (floCrypto.verifyPrivKey(privKey, floGlobals.adminID)) + 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); - else { - getInput.Text('Incorrect Private Key! Re-Enter: (Cancel)', 'Cancel').then(value => { + } catch (error) { + getInput.Text(error + ' Re-Enter: (Cancel)', 'Cancel').then(value => { if (value === 'Cancel') return reject(true); validateKey(value) @@ -41,7 +46,7 @@ function getPassword() { getPassword() .then(result => resolve(result)) .catch(error => reject(error)) - } else + } else resolve(value1); }) } @@ -51,13 +56,13 @@ function getPassword() { function resetPassword() { return new Promise((resolve, reject) => { - getInput.Text(`Enter private key for adminID (${floGlobals.adminID})`).then(value => { + 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(__dirname + '/../args/keys.json', JSON.stringify(splitShares), 'utf8', (err) => { + fs.writeFile(__dirname + `/../args/keys${process.env.I || ""}.json`, JSON.stringify(splitShares), 'utf8', (err) => { if (err) { console.error(err); return reject(false); diff --git a/src/app.js b/src/app.js index 582a0f9..cc05e06 100644 --- a/src/app.js +++ b/src/app.js @@ -37,6 +37,16 @@ module.exports = function App(secret, DB) { })); */ + app.use(function(req, res, next) { + res.setHeader('Access-Control-Allow-Origin', "*"); + // Request methods you wish to allow + res.setHeader('Access-Control-Allow-Methods', 'GET, POST'); + // Request headers you wish to allow + res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); + // Pass to next layer of middleware + next(); + }) + //get code for login or signup app.get('/get-login-code', Request.getLoginCode); @@ -47,7 +57,7 @@ module.exports = function App(secret, DB) { app.post('/login', Request.Login); //logout request - app.get('/logout', Request.Logout); + app.post('/logout', Request.Logout); //place sell or buy order app.post('/buy', Request.PlaceBuyOrder); @@ -65,7 +75,7 @@ module.exports = function App(secret, DB) { app.get('/get-rate', Request.getRate) //get account details - app.get('/account', Request.Account); + app.post('/account', Request.Account); //withdraw and deposit request app.post('/deposit-flo', Request.DepositFLO); diff --git a/src/backup/head.js b/src/backup/head.js index e64bde5..4a70b02 100644 --- a/src/backup/head.js +++ b/src/backup/head.js @@ -1,6 +1,6 @@ 'use strict'; -const K_Bucket = require('./KBucket'); +const K_Bucket = require('../../public/KBucket'); const slave = require('./slave'); const WebSocket = require('ws'); const shareThreshold = 50 / 100; @@ -140,11 +140,13 @@ function send_dataImmutable(timestamp, ws) { //Shares function generateNewSink() { let sink = floCrypto.generateNewID(); - let nextNodes = KB.nextNode(global.myFloID, null); - let shares = floCrypto.createShamirsSecretShares(sink.privKey, nextNodes.length, Math.ceil(nextNodes.length * shareThreshold)); sink.shares = {}; - for (let i in nextNodes) - sink.shares[nextNodes[i]] = shares[i]; + let nextNodes = nodeKBucket.nextNode(global.myFloID, null); + if (nextNodes.length) { + let shares = floCrypto.createShamirsSecretShares(sink.privKey, nextNodes.length, Math.ceil(nextNodes.length * shareThreshold)); + for (let i in nextNodes) + sink.shares[nextNodes[i]] = shares[i]; + } return sink; } @@ -212,20 +214,20 @@ function collectShares(floID, sinkID, share) { function connectWS(floID) { let url = nodeURL[floID]; return new Promise((resolve, reject) => { - const ws = new WebSocket(url); + const ws = new WebSocket('ws://' + url); ws.on('open', _ => resolve(ws)); - ws.on('error', _ => reject(error)); + ws.on('error', error => reject(error)); }) } -function connectToMaster(i = 0) { +function connectToMaster(i = 0, init = false) { if (i >= nodeList.length) { console.error("No master is found, and myFloID is not in list. This should not happen!"); process.exit(1); } let floID = nodeList[i]; if (floID === myFloID) - serveAsMaster(); + serveAsMaster(init); else connectWS(floID).then(ws => { ws.floID = floID; @@ -233,26 +235,27 @@ function connectToMaster(i = 0) { serveAsSlave(ws); }).catch(error => { console.log(`Node(${floID}) is offline`); - connectToMaster(i + 1) + connectToMaster(i + 1, init) }); } //Node becomes master -function serveAsMaster() { - app.resume(); +function serveAsMaster(init) { + console.debug('Starting master process'); slave.stop(); mod = MASTER_MODE; - informLiveNodes(); - collectShares.active = true; + informLiveNodes(init); + app.resume(); } function serveAsSlave(ws) { + console.debug('Starting slave process'); app.pause(); slave.start(ws); mod = SLAVE_MODE; } -function informLiveNodes() { +function informLiveNodes(init) { let message = { floID: global.myFloID, type: "UPDATE_MASTER", @@ -261,12 +264,34 @@ function informLiveNodes() { }; message.sign = floCrypto.signData(message.type + "|" + message.req_time, global.myPrivKey); message = JSON.stringify(message); - for (let n in nodeURL) - if (n !== global.myFloID) - connectWS(n).then(ws => { + let nodes = nodeList.filter(n => n !== global.myFloID); + Promise.allSettled(nodes.map(n => connectWS(n))).then(result => { + let flag = false; + for (let i in result) + if (result[i].status === "fulfilled") { + let ws = result[i].value; ws.send(message); ws.close(); - }).catch(error => console.warn(`Node ${n} is offline`)); + flag = true; + } else + console.warn(`Node(${nodes[i]}) is offline`); + if (init) { + if (flag === true) + collectShares.active = true; + else { + //No other node is active (possible 1st node to start exchange) + console.debug("Starting the exchange...") + let newSink = generateNewSink(); + storeSink(newSink.floID, newSink.privKey); + sendSharesToNodes(newSink.floID, newSink.shares); + } + } else { + collectShares.active = true; + DB.query("SELECT floID, share FROM sinkShares ORDER BY time_ DESC LIMIT 1") + .then(result => collectShares(global.myFloID, result[0].floID, result[0].share)) + .catch(error => console.error(error)) + } + }); } function updateMaster(floID) { @@ -343,7 +368,7 @@ function startBackupTransmitter(server) { function initProcess(a) { app = a; startBackupTransmitter(app.server); - connectToMaster(); + connectToMaster(0, true); } module.exports = { @@ -352,6 +377,7 @@ module.exports = { nodeURL = list; nodeKBucket = new K_Bucket(floGlobals.adminID, Object.keys(nodeURL)); nodeList = nodeKBucket.order; + console.debug(nodeList); }, set DB(db) { DB = db; diff --git a/src/main.js b/src/main.js index 2c91482..42a2b73 100644 --- a/src/main.js +++ b/src/main.js @@ -1,5 +1,4 @@ 'use strict'; -const config = require('../args/app-config.json'); global.floGlobals = require('../public/floGlobals'); require('./set_globals'); require('./lib'); @@ -9,7 +8,6 @@ require('./tokenAPI'); const Database = require("./database"); const App = require('./app'); -const PORT = config['port']; const backup = require('./backup/head'); @@ -47,7 +45,7 @@ function refreshDataFromBlockchain() { promises.push(DB.query("DELETE FROM nodeList WHERE floID=?", [n])); if (content.Nodes.add) for (let n in content.Nodes.add) - promises.push(DB.query("INSERT INTO nodeList (floID, uri) VALUE (?,?) ON DUPLICATE KEY UPDATE uri=NEW.uri", [n, content.Nodes.add[n]])); + promises.push(DB.query("INSERT INTO nodeList (floID, uri) VALUE (?,?) AS new ON DUPLICATE KEY UPDATE uri=new.uri", [n, content.Nodes.add[n]])); } //Trusted List if (content.Trusted) { @@ -57,7 +55,7 @@ function refreshDataFromBlockchain() { promises.push(DB.query("DELETE FROM trustedList WHERE floID=?", [id])); if (content.Trusted.add) for (let id of content.Trusted.add) - promises.push(DB.query("INSERT INTO trustedList (floID) VALUE (?) ON DUPLICATE KEY UPDATE floID=NEW.floID", [id])); + promises.push(DB.query("INSERT INTO trustedList (floID) VALUE (?) AS new ON DUPLICATE KEY UPDATE floID=new.floID", [id])); } //Tag List with priority and API if (content.Tag) { @@ -66,16 +64,17 @@ function refreshDataFromBlockchain() { promises.push(DB.query("DELETE FROM TagList WHERE tag=?", [t])); if (content.Tag.add) for (let t in content.Tag.add) - promises.push(DB.query("INSERT INTO TagList (tag, sellPriority, buyPriority, api) VALUE (?,?,?,?)", [t, content.Tag.add[t].sellPriority, content.Tag.add[t].buyPriority, content.Tag.add[t].api])); + promises.push(DB.query("INSERT INTO TagList (tag, sellPriority, buyPriority, api) VALUE (?,?,?,?) AS new ON DUPLICATE KEY UPDATE tag=new.tag", [t, content.Tag.add[t].sellPriority, content.Tag.add[t].buyPriority, content.Tag.add[t].api])); if (content.Tag.update) for (let t in content.Tag.update) for (let a in content.Tag.update[t]) promises.push(`UPDATE TagList WHERE tag=? SET ${a}=?`, [t, content.Tag.update[t][a]]); } }); - promises.push(DB.query("INSERT INTO lastTx (floID, num) VALUE (?, ?) ON DUPLICATE KEY UPDATE num=NEW.num", [floGlobals.adminID, result.totalTxs])); + promises.push(DB.query("INSERT INTO lastTx (floID, num) VALUE (?, ?) AS new ON DUPLICATE KEY UPDATE num=new.num", [floGlobals.adminID, result.totalTxs])); //Check if all save process were successful Promise.allSettled(promises).then(results => { + console.debug(results.filter(r => r.status === "rejected")); if (results.reduce((a, r) => r.status === "rejected" ? ++a : a, 0)) console.warn("Some data might not have been saved in database correctly"); }); @@ -94,7 +93,7 @@ function loadDataFromDB(changes, startup) { if (startup || changes.nodes) promises.push(loadDataFromDB.nodeList()); if (startup || changes.trusted) - promises.push(loadDataFromDB.trustedIDs); + promises.push(loadDataFromDB.trustedIDs()); Promise.all(promises) .then(_ => resolve("Data load successful")) .catch(error => reject(error)) @@ -103,7 +102,7 @@ function loadDataFromDB(changes, startup) { loadDataFromDB.nodeList = function() { return new Promise((resolve, reject) => { - DB.query("SELECT (floID, uri) FROM nodeList").then(result => { + DB.query("SELECT * FROM nodeList").then(result => { let nodes = {} for (let i in result) nodes[result[i].floID] = result[i].uri; @@ -133,23 +132,20 @@ function setDB(db) { } module.exports = function startServer(public_dir) { + const config = require(`../args/config${process.env.I || ""}.json`); try { - var _tmp = require('../args/keys.json'); + var _tmp = require(`../args/keys${process.env.I || ""}.json`); _tmp = floCrypto.retrieveShamirSecret(_tmp); var _pass = process.env.PASSWORD; if (!_pass) { console.error('Password not entered!'); process.exit(1); } - _tmp = Crypto.AES.decrypt(_tmp, _pass); - if (floCrypto.verifyPrivKey(_tmp, floGlobals.adminID)) { - global.myPrivKey = _tmp; - global.myPubKey = floCrypto.getPubKeyHex(global.myPrivKey); - global.myFloID = floCrypto.getFloID(global.myPubKey); - } else { - console.error('Loaded wrong private key!'); - process.exit(1); - } + global.myPrivKey = Crypto.AES.decrypt(_tmp, _pass); + global.myPubKey = floCrypto.getPubKeyHex(global.myPrivKey); + global.myFloID = floCrypto.getFloID(global.myPubKey); + if (!global.myFloID || !global.myPubKey || !global.myPrivKey) + throw "Invalid Keys"; } catch (error) { console.error('Unable to load private key!'); process.exit(1); @@ -162,7 +158,7 @@ module.exports = function startServer(public_dir) { setDB(db); app = new App(config['secret'], DB); refreshData(true).then(_ => { - app.start(PORT).then(result => { + app.start(config['port']).then(result => { console.log(result); backup.init(app); }).catch(error => console.error(error)) diff --git a/src/request.js b/src/request.js index 8d51727..5fcc6f8 100644 --- a/src/request.js +++ b/src/request.js @@ -29,12 +29,12 @@ function validateRequestFromFloID(request, sign, floID, proxy = true) { if (!serving) return reject(INVALID(INVALID_SERVER_MSG)); else if (!floCrypto.validateAddr(floID)) - return res.status(INVALID.e_code).send("Invalid floID"); + return reject(INVALID.e_code).send("Invalid floID"); DB.query("SELECT " + (proxy ? "session_time, proxyKey AS pubKey FROM Sessions" : "pubKey FROM Users") + " WHERE floID=?", [floID]).then(result => { if (result.length < 1) return reject(INVALID(proxy ? "Session not active" : "User not registered")); if (proxy && result[0].session_time + maxSessionTimeout < Date.now()) - return res.status(INVALID.e_code).send("Session Expired! Re-login required"); + return reject(INVALID.e_code).send("Session Expired! Re-login required"); let req_str = validateRequest(request, sign, result[0].pubKey); req_str instanceof INVALID ? reject(req_str) : resolve(req_str); }).catch(error => reject(error)); @@ -64,7 +64,7 @@ function storeRequest(floID, req_str, sign) { function getLoginCode(req, res) { let randID = floCrypto.randString(8, true) + Math.round(Date.now() / 1000); let hash = Crypto.SHA1(randID + secret); - res.status(INVALID.e_code).send({ + res.send({ code: randID, hash: hash }); @@ -111,9 +111,9 @@ function Login(req, res) { proxyKey: data.proxyKey, timestamp: data.timestamp }, data.sign, data.floID, false).then(req_str => { - DB.query("INSERT INTO Sessions (floID, proxyKey) VALUES (?, ?, ?) " + - "ON DUPLICATE KEY UPDATE session_time=DEFAULT, proxyKey=?", - [data.floID, data.code, data.proxyKey, data.code, data.proxyKey]).then(_ => { + DB.query("INSERT INTO Sessions (floID, proxyKey) VALUE (?, ?) AS new " + + "ON DUPLICATE KEY UPDATE session_time=DEFAULT, proxyKey=new.proxyKey", + [data.floID, data.proxyKey]).then(_ => { storeRequest(data.floID, req_str, data.sign); res.send("Login Successful"); }).catch(error => { @@ -131,6 +131,7 @@ function Login(req, res) { } function Logout(req, res) { + let data = req.body; validateRequestFromFloID({ type: "logout", timestamp: data.timestamp