var crypto = require('crypto') let db = require('@config/database') let Auth = require('@helpers/Auth') let User = module.exports = {} //Login a user, if that user does not exist create them //Issues login token User.login = (username, password) => { return new Promise((resolve, reject) => { const lowerName = username.toLowerCase(); db.promise() .query('SELECT * FROM users WHERE username = ? LIMIT 1', [lowerName]) .then((rows, fields) => { //Pull out user data from database results const lookedUpUser = rows[0][0]; //User not found, create a new account with set data if(rows[0].length == 0){ User.create(lowerName, password) .then(loginToken => { resolve(loginToken) }) return } //hash the password and check for a match const salt = new Buffer(lookedUpUser.salt, 'binary') crypto.pbkdf2(password, salt, lookedUpUser.iterations, 512, 'sha512', function(err, delivered_key){ if(delivered_key.toString('hex') === lookedUpUser.password){ //Passback a json web token const token = Auth.createToken(lookedUpUser.id) resolve(token) } else { reject('Password does not match database') } }) }) .catch(console.log) }) } //Create user account //Issues login token User.create = (username, password) => { //For some reason, username won't get into the promise. But password will @TODO figure this out const lowerName = username.toLowerCase().trim() return new Promise((resolve, reject) => { db.promise() .query('SELECT * FROM users WHERE username = ? LIMIT 1', [lowerName]) .then((rows, fields) => { if(rows[0].length === 0){ //No users returned, create new one. Start with hashing password //Params for hash function let shasum = crypto.createHash('sha512') //Prepare Hash const ran = parseInt(Date.now()) //Get current time in miliseconds const semiRandomInt = Math.floor(Math.random()*11) //Grab a random number const otherRandomInt = (ran*semiRandomInt+ran)*semiRandomInt-ran //Mix things up a bit shasum.update(''+otherRandomInt) //Update Hasd const saltString = shasum.digest('hex') const salt = new Buffer(saltString, 'binary') //Generate Salt hash const iterations = 25000 crypto.pbkdf2(password, salt, iterations, 512, 'sha512', function(err, delivered_key) { //Create new user object with freshly salted password var currentDate = new Date().toISOString().slice(0, 19).replace('T', ' '); var new_user = { username: lowerName, password: delivered_key.toString('hex'), salt: salt, iterations: iterations, last_login: currentDate, created: currentDate }; db.promise() .query('INSERT INTO users SET ?', new_user) .then((rows, fields) => { if(rows[0].affectedRows == 1){ const newUserId = rows[0].insertId const loginToken = Auth.createToken(newUserId) resolve(loginToken) } else { //Emit Error to user reject('New user could not be created') } }) .catch(console.log) }) } else { reject('Username already in use.') }//END user create }) .catch(console.log) }) }