diff --git a/common/utilities.js b/common/utilities.js index a081dea..c14f2b3 100644 --- a/common/utilities.js +++ b/common/utilities.js @@ -1,9 +1,26 @@ -var emailExpression = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; +let emailExpression = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; function validateEmail(email) { return emailExpression.test(email); } +let excluded = [ //errors that should not be logged + 'Not enough gold', + 'Not enough recruits', + 'Not enough soldiers', + 'Not enough spies', + 'Not enough scientists', + 'Not enough time has passed' +]; + +const log = (msg, ...args) => { + if (excluded.indexOf(msg) === -1) { + console.log(`log ${Date()}: ${msg} (${args.toString()})`); + } + return msg; +} + module.exports = { - validateEmail + validateEmail: validateEmail, + log: log }; \ No newline at end of file diff --git a/server/accounts.js b/server/accounts.js index b830014..164e4c4 100644 --- a/server/accounts.js +++ b/server/accounts.js @@ -7,7 +7,7 @@ let formidable = require('formidable'); let sendmail = require('sendmail')(); //utilities -let { validateEmail } = require('../common/utilities.js'); +let { log, validateEmail } = require('../common/utilities.js'); let { throttle, isThrottled } = require('../common/throttle.js'); const signup = (connection) => (req, res) => { @@ -20,7 +20,7 @@ const signup = (connection) => (req, res) => { //validate email, username and password if (!validateEmail(fields.email) || fields.username.length < 4 || fields.username.length > 100 || fields.password.length < 8 || fields.password !== fields.retype) { - res.status(400).write('Invalid signup data'); + res.status(400).write(log('Invalid signup data', fields)); res.end(); return; } @@ -31,13 +31,13 @@ const signup = (connection) => (req, res) => { if (err) throw err; if (results[0].email !== 0) { - res.status(400).write('Email already registered!'); + res.status(400).write(log('Email already registered!', fields.email)); res.end(); return; } if (results[0].username !== 0) { - res.status(400).write('Username already registered!'); + res.status(400).write(log('Username already registered!', fields.username)); res.end(); return; } @@ -58,7 +58,7 @@ const signup = (connection) => (req, res) => { //prevent too many clicks if (isThrottled(fields.email)) { - res.status(400).write('signup throttled'); + res.status(400).write(log('signup throttled', fields.email)); res.end(); return; } @@ -80,12 +80,12 @@ const signup = (connection) => (req, res) => { }, (err, reply) => { //final check if (err) { - res.write(`
Something went wrong (did you use a valid email?)
${err}
`); + res.status(400).write(log('Something went wrong (did you use a valid email?)', err)); res.end(); return; } - res.status(200).write('Verification email sent!'); + res.status(200).write(log('Verification email sent!', fields.email)); res.end(); }); }); @@ -104,14 +104,14 @@ const verify = (connection) => (req, res) => { //correct number of results if (results.length != 1) { - res.write('That account does not exist or this link has already been used.
'); + res.status(400).write(log('That account does not exist or this link has already been used.', req.query.email, req.query.verify)); res.end(); return; } //verify the link if (req.query.verify != results[0].verify) { - res.write('Verification failed!
'); + res.status(400).write(log('Verification failed!', req.query.email, req.query.verify, results[0].verify)); res.end(); return; } @@ -126,7 +126,7 @@ const verify = (connection) => (req, res) => { connection.query(query, [results[0].email], (err) => { if (err) throw err; - res.write('Verification succeeded!
'); + res.status(200).write(log('Verification succeeded!', req.query.email)); res.end(); }); }); @@ -143,7 +143,7 @@ const login = (connection) => (req, res) => { //validate email, username and password if (!validateEmail(fields.email) || fields.password.length < 8) { - res.write('Invalid login data
'); + res.status(400).write(log('Invalid login data', fields.email)); //WARNING: NEVER LOG PASSWORDS. EVER. res.end(); return; } @@ -155,7 +155,7 @@ const login = (connection) => (req, res) => { //found this email? if (results.length === 0) { - res.status(400).write('Incorrect email or password'); + res.status(400).write(log('Incorrect email or password', fields.email, 'Did not find this email')); res.end(); return; } @@ -166,7 +166,7 @@ const login = (connection) => (req, res) => { //compare the passwords if (results[0].hash !== newHash) { - res.status(400).write('Incorrect email or password'); + res.status(400).write(log('Incorrect email or password', fields.email, 'Did not find this password')); res.end(); return; } @@ -185,6 +185,8 @@ const login = (connection) => (req, res) => { username: results[0].username, token: rand }); + res.end(); + log('Logged in', fields.email, rand); }); }); }); @@ -195,6 +197,7 @@ const logout = (connection) => (req, res) => { let query = 'DELETE FROM sessions WHERE sessions.accountId IN (SELECT accounts.id FROM accounts WHERE email = ?) AND token = ?;'; connection.query(query, [req.body.email, req.body.token], (err) => { if (err) throw err; + log('Logged out', req.body.email, req.body.token); }); res.end(); @@ -210,7 +213,7 @@ const passwordChange = (connection) => (req, res) => { //validate password, retype if (!validateEmail(fields.email) || fields.password.length < 8 || fields.password !== fields.retype) { - res.status(400).write('Invalid password change data'); + res.status(400).write(log('Invalid password change data', fields.email)); res.end(); return; } @@ -225,7 +228,7 @@ const passwordChange = (connection) => (req, res) => { results.map((result) => { if (result.token == fields.token) found = true; }); if (!found) { - res.status(400).write('Invalid password change authentication'); + res.status(400).write(log('Invalid password change authentication', fields.email, fields.token)); res.end(); return; } @@ -256,6 +259,7 @@ const passwordChange = (connection) => (req, res) => { res.status(200).json({ token: rand }); + log('Password changed', fields.email); }); }); }); @@ -275,7 +279,7 @@ const passwordRecover = (connection) => (req, res) => { //validate email, username and password if (!validateEmail(fields.email)) { - res.status(400).write('Invalid recover data'); + res.status(400).write(log('Invalid recover data', fields.email)); res.end(); return; } @@ -286,7 +290,7 @@ const passwordRecover = (connection) => (req, res) => { if (err) throw err; if (results.length !== 1) { - res.status(400).write('Invalid recover data (did you use a registered email?)'); + res.status(400).write(log('Invalid recover data (did you use a registered email?)', fields.email)); res.end(); return; } @@ -305,7 +309,7 @@ const passwordRecover = (connection) => (req, res) => { //prevent too many clicks if (isThrottled(fields.email)) { - res.status(400).write('recover throttled'); + res.status(400).write(log('recover throttled', fields.email)); res.end(); return; } @@ -322,12 +326,12 @@ const passwordRecover = (connection) => (req, res) => { }, (err, reply) => { //final check if (err) { - res.write(`Something went wrong (did you use a valid email?)
${err}`) + res.status(400).write(log('Something went wrong (did you use a valid email?)', err)); res.end(); return; } - res.status(200).write('Recovery email sent!'); + res.status(200).write(log('Recovery email sent!', fields.email)); res.end(); }); }); @@ -345,7 +349,7 @@ const passwordReset = (connection) => (req, res) => { //validate email, username and password if (!validateEmail(fields.email) || fields.password.length < 8 || fields.password !== fields.retype) { - res.status(400).write('Invalid reset data (invalid email/password)'); + res.status(400).write(log('Invalid reset data (invalid email/password)', fields.email)); res.end(); return; } @@ -357,7 +361,7 @@ const passwordReset = (connection) => (req, res) => { //results should be only 1 account if (results.length !== 1) { - res.status(400).write('Invalid reset data (incorrect parameters/database state)'); + res.status(400).write(log('Invalid reset data (incorrect parameters/database state)', fields.email)); res.end(); return; } @@ -378,7 +382,7 @@ const passwordReset = (connection) => (req, res) => { connection.query(query, [fields.email], (err) => { if (err) throw err; - res.status(200).write('Password updated!'); + res.status(200).write(log('Password updated!', fields.email)); res.end(); return; }); diff --git a/server/database.js b/server/database.js index 08d1556..029c27f 100644 --- a/server/database.js +++ b/server/database.js @@ -4,6 +4,9 @@ require('dotenv').config(); //libraries let mysql = require('mysql'); +//utilities +let { log } = require('../common/utilities.js'); + let connection; function handleDisconnect() { @@ -19,16 +22,16 @@ function handleDisconnect() { //connect connection.connect((err) => { if (err) { - console.log('Error connecting to mysql: ', err); + log('Error connecting to mysql: ', err); setTimeout(handleDisconnect, 2000); } else { - console.log('Connected to mysql'); + log('Connected to mysql'); } }); //prepare for failure connection.on('error', (err) => { - console.log('mysql error: ', err); + log('mysql error: ', err); if (err.code === 'PROTOCOL_CONNECTION_LOST') { handleDisconnect(); diff --git a/server/index.js b/server/index.js index 2601f3b..efdf9d8 100644 --- a/server/index.js +++ b/server/index.js @@ -8,6 +8,9 @@ let http = require('http').Server(app); let bodyParser = require('body-parser'); let path = require('path'); +//utilities +let { log } = require('../common/utilities.js'); + app.use(bodyParser.json()); //handle the news request @@ -51,5 +54,5 @@ app.get('*', (req, res) => { //startup http.listen(4000, () => { - console.log('listening to *:4000'); + log('listening to *:4000'); }); \ No newline at end of file diff --git a/server/profiles.js b/server/profiles.js index ab6fcbb..bdd66b7 100644 --- a/server/profiles.js +++ b/server/profiles.js @@ -5,12 +5,15 @@ require('dotenv').config(); let formidable = require('formidable'); let CronJob = require('cron').CronJob; +//utilities +let { log } = require('../common/utilities.js'); + //profile creation & requesting const profileCreate = (connection) => (req, res) => { //formidable handles forms let form = formidable.IncomingForm(); - //parse form + //parse form TODO: form? That was a bad idea form.parse(req, (err, fields) => { if (err) throw err; @@ -25,7 +28,7 @@ function profileCreateInner(connection, req, res, fields) { if (err) throw err; if (results.length === 1) { - res.status(400).write('That profile already exists'); + res.status(400).write(log('That profile already exists', fields.username)); res.end(); return; } @@ -36,7 +39,7 @@ function profileCreateInner(connection, req, res, fields) { if (err) throw err; if (results.length !== 1 || results[0].accountId != fields.id) { - res.status(400).write('Invalid profile creation credentials'); + res.status(400).write(log('Invalid profile creation credentials', fields.username, fields.id, fields.token)); res.end(); return; } @@ -45,6 +48,8 @@ function profileCreateInner(connection, req, res, fields) { connection.query(query, [fields.username], (err) => { if (err) throw err; + log('Profile created', fields.username, fields.id, fields.token); + return profileRequestInner(connection, req, res, fields); }); }); @@ -78,7 +83,7 @@ function profileRequestInner(connection, req, res, fields) { if (results.length === 1) { return profileCreateInner(connection, req, res, fields); } else { - res.status(400).write('Profile not found'); + res.status(400).write(log('Profile not found', fields.username, fields.id, fields.token)); res.end(); } }); @@ -93,6 +98,7 @@ function profileRequestInner(connection, req, res, fields) { scientists: results[0].scientists }); res.end(); +// log('Profile sent', fields.username, fields.id, fields.token); } }); } @@ -112,7 +118,7 @@ const recruit = (connection) => (req, res) => { if (err) throw err; if (results.length !== 1) { - res.status(400).write('Invalid recruit credentials'); + res.status(400).write(log('Invalid recruit credentials', fields.username, fields.id, fields.token)); res.end(); return; } @@ -123,7 +129,7 @@ const recruit = (connection) => (req, res) => { if (err) throw err; if (results.length !== 1) { - res.status(400).write('Invalid database state'); //TODO: internal error logging + res.status(400).write(log('Invalid database state', fields.username, fields.id, fields.token)); res.end(); return; } @@ -132,7 +138,7 @@ const recruit = (connection) => (req, res) => { //not enough time has passed if (timespans < 22) { - res.status(400).write('Not enough time has passed'); + res.status(400).write(log('Not enough time has passed', fields.username, fields.id, fields.token)); res.end(); return; } @@ -149,7 +155,7 @@ const recruit = (connection) => (req, res) => { //check just in case if (results.length !== 1) { - res.status(400).write('Invalid recruit credentials'); + res.status(400).write(log('Invalid recruit credentials', fields.username, fields.id, fields.token)); res.end(); return; } @@ -164,6 +170,7 @@ const recruit = (connection) => (req, res) => { scientists: results[0].scientists }); res.end(); + log('Recruit successful', fields.username, fields.id, fields.token); }); }); }); @@ -185,19 +192,19 @@ const train = (connection) => (req, res) => { if (err) throw err; if (results.length !== 1) { - res.status(400).write('Invalid train credentials'); + res.status(400).write(log('Invalid train credentials', fields.username, fields.id, fields.token)); res.end(); return; } //verify the role argument if (fields.role !== 'soldier' && fields.role !== 'spy' && fields.role !== 'scientist') { - res.status(400).write('Invalid train parameters'); + res.status(400).write(log('Invalid train parameters', fields.username, fields.role, fields.id, fields.token)); res.end(); return; } - //determine the cost of the training + //determine the cost of the training TODO: make these global for the client too let cost = 0; switch(fields.role) { case 'soldier': @@ -219,13 +226,13 @@ const train = (connection) => (req, res) => { if (err) throw err; if (results[0].recruits <= 0) { - res.status(400).write('Not enough recruits'); + res.status(400).write(log('Not enough recruits', fields.username, results[0].recruits, fields.id, fields.token)); res.end(); return; } if (results[0].gold < cost) { - res.status(400).write('Not enough gold'); + res.status(400).write(log('Not enough gold', fields.username, results[0].gold, fields.id, fields.token)); res.end(); return; } @@ -242,7 +249,7 @@ const train = (connection) => (req, res) => { //check just in case if (results.length !== 1) { - res.status(400).write('Invalid recruit credentials'); + res.status(400).write(log('Invalid recruit credentials', fields.username, fields.id, fields.token)); res.end(); return; } @@ -257,6 +264,7 @@ const train = (connection) => (req, res) => { scientists: results[0].scientists }); res.end(); + log('Train successful', fields.username, fields.role, fields.id, fields.token); }); }); }); @@ -278,14 +286,14 @@ const untrain = (connection) => (req, res) => { if (err) throw err; if (results.length !== 1) { - res.status(400).write('Invalid train credentials'); + res.status(400).write(log('Invalid untrain credentials', fields.username, fields.role, fields.id, fields.token)); res.end(); return; } //verify the role argument if (fields.role !== 'soldier' && fields.role !== 'spy' && fields.role !== 'scientist') { - res.status(400).write('Invalid untrain parameters'); + res.status(400).write(log('Invalid untrain parameters', fields.username, fields.role, fields.id, fields.token)); res.end(); return; } @@ -296,19 +304,19 @@ const untrain = (connection) => (req, res) => { if (err) throw err; if (fields.role === 'soldier' && results[0].soldiers <= 0) { - res.status(400).write('Not enough soldiers'); + res.status(400).write(log('Not enough soldiers', fields.username, results[0].soldiers, fields.id, fields.token)); res.end(); return; } if (fields.role === 'spy' && results[0].spies <= 0) { - res.status(400).write('Not enough spies'); + res.status(400).write(log('Not enough spies', fields.username, results[0].spies, fields.id, fields.token)); res.end(); return; } if (fields.role === 'scientist' && results[0].scientists <= 0) { - res.status(400).write('Not enough scientists'); + res.status(400).write(log('Not enough scientists', fields.username, results[0].scientists, fields.id, fields.token)); res.end(); return; } @@ -325,7 +333,7 @@ const untrain = (connection) => (req, res) => { //check just in case if (results.length !== 1) { - res.status(400).write('Invalid recruit credentials'); + res.status(400).write(log('Invalid untrain credentials', fields.username, fields.role, fields.id, fields.token)); res.end(); return; } @@ -340,6 +348,7 @@ const untrain = (connection) => (req, res) => { scientists: results[0].scientists }); res.end(); + log('Untrain successful', fields.username, fields.role, fields.id, fields.token); }); }); }); @@ -353,8 +362,7 @@ const runGoldTick = (connection) => { connection.query(query, (err) => { if (err) throw err; - //debugging - //console.log(Date().toString() + ' gold tick'); + log('Gold tick'); }); });