Removing need for user registration

- Users can directly login or request without the need for user registration.
- Users can sign the requests either directly with own privateKey or by using a proxy
- Request's timestamp will be checked for Sign expiry.
- Request's sign will be checked for duplication.
- Cash table update will try to insert if record is not there
- Request Log table will also store a boolean value for sign by proxy or not
- Updated the SQL schema for the above changes.
This commit is contained in:
sairajzero 2022-03-15 04:06:43 +05:30
parent 3296b16710
commit f59c6b3f2a
9 changed files with 177 additions and 161 deletions

View File

@ -33,31 +33,21 @@ CREATE TABLE TrustedList(
/* User Data */
CREATE TABLE Users (
id INT NOT NULL AUTO_INCREMENT,
floID CHAR(34) NOT NULL,
pubKey CHAR(66) NOT NULL,
created DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY(id),
PRIMARY KEY(floID)
);
CREATE TABLE UserSession (
id INT NOT NULL AUTO_INCREMENT,
floID CHAR(34) NOT NULL,
proxyKey CHAR(66) NOT NULL,
session_time DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY (id),
PRIMARY KEY(floID),
FOREIGN KEY (floID) REFERENCES Users(floID)
PRIMARY KEY(floID)
);
CREATE TABLE Cash (
id INT NOT NULL AUTO_INCREMENT,
floID CHAR(34) NOT NULL UNIQUE,
balance DECIMAL(12, 2) DEFAULT 0.00,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID)
KEY(id),
PRIMARY KEY(floID)
);
CREATE TABLE Vault (
@ -68,7 +58,6 @@ CREATE TABLE Vault (
base DECIMAL(10, 2),
quantity FLOAT NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID),
FOREIGN KEY (asset) REFERENCES AssetList(asset)
);
@ -78,7 +67,6 @@ CREATE TABLE UserTag (
tag VARCHAR(50) NOT NULL,
PRIMARY KEY(floID, tag),
KEY (id),
FOREIGN KEY (floID) REFERENCES Users(floID),
FOREIGN KEY (tag) REFERENCES TagList(tag)
);
@ -89,9 +77,10 @@ CREATE TABLE RequestLog(
floID CHAR(34) NOT NULL,
request TEXT NOT NULL,
sign TEXT NOT NULL,
proxy BOOLEAN NOT NULL,
request_time DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID)
UNIQUE (sign)
);
CREATE TABLE SellOrder (
@ -102,7 +91,6 @@ CREATE TABLE SellOrder (
minPrice DECIMAL(10, 2) NOT NULL,
time_placed DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID),
FOREIGN KEY (asset) REFERENCES AssetList(asset)
);
@ -114,7 +102,6 @@ CREATE TABLE BuyOrder (
maxPrice DECIMAL(10, 2) NOT NULL,
time_placed DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID),
FOREIGN KEY (asset) REFERENCES AssetList(asset)
);
@ -124,8 +111,7 @@ CREATE TABLE InputFLO (
floID CHAR(34) NOT NULL,
amount FLOAT,
status VARCHAR(50) NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID)
PRIMARY KEY(id)
);
CREATE TABLE OutputFLO (
@ -134,8 +120,7 @@ CREATE TABLE OutputFLO (
floID CHAR(34) NOT NULL,
amount FLOAT NOT NULL,
status VARCHAR(50) NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID)
PRIMARY KEY(id)
);
CREATE TABLE InputToken (
@ -145,8 +130,7 @@ CREATE TABLE InputToken (
token VARCHAR(64),
amount FLOAT,
status VARCHAR(50) NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID)
PRIMARY KEY(id)
);
CREATE TABLE OutputToken (
@ -156,8 +140,7 @@ CREATE TABLE OutputToken (
token VARCHAR(64),
amount FLOAT NOT NULL,
status VARCHAR(50) NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY (floID) REFERENCES Users(floID)
PRIMARY KEY(id)
);
/* Transaction Data */
@ -180,9 +163,7 @@ CREATE TABLE TransferTransactions (
tx_time DATETIME DEFAULT CURRENT_TIMESTAMP,
txid VARCHAR(66) NOT NULL,
KEY(id),
PRIMARY KEY(txid),
FOREIGN KEY (sender) REFERENCES Users(floID),
FOREIGN KEY (receiver) REFERENCES Users(floID)
PRIMARY KEY(txid)
);
CREATE TABLE TradeTransactions (
@ -196,8 +177,6 @@ CREATE TABLE TradeTransactions (
txid VARCHAR(66) NOT NULL,
KEY(id),
PRIMARY KEY(txid),
FOREIGN KEY (buyer) REFERENCES Users(floID),
FOREIGN KEY (seller) REFERENCES Users(floID),
FOREIGN KEY (asset) REFERENCES AssetList(asset)
);
@ -219,8 +198,6 @@ CREATE TABLE AuditTrade(
buyer_old_cash FLOAT NOT NULL,
buyer_new_cash FLOAT NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY (sellerID) REFERENCES Users(floID),
FOREIGN KEY (buyerID) REFERENCES Users(floID),
FOREIGN KEY (asset) REFERENCES AssetList(asset)
);
@ -249,13 +226,6 @@ CREATE TABLE sinkShares(
PRIMARY KEY(floID)
);
CREATE TRIGGER Users_I AFTER INSERT ON Users
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Users', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
CREATE TRIGGER Users_U AFTER UPDATE ON Users
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Users', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
CREATE TRIGGER Users_D AFTER DELETE ON Users
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Users', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
CREATE TRIGGER RequestLog_I AFTER INSERT ON RequestLog
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('RequestLog', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
CREATE TRIGGER RequestLog_U AFTER UPDATE ON RequestLog

View File

@ -15,7 +15,6 @@ TRUNCATE UserTag;
TRUNCATE TransferTransactions;
TRUNCATE TradeTransactions;
TRUNCATE Vault;
DELETE FROM Users;
/* Blockchain data */
TRUNCATE LastTx;

View File

@ -102,6 +102,8 @@ function getAccount(floID, proxySecret) {
floID: floID,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "get_account",
timestamp: request.timestamp
@ -173,11 +175,11 @@ function getTx(txid) {
})
}
function signRequest(request, privKey) {
function signRequest(request, signKey) {
if (typeof request !== "object")
throw Error("Request is not an object");
let req_str = Object.keys(request).sort().map(r => r + ":" + request[r]).join("|");
return floCrypto.signData(req_str, privKey);
return floCrypto.signData(req_str, signKey);
}
function getLoginCode() {
@ -190,6 +192,7 @@ function getLoginCode() {
})
}
/*
function signUp(privKey, code, hash) {
return new Promise((resolve, reject) => {
if (!code || !hash)
@ -220,6 +223,7 @@ function signUp(privKey, code, hash) {
.catch(error => reject(error));
});
}
*/
function login(privKey, proxyKey, code, hash) {
return new Promise((resolve, reject) => {
@ -228,6 +232,7 @@ function login(privKey, proxyKey, code, hash) {
let request = {
proxyKey: proxyKey,
floID: floCrypto.getFloID(privKey),
pubKey: floCrypto.getPubKeyHex(privKey),
timestamp: Date.now(),
code: code,
hash: hash
@ -261,6 +266,8 @@ function logout(floID, proxySecret) {
floID: floID,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "logout",
timestamp: request.timestamp
@ -293,6 +300,8 @@ function buy(asset, quantity, max_price, floID, proxySecret) {
max_price: max_price,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "buy_order",
asset: asset,
@ -329,6 +338,8 @@ function sell(asset, quantity, min_price, floID, proxySecret) {
min_price: min_price,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "sell_order",
quantity: quantity,
@ -362,6 +373,8 @@ function cancelOrder(type, id, floID, proxySecret) {
orderID: id,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "cancel_order",
order: type,
@ -396,6 +409,8 @@ function transferToken(receiver, token, amount, floID, proxySecret) {
amount: amount,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "transfer_token",
receiver: receiver,
@ -418,7 +433,7 @@ function transferToken(receiver, token, amount, floID, proxySecret) {
})
}
function depositFLO(quantity, floID, sinkID, privKey, proxySecret) {
function depositFLO(quantity, floID, sinkID, privKey, proxySecret = null) {
return new Promise((resolve, reject) => {
if (typeof quantity !== "number" || quantity <= floGlobals.fee)
return reject(`Invalid quantity (${quantity})`);
@ -428,11 +443,13 @@ function depositFLO(quantity, floID, sinkID, privKey, proxySecret) {
txid: txid,
timestamp: Date.now()
};
if (!proxySecret) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(privKey);
request.sign = signRequest({
type: "deposit_flo",
txid: txid,
timestamp: request.timestamp
}, proxySecret);
}, proxySecret || privKey);
console.debug(request);
exchangeAPI('/deposit-flo', {
@ -456,6 +473,8 @@ function withdrawFLO(quantity, floID, proxySecret) {
amount: quantity,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "withdraw_flo",
amount: quantity,
@ -476,7 +495,7 @@ function withdrawFLO(quantity, floID, proxySecret) {
})
}
function depositToken(token, quantity, floID, sinkID, privKey, proxySecret) {
function depositToken(token, quantity, floID, sinkID, privKey, proxySecret = null) {
return new Promise((resolve, reject) => {
if (!floCrypto.verifyPrivKey(privKey, floID))
return reject("Invalid Private Key");
@ -486,11 +505,13 @@ function depositToken(token, quantity, floID, sinkID, privKey, proxySecret) {
txid: txid,
timestamp: Date.now()
};
if (!proxySecret) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(privKey);
request.sign = signRequest({
type: "deposit_token",
txid: txid,
timestamp: request.timestamp
}, proxySecret);
}, proxySecret || privKey);
console.debug(request);
exchangeAPI('/deposit-token', {
@ -515,6 +536,8 @@ function withdrawToken(token, quantity, floID, proxySecret) {
amount: quantity,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "withdraw_token",
token: token,
@ -544,6 +567,8 @@ function addUserTag(tag_user, tag, floID, proxySecret) {
tag: tag,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "add_tag",
user: tag_user,
@ -573,6 +598,8 @@ function removeUserTag(tag_user, tag, floID, proxySecret) {
tag: tag,
timestamp: Date.now()
};
if (floCrypto.getFloID(proxySecret) === floID) //Direct signing (without proxy)
request.pubKey = floCrypto.getPubKeyHex(proxySecret);
request.sign = signRequest({
type: "remove_tag",
user: tag_user,

View File

@ -4,7 +4,8 @@ module.exports = {
PERIOD_INTERVAL: 15 * 60 * 1000 // 15 min
},
request: {
MAX_SESSION_TIMEOUT: 60 * 24 * 60 * 60 * 1000, //60 days
SIGN_EXPIRE_TIME: 1 * 60 * 1000, //1 min
MAX_SESSION_TIMEOUT: 30 * 24 * 60 * 60 * 1000, //30 days
INVALID_SERVER_MSG: "INCORRECT_SERVER_ERROR" //Should be reflected in public backend script
},
market: {

View File

@ -53,7 +53,7 @@ module.exports = function App(secret, DB) {
app.get('/get-login-code', Request.getLoginCode);
//signup request
app.post('/signup', Request.SignUp);
//app.post('/signup', Request.SignUp); Removing need for signup
//login request
app.post('/login', Request.Login);

View File

@ -112,7 +112,7 @@ function processOrders(seller_best, buyer_best, txQueries, quantity, clear_sell)
function updateBalance(seller_best, buyer_best, txQueries, asset, cur_price, quantity) {
//Update cash balance for seller and buyer
let totalAmount = cur_price * quantity;
txQueries.push(["UPDATE Cash SET balance=balance+? WHERE floID=?", [totalAmount, seller_best.floID]]);
txQueries.push(["INSERT INTO Cash (floID, balance) VALUE (?, ?) ON DUPLICATE KEY UPDATE balance=balance+?", [seller_best.floID, totalAmount, totalAmount]]);
txQueries.push(["UPDATE Cash SET balance=balance-? WHERE floID=?", [totalAmount, buyer_best.floID]]);
//Add coins to Buyer
txQueries.push(["INSERT INTO Vault(floID, asset, base, quantity) VALUES (?, ?, ?, ?)", [buyer_best.floID, asset, cur_price, quantity]])
@ -158,6 +158,11 @@ function auditBalance(sellerID, buyerID, asset) {
DB.query("SELECT floID, SUM(quantity) as asset_balance FROM Vault WHERE asset=? AND floID IN (?, ?) GROUP BY floID", [asset, sellerID, buyerID]).then(result => {
for (let i in result)
balance[result[i].floID].asset = result[i].asset_balance;
//Set them as 0 if undefined or null
balance[sellerID].cash = balance[sellerID].cash || 0;
balance[sellerID].asset = balance[sellerID].asset || 0;
balance[buyerID].cash = balance[buyerID].cash || 0;
balance[buyerID].asset = balance[buyerID].asset || 0;
resolve(balance);
}).catch(error => reject(error))
}).catch(error => reject(error))

View File

@ -364,8 +364,8 @@ function getTopValidBuyOrder(orders, cur_price) {
function verifyBuyOrder(buyOrder, cur_price) {
return new Promise((resolve, reject) => {
DB.query("SELECT balance AS bal FROM Cash WHERE floID=?", [buyOrder.floID]).then(result => {
if (result[0].bal < cur_price * buyOrder.quantity) {
DB.query("SELECT balance FROM Cash WHERE floID=?", [buyOrder.floID]).then(result => {
if (!result.length || result[0].balance < cur_price * buyOrder.quantity) {
//This should not happen unless a buy order is placed when user doesnt have enough cash balance
console.warn(`Buy order ${buyOrder.id} is active, but Cash is insufficient`);
reject(false);

View File

@ -10,18 +10,9 @@ const {
var DB, assetList; //container for database and allowed assets
const checkIfUserRegistered = floID => new Promise((resolve, reject) => {
DB.query("SELECT id FROM Users WHERE floID=?", [floID]).then(result => {
if (result.length)
resolve(result[0].id);
else
reject(INVALID(`User ${floID} not registered`));
}).catch(error => reject(error));
});
const getAssetBalance = (floID, asset) => new Promise((resolve, reject) => {
let promises = (asset === floGlobals.currency) ? [
DB.query("SELECT balance FROM Cash WHERE floID=?", [floID]),
DB.query("SELECT SUM(balance) AS balance FROM Cash WHERE floID=?", [floID]),
DB.query("SELECT SUM(quantity*maxPrice) AS locked FROM BuyOrder WHERE floID=?", [floID])
] : [
DB.query("SELECT SUM(quantity) AS balance FROM Vault WHERE floID=? AND asset=?", [floID, asset]),
@ -164,7 +155,7 @@ function getAccountDetails(floID) {
else
switch (i) {
case 0:
response.cash = a.value[0].balance;
response.cash = a.value.length ? a.value[0].balance : 0;
break;
case 1:
response.vault = a.value;
@ -216,22 +207,20 @@ function transferToken(sender, receiver, token, amount) {
else if (token !== floGlobals.currency && !assetList.includes(token))
return reject(INVALID(`Invalid token (${token})`));
getAssetBalance.check(senderID, token, amount).then(_ => {
checkIfUserRegistered(receiver).then(_ => {
consumeAsset(sender, token, amount).then(txQueries => {
if (token === floGlobals.currency)
txQueries.push(["UPDATE Cash SET balance=balance+? WHERE floID=?", [amount, receiver]]);
else
txQueries.push(["INSERT INTO Vault(floID, quantity) VALUES (?, ?)", [receiver, amount]]);
let time = Date.now();
let hash = TRANSFER_HASH_PREFIX + Crypto.SHA256([time, sender, receiver, token, amount].join("|"));
txQueries.push([
"INSERT INTO TransferTransactions (sender, receiver, token, amount, tx_time, txid)",
[sender, receiver, token, amount, global.convertDateToString(time), hash]
]);
DB.transaction(txQueries)
.then(result => resolve(hash))
.catch(error => reject(error))
}).catch(error => reject(error))
consumeAsset(sender, token, amount).then(txQueries => {
if (token === floGlobals.currency)
txQueries.push(["INSERT INTO Cash (floID, balance) VALUE (?, ?) ON DUPLICATE KEY UPDATE balance=balance+?", [receiver, amount, amount]]);
else
txQueries.push(["INSERT INTO Vault(floID, quantity) VALUES (?, ?)", [receiver, amount]]);
let time = Date.now();
let hash = TRANSFER_HASH_PREFIX + Crypto.SHA256([time, sender, receiver, token, amount].join("|"));
txQueries.push([
"INSERT INTO TransferTransactions (sender, receiver, token, amount, tx_time, txid)",
[sender, receiver, token, amount, global.convertDateToString(time), hash]
]);
DB.transaction(txQueries)
.then(result => resolve(hash))
.catch(error => reject(error))
}).catch(error => reject(error))
}).catch(error => reject(error))
})
@ -392,7 +381,7 @@ function confirmDepositToken() {
}
txQueries.push(["UPDATE InputToken SET status=?, token=?, amount=? WHERE id=?", ["SUCCESS", token_name, amount_token, req.id]]);
if (token_name === floGlobals.currency)
txQueries.push(["UPDATE Cash SET balance=balance+? WHERE floID=?", [amount_token, req.floID]]);
txQueries.push(["INSERT INTO Cash (floID, balance) VALUE (?, ?) ON DUPLICATE KEY UPDATE balance=balance+?", [req.floID, amount_token, amount_token]]);
else
txQueries.push(["INSERT INTO Vault(floID, asset, quantity) VALUES (?, ?, ?)", [req.floID, token_name, amount_token]]);
DB.transaction(txQueries)

View File

@ -3,6 +3,7 @@
const market = require("./market");
const {
SIGN_EXPIRE_TIME,
MAX_SESSION_TIMEOUT,
INVALID_SERVER_MSG
} = require("./_constants")["request"];
@ -25,40 +26,61 @@ INTERNAL.e_code = 500;
var serving;
function validateRequestFromFloID(request, sign, floID, proxy = true) {
function validateRequest(request, sign, floID, pubKey) {
return new Promise((resolve, reject) => {
if (!serving)
return reject(INVALID(INVALID_SERVER_MSG));
reject(INVALID(INVALID_SERVER_MSG));
else if (!request.timestamp)
reject(INVALID("Timestamp parameter missing"));
else if (Date.now() - SIGN_EXPIRE_TIME > request.timestamp)
reject(INVALID("Signature Expired"));
else if (!floCrypto.validateAddr(floID))
return reject(INVALID("Invalid floID"));
DB.query("SELECT " + (proxy ? "session_time, proxyKey AS pubKey FROM UserSession" : "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 + MAX_SESSION_TIMEOUT < Date.now())
return reject(INVALID("Session Expired! Re-login required"));
let req_str = validateRequest(request, sign, result[0].pubKey);
req_str instanceof INVALID ? reject(req_str) : resolve(req_str);
reject(INVALID("Invalid floID"));
else if (typeof request !== "object")
reject(INVALID("Request is not an object"));
else validateRequest.getSignKey(floID, pubKey).then(signKey => {
let req_str = Object.keys(request).sort().map(r => r + ":" + request[r]).join("|");
try {
if (!floCrypto.verifySign(req_str, sign, signKey))
reject(INVALID("Invalid request signature! Re-login if this error occurs frequently"));
else validateRequest.checkIfSignUsed(sign)
.then(result => resolve(req_str))
.catch(error => reject(error))
} catch {
reject(INVALID("Corrupted sign/key"));
}
}).catch(error => reject(error));
});
}
function validateRequest(request, sign, pubKey) {
if (typeof request !== "object")
return INVALID("Request is not an object");
let req_str = Object.keys(request).sort().map(r => r + ":" + request[r]).join("|");
try {
if (floCrypto.verifySign(req_str, sign, pubKey))
return req_str;
else
return INVALID("Invalid request signature! Re-login if this error occurs frequently");
} catch {
return INVALID("Corrupted sign/key");
}
}
validateRequest.getSignKey = (floID, pubKey) => new Promise((resolve, reject) => {
if (!pubKey)
DB.query("SELECT session_time, proxyKey FROM UserSession WHERE floID=?", [floID]).then(result => {
if (result.length < 1)
reject(INVALID("Session not active"));
else if (proxy && result[0].session_time + MAX_SESSION_TIMEOUT < Date.now())
reject(INVALID("Session Expired! Re-login required"));
else
resolve(result[0].proxyKey);
}).catch(error => reject(error));
else if (floCrypto.getFloID(pubKey) === floID)
resolve(pubKey);
else
reject(INVALID("Invalid pubKey"));
});
function storeRequest(floID, req_str, sign) {
validateRequest.checkIfSignUsed = sign => new Promise((resolve, reject) => {
DB.query("SELECT id FROM RequestLog WHERE sign=?", [sign]).then(result => {
if (result.length)
reject(INVALID("Duplicate signature"));
else
resolve(true);
}).catch(error => reject(error))
});
function storeRequest(floID, req_str, sign, proxy = false) {
//console.debug(floID, req_str);
DB.query("INSERT INTO RequestLog (floID, request, sign) VALUES (?,?,?)", [floID, req_str, sign])
DB.query("INSERT INTO RequestLog (floID, request, sign, proxy) VALUES (?,?,?, ?)", [floID, req_str, sign, proxy])
.then(_ => null).catch(error => console.error(error));
}
@ -73,6 +95,7 @@ function getLoginCode(req, res) {
});
}
/*
function SignUp(req, res) {
if (!serving)
return res.status(INVALID.e_code).send(INVALID_SERVER_MSG);
@ -81,7 +104,7 @@ function SignUp(req, res) {
return res.status(INVALID.e_code).send("Invalid Public Key");
if (!data.code || data.hash != Crypto.SHA1(data.code + secret))
return res.status(INVALID.e_code).send("Invalid Code");
let req_str = validateRequest({
let req_str = validateRequest_X({
type: "create_account",
random: data.code,
timestamp: data.timestamp
@ -103,17 +126,20 @@ function SignUp(req, res) {
}
});
}
*/
function Login(req, res) {
let data = req.body;
if (!data.code || data.hash != Crypto.SHA1(data.code + secret))
return res.status(INVALID.e_code).send("Invalid Code");
validateRequestFromFloID({
if (!data.pubKey)
return res.status(INVALID.e_code).send("Public key missing");
validateRequest({
type: "login",
random: data.code,
proxyKey: data.proxyKey,
timestamp: data.timestamp
}, data.sign, data.floID, false).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
DB.query("INSERT INTO UserSession (floID, proxyKey) VALUE (?, ?) " +
"ON DUPLICATE KEY UPDATE session_time=DEFAULT, proxyKey=?",
[data.floID, data.proxyKey, data.proxyKey]).then(_ => {
@ -135,12 +161,12 @@ function Login(req, res) {
function Logout(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "logout",
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
DB.query("DELETE FROM UserSession WHERE floID=?", [data.floID]).then(_ => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send('Logout successful');
}).catch(error => {
console.error(error);
@ -158,15 +184,15 @@ function Logout(req, res) {
function PlaceSellOrder(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "sell_order",
asset: data.asset,
quantity: data.quantity,
min_price: data.min_price,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.addSellOrder(data.floID, data.asset, data.quantity, data.min_price).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -188,15 +214,15 @@ function PlaceSellOrder(req, res) {
function PlaceBuyOrder(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "buy_order",
asset: data.asset,
quantity: data.quantity,
max_price: data.max_price,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.addBuyOrder(data.floID, data.asset, data.quantity, data.max_price).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -218,14 +244,14 @@ function PlaceBuyOrder(req, res) {
function CancelOrder(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "cancel_order",
order: data.orderType,
id: data.orderID,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.cancelOrder(data.orderType, data.orderID, data.floID).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -247,15 +273,15 @@ function CancelOrder(req, res) {
function TransferToken(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "transfer_token",
receiver: data.receiver,
token: data.token,
amount: data.amount,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.transferToken(data.floID, data.receiver, data.token, data.amount).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -335,10 +361,10 @@ function getTransaction(req, res) {
function Account(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "get_account",
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.getAccountDetails(data.floID).then(result => {
result.sinkID = global.sinkID;
if (trustedIDs.includes(data.floID))
@ -357,13 +383,13 @@ function Account(req, res) {
function DepositFLO(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "deposit_flo",
txid: data.txid,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.depositFLO(data.floID, data.txid).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -385,13 +411,13 @@ function DepositFLO(req, res) {
function WithdrawFLO(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "withdraw_flo",
amount: data.amount,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.withdrawFLO(data.floID, data.amount).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -413,13 +439,13 @@ function WithdrawFLO(req, res) {
function DepositToken(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "deposit_token",
txid: data.txid,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.depositToken(data.floID, data.txid).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -441,14 +467,14 @@ function DepositToken(req, res) {
function WithdrawToken(req, res) {
let data = req.body;
validateRequestFromFloID({
validateRequest({
type: "withdraw_token",
token: data.token,
amount: data.amount,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.withdrawToken(data.floID, data.token, data.amount).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -471,15 +497,15 @@ function WithdrawToken(req, res) {
function addUserTag(req, res) {
let data = req.body;
if (!trustedIDs.includes(data.floID))
return res.status(INVALID.e_code).send("Access Denied");
validateRequestFromFloID({
res.status(INVALID.e_code).send("Access Denied");
else validateRequest({
type: "add_tag",
user: data.user,
tag: data.tag,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.group.addTag(data.user, data.tag).then(result => {
storeRequest(data.floID, req_str, data.sign);
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
@ -502,25 +528,16 @@ function addUserTag(req, res) {
function removeUserTag(req, res) {
let data = req.body;
if (!trustedIDs.includes(data.floID))
return res.status(INVALID.e_code).send("Access Denied");
else
validateRequestFromFloID({
type: "remove_tag",
user: data.user,
tag: data.tag,
timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => {
market.group.removeTag(data.user, data.tag).then(result => {
storeRequest(data.floID, req_str, data.sign);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
res.status(INVALID.e_code).send(error.message);
else {
console.error(error);
res.status(INTERNAL.e_code).send("Request processing failed! Try again later!");
}
});
res.status(INVALID.e_code).send("Access Denied");
else validateRequest({
type: "remove_tag",
user: data.user,
tag: data.tag,
timestamp: data.timestamp
}, data.sign, data.floID, data.pubKey).then(req_str => {
market.group.removeTag(data.user, data.tag).then(result => {
storeRequest(data.floID, req_str, data.sign, !data.pubKey);
res.send(result);
}).catch(error => {
if (error instanceof INVALID)
res.status(INVALID.e_code).send(error.message);
@ -529,11 +546,19 @@ function removeUserTag(req, res) {
res.status(INTERNAL.e_code).send("Request processing failed! Try again later!");
}
});
}).catch(error => {
if (error instanceof INVALID)
res.status(INVALID.e_code).send(error.message);
else {
console.error(error);
res.status(INTERNAL.e_code).send("Request processing failed! Try again later!");
}
});
}
module.exports = {
getLoginCode,
SignUp,
//SignUp,
Login,
Logout,
PlaceBuyOrder,