Skip to content

Commit

Permalink
Improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
mahdiyari committed Jul 11, 2018
1 parent deaffc5 commit 7c59954
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 183 deletions.
41 changes: 32 additions & 9 deletions conf/mysql/index.js
@@ -1,14 +1,37 @@
// MySQL connection
// creating a MySQL pool which will handle up to 1,000 connections
// connections more than 1,000 will be added to the queue
const mysql = require('mysql')
// import config file
const config = require('../../config')
var con = mysql.createConnection({
host: config.db.host, // MySQL host
user: config.db.user, // MySQL username
password: config.db.pw, // MySQL password
database: config.db.name, // MySQL database
charset: 'utf8mb4' // MySQL charset (fix possible charset errors)
// changed from connection to the pool
const pool = mysql.createPool({
connectionLimit: 1000,
host: config.db.host,
user: config.db.user,
password: config.db.pw,
database: config.db.name,
charset: 'utf8mb4'
})

// export con to import in the other files
// Rewriting MySQL query method as a promise
const con = {}
con.query = async (query, val) => {
if (val) {
let qu = await new Promise((resolve, reject) => {
pool.query(query, val, (error, results) => {
if (error) reject(new Error(error))
resolve(results)
})
})
return qu
} else {
let qu = await new Promise((resolve, reject) => {
pool.query(query, (error, results) => {
if (error) reject(new Error(error))
resolve(results)
})
})
return qu
}
}

module.exports = con
4 changes: 2 additions & 2 deletions config.js
Expand Up @@ -15,9 +15,9 @@ config.sc2.callbackURL = 'https://dblog.io' // callback url
config.sc2.scope = ['login'] // scopes
// RPC nodes
// main RPC node (websocket)
config.rpc = 'ws://rpc.buildteam.io:8090'
config.rpc = 'ws://rpc2.steemviz.com:8090'
// RPC node (http)
config.rpchttp = 'http://rpc.buildteam.io:8090'
config.rpchttp = 'http://rpc2.steemviz.com:8090'

// export config to use in the other files
module.exports = config
294 changes: 122 additions & 172 deletions login_apis/confirm_process.js
Expand Up @@ -6,210 +6,160 @@ const con = require('../conf/mysql')
const crypto = require('crypto')

// Process post requests
// This will receive user's id, name, access_token and optional hash_key
// Purpose of this API is to assign a 'hash_key' to each user
// And return hash_key of each logged users
// hash_key is a random generated hex string
router.post('/', (req, res) => {
res.set('Content-Type', 'application/json') // JSON header
if (req.body.access_token && req.body.username && req.body.uid) {
const accessToken = req.body.access_token
api.setAccessToken(accessToken) // set access_token to steemconnect
const uid = req.body.uid // user id in blockchain
const username = req.body.username
if (req.body.hash_key) {
// skip if there was already correct hash_key
const hashKey = req.body.hash_key
CheckHash(hashKey, uid, username, res)
} else { // User don't have hash_key
con.query(
'SELECT EXISTS(SELECT `username` FROM `users` WHERE `uid`=?)',
[uid],
(error, results) => setOrGetHashKey({ uid, username, res, error, results })
)
res.set('Content-Type', 'application/json')
try {
if (req.body.access_token && req.body.username && req.body.uid) {
const accessToken = req.body.access_token
// set access_token to steemconnect
api.setAccessToken(accessToken)
// user id in the blockchain
const uid = req.body.uid
const username = req.body.username
if (req.body.hash_key) {
// skip if there was already correct hash_key
const hashKey = req.body.hash_key
CheckHash(hashKey, uid, username)
.then(hash => {
res.status(200).json({
hash_key: hash,
username,
uid
})
})
.catch(err => {
res.status(400).json({
error: 1,
message: err
})
})
} else {
// User don't sent a hash_key
// We will verify user login details then return a hash_key
con.query('SELECT EXISTS(SELECT `username` FROM `users` WHERE `uid`=?)', [uid])
.then(results => setOrGetHashKey({ uid, username, results }))
.then(hash => {
res.status(200).json({
hash_key: hash,
username,
uid
})
})
}
} else {
// User is not authorized
res.status(401).end()
}
} else {
// Unauthorized
res.status(401).end()
} catch (err) {
res.status(400).json({
error: 1,
message: err
})
}
})
const setOrGetHashKey = ({ res, uid, username, error, results }) => {
console.log(error)
if (!error) {
const exists = results[0][0]
console.log('exists = ' + exists)
if (exists) { // Get hash_key from database
RetrieveHash(uid, username, res)
} else { // Generate new hash_key
SetHash(uid, username, res)
}
const setOrGetHashKey = async ({ uid, username, results }) => {
let exists = results[0]
for (let i in exists) {
exists = exists[i]
}
if (exists) {
// User is in the database
// Get hash_key from database
let hash = await RetrieveHash(uid)
return hash
} else {
// Insert user to the database
// and Generate new hash_key
let hash = await SetHash(uid, username)
return hash
}
}

// Checking the hash_key which is sent by the user's cookies
// We will send this hash_key in the respond if it was correct
// This process will avoid calling to the steemconnect
/* checkHash Start */
const CheckHash = (hashKey, uid, username, res) => {
// let's check is this user already in the database?
con.query(
'SELECT EXISTS(SELECT `username` FROM `users` WHERE `uid`=?)',
[uid],
(error, results) => {
checkHashDbCheck({ res, hashKey, uid, username, error, results })
}
)
const CheckHash = async (hashKey, uid, username) => {
// let's check is this user already in the database or not
let results = await con.query('SELECT EXISTS(SELECT `username` FROM `users` WHERE `uid`=?)', [uid])
let hash = await checkHashDbCheck({ hashKey, uid, username, results })
return hash
}
const checkHashDbCheck = ({ res, hashKey, uid, username, error, results }) => {
if (!error) {
results = results[0]
let exists
for (let i in results) {
exists = results[i]
}
if (exists) {
// Username is already in the database
// We will compare received hash_key vs database
con.query(
'SELECT `hash_key` FROM `users` WHERE `uid`=?',
[uid],
(error, results) => {
checkHashRetrieve({ res, hashKey, username, uid, error, results })
}
)
} else {
// Username is not in the database
// but, user sent a hash_key
// set a new hash_key
SetHash(uid, username, res)
}
const checkHashDbCheck = async ({ hashKey, uid, username, results }) => {
results = results[0]
let exists
for (let i in results) {
exists = results[i]
}
}
// Get hash_key from database and compare
const checkHashRetrieve = ({ res, hashKey, username, uid, error, results }) => {
if (!error) {
const hash = results[0].hash_key
// provided hash_key is correct
if (hash === hashKey) {
// return hash_key
res.status(200).send(
JSON.stringify({
hash_key: hashKey,
username: username,
uid: uid
})
)
} else {
// provided hashKey is not correct
// return correct hashKey
RetrieveHash(uid, username, res)
if (exists) {
// Username is already in the database
// We will compare received hash_key vs database
let results = await con.query('SELECT `hash_key` FROM `users` WHERE `uid`=?', [uid])
if (results[0].hash_key === hashKey) return hashKey
else {
let hash = await RetrieveHash(uid)
return hash
}
} else {
// Username is not in the database
// but, user sent a hash_key
// set a new hash_key
let hash = await SetHash(uid, username)
return hash
}
}
/* CheckHash End */

// Get hash_key from database for users who already are in the database
/* RetrieveHash Start */
const RetrieveHash = (uid, username, res) => {
con.query(
'SELECT `hash_key` FROM `users` WHERE `uid`=?',
[uid],
(error, results) => RetrieveHashDbCheck({ res, uid, username, error, results })
)
const RetrieveHash = async (uid) => {
let results = await con.query('SELECT `hash_key` FROM `users` WHERE `uid`=?', [uid])
// call to steemconnect to verify user is logged in
let auth = await isAuth()
if (auth) return (results[0].hash_key)
}
// Process database response and return hash_key
const RetrieveHashDbCheck = ({ res, uid, username, error, results }) => {
if (!error) {
// call to steemconnect
// to verify user is logged in
api.me((err, ress) => {
if (!err && ress) {
// steemconnect access_token is correct
// user is logged in
if (ress.account && ress.account.id === uid) {
if (results[0].hash_key) {
res.status(200).send(
JSON.stringify({
// return result
username: username,
uid: uid,
hash_key: results[0].hash_key
})
)
} else {
// any error
res.status(400).send(
JSON.stringify({
error: 'invalid request (db die)'
})
)
}
} else {
// Not logged in steemconnect
res.status(400).send(
JSON.stringify({
error: 'invalid request (401)'
})
)
}

// this function will verify login details by calling to steemconnect
const isAuth = async () => {
let auth = await new Promise((resolve, reject) => {
api.me((err, result) => {
if (!err && result && result.account) {
resolve(result)
} else {
// steemconnect call error
res.status(400).send(
JSON.stringify({
error: 'invalid request (sc die)'
})
)
reject(new Error(err))
}
})
}
})
return auth
}
/* RetrieveHash End */

/* SetHash Start */
// First time login
// Generating new hash_key
const SetHash = (uid, username, res) => {
const SetHash = async (uid, username) => {
// Create random hex string (hash_key)
const hash = crypto.randomBytes(20).toString('hex')
// call to steemconnect
// to verify user is logged in
api.me((err, ress) => {
if (!err && ress && ress.account && ress.account.id === uid) {
// user is logged in
const username = ress.user
// inserting hash_key and user info to the database
con.query(
'INSERT INTO `users`(`uid`, `username`, `hash_key`) VALUES (?,?,?)',
[uid, username, hash],
(error, results) => {
SetHashDbInsert({ res, username, uid, hash, error, results })
}
)
} else {
// steemconnect call error
res.status(400).send(
JSON.stringify({
error: 'invalid request (sc die)'
})
)
}
})
}
// Return hash_key after inserting data to the database
const SetHashDbInsert = ({ res, uid, username, hash, error, results }) => {
if (!error) {
res.status(200).send(
JSON.stringify({
// return result
username: username,
uid: uid,
hash_key: hash
})
let auth = await isAuth()
let id = await auth.account.id
let user = await auth.user
if (uid === id && user === username) {
let results = await con.query(
'INSERT INTO `users`(`uid`, `username`, `hash_key`) VALUES (?,?,?)',
[uid, username, hash]
)
if (results) return hash
else throw new Error('db insert fail')
}
}
/* SetHash End */

// export router to import in the /api.js
module.exports = router

// keep MySQL connection live
// prevent MySQL connection timeout error
setInterval(() => {
con.query('SELECT 1', () => {})
}, 5000)
// previosly we used this method to keep one MySQL connection alive
// now, we are using a pool which will handle multiple connections
// we can use it again if any possible error
// setInterval(() => {
// con.query('SELECT 1', () => {})
// }, 5000)

0 comments on commit 7c59954

Please sign in to comment.