diff --git a/config/demo.js b/config/demo.js index 5404759..2298920 100644 --- a/config/demo.js +++ b/config/demo.js @@ -1,23 +1,23 @@ -'use strict'; - // Imports -const fs = require('fs'), - debug = require('debug')('tracman-demo'); +const fs = require('fs') +const debug = require('debug')('tracman-demo') module.exports = (io)=>{ // File is space-seperated: delay, lat, lon, dir, spd fs.readFile(__dirname+'/demo.txt', (err,data)=>{ - if (err){ console.error(`❌ ${err.stack}`); } + if (err){ console.error(`Error reading file from ${__dirname+'demo.txt'}:\n${err.stack}`); } - const lines = data.toString().split('\n'); + const lines = data.toString().split('\n') + debug(`Found ${lines.length} lines in ${__dirname+'demo.txt'}`); (function sendLoc(ln) { - if (ln>20754){ sendLoc(0) } + debug(`sendLoc(${ln}) called`) + if (ln>20754){ sendLoc(0); } // Reached end of list, restart else { - let loc = lines[ln].split(' '); - debug(`Sending demo location: ${loc[1]}, ${loc[2]}`); + let loc = lines[ln].split(' ') + debug(`Sending demo location: ${loc[1]}, ${loc[2]}`) io.to('demo').emit('get', { tim: new Date(), lat: loc[1], @@ -26,13 +26,13 @@ module.exports = (io)=>{ spd: loc[4] }); - // Repeat after delay in milliseconds + // Repeat for next location setTimeout(()=>{ sendLoc(ln+1); // next line of file - }, loc[0]); + }, loc[0]); // Number of miliseconds delay } - })(5667); + })(5667); // Initiate }); -}; \ No newline at end of file +}; diff --git a/config/mail.js b/config/mail.js index 6d9acfe..da64fec 100644 --- a/config/mail.js +++ b/config/mail.js @@ -1,7 +1,6 @@ -'use strict'; - -const nodemailer = require('nodemailer'), - env = require('./env/env.js'); +const nodemailer = require('nodemailer') +const env = require('./env/env.js') +const debug = require('debug')('tracman-mail') let transporter = nodemailer.createTransport({ host: env.mailserver, @@ -15,27 +14,28 @@ let transporter = nodemailer.createTransport({ module.exports = { - verify: ()=>{ - transporter.verify( (err,success)=>{ - if (err){ console.error(`SMTP Error: ${err}`); } - console.log(`📧 SMTP ${!success?'not ':''}ready`); - } ); + verify: () => { + debug(`Verifying SMTP connection...`) + transporter.verify( (err,success) => { + if (err){ console.error(`📧 SMTP ${err}`); } + console.log(`📧 SMTP${(success)?'':' not'} ready`) + } ) }, send: transporter.sendMail.bind(transporter), - text: (text)=>{ - return `Tracman\n\n${text}\n\nDo not reply to this email\nFor information about why you received this email, see the privacy policy at ${env.url}/privacyy#email`; + text: (text) => { + return `Tracman\n\n${text}\n\nDo not reply to this email\nFor information about why you received this email, see the privacy policy at ${env.url}/privacyy#email` }, html: (text)=>{ - return `
Do not reply to this email. For information about why you recieved this email, see our privacy policy.
`; + return `Do not reply to this email. For information about why you recieved this email, see our privacy policy.
` }, - noReply: `"Tracman"Welcome to Tracman!
To complete your registration, follow this link and set your password:
${env.url}/settings/password/${token}
This link will expire at ${expirationTimeString}.
`) + debug(`Emailing new user ${user.id} at ${user.email} instructions to create a password...`) + mail.send({ + from: mail.noReply, + to: `<${user.email}>`, + subject: 'Complete your Tracman registration', + text: mail.text(`Welcome to Tracman! \n\nTo complete your registration, follow this link and set your password:\n${env.url}/settings/password/${token}\n\nThis link will expire at ${expirationTimeString}. `), + html: mail.html(`Welcome to Tracman!
To complete your registration, follow this link and set your password:
${env.url}/settings/password/${token}
This link will expire at ${expirationTimeString}.
`) + }) + .then(()=>{ + debug(`Successfully emailed new user ${user.id} instructions to continue`); + req.flash('success', `An email has been sent to ${user.email}. Check your inbox and follow the link to complete your registration. (Your registration link will expire in one hour). `); + res.redirect('/login'); + }) - .then(()=>{ - debug(`Successfully emailed new user ${user.id} instructions to continue`); - req.flash('success', `An email has been sent to ${user.email}. Check your inbox and follow the link to complete your registration. (Your registration link will expire in one hour). `); - res.redirect('/login'); + .then( () => { + debug(`Successfully emailed new user ${user.id} instructions to continue`) + req.flash('success', `An email has been sent to ${user.email}. Check your inbox and follow the link to complete your registration. (Your registration link will expire in one hour). `) + res.redirect('/login') + }) + .catch( (err) => { + debug(`Failed to email new user ${user.id} instructions to continue!`) + mw.throwErr(err,req) + res.redirect('/login#signup') }) - .catch((err)=>{ - debug(`Failed to email new user ${user.id} instructions to continue!`); - mw.throwErr(err,req); - res.redirect('/login#signup'); - }); } - }); + }) } // Validate email - req.checkBody('email', 'Please enter a valid email address.').isEmail(); + req.checkBody('email', 'Please enter a valid email address.').isEmail() // Check if somebody already has that email - debug(`Searching for user with email ${req.body.email}...`); + debug(`Searching for user with email ${req.body.email}...`) User.findOne({'email':req.body.email}) - .then( (user)=>{ + .then( (user) => { // User already exists if (user && user.auth.password) { - debug(`User ${user.id} has email ${req.body.email} and has a password`); - req.flash('warning',`A user with that email already exists! If you forgot your password, you can reset it here.`); - res.redirect('/login#login'); - next(); - } + debug(`User ${user.id} has email ${req.body.email} and has a password`) + req.flash('warning',`A user with that email already exists! If you forgot your password, you can reset it here.`) + res.redirect('/login#login') + next() // User exists but hasn't created a password yet - else if (user) { - debug(`User ${user.id} has email ${req.body.email} but doesn't have a password`); + } else if (user) { + debug(`User ${user.id} has email ${req.body.email} but doesn't have a password... resending token`) // Send another token (or the same one if it hasn't expired) - sendToken(user); - } + sendToken(user) // Create user - else { - debug(`User with email ${req.body.email} doesn't exist; creating one`); + } else { + debug(`User with email ${req.body.email} doesn't exist; creating one`) - user = new User(); - user.created = Date.now(); - user.email = req.body.email; - user.slug = slugify(user.email.substring(0, user.email.indexOf('@'))); + user = new User() + user.created = Date.now() + user.email = req.body.email + user.slug = slugify(user.email.substring(0, user.email.indexOf('@'))) // Generate unique slug - const slug = new Promise((resolve,reject) => { - debug(`Creating new slug for user...`); + const slug = new Promise( (resolve, reject) => { + debug(`Creating new slug for user...`) (function checkSlug(s,cb){ - - debug(`Checking to see if slug ${s} is taken...`); + debug(`Checking to see if slug ${s} is taken...`) User.findOne({slug:s}) - .then((existingUser)=>{ + .then( (existingUser) => { // Slug in use: generate a random one and retry if (existingUser){ - debug(`Slug ${s} is taken; generating another...`); - crypto.randomBytes(6, (err,buf)=>{ + debug(`Slug ${s} is taken; generating another...`) + crypto.randomBytes(6, (err, buf) => { if (err) { - debug('Failed to create random bytes for slug!'); - mw.throwErr(err,req); - reject(); + debug('Failed to create random bytes for slug!') + mw.throwErr(err, req) + reject() } if (buf) { - checkSlug(buf.toString('hex'),cb); + checkSlug( buf.toString('hex'), cb ) } - }); + }) } // Unique slug: proceed else { - debug(`Slug ${s} is unique`); - cb(s); + debug(`Slug ${s} is unique`) + cb(s) } }) - .catch((err)=>{ - debug('Failed to create slug!'); - mw.throwErr(err,req); - reject(); - }); - - })(user.slug, (newSlug)=>{ - debug(`Successfully created slug: ${newSlug}`); - user.slug = newSlug; - resolve(); - }); - }); + .catch( (err) => { + debug('Failed to create slug!') + mw.throwErr(err, req) + reject() + }) + + // Slug created successfully + }) (user.slug, (newSlug) => { + debug(`Successfully created slug: ${newSlug}`) + user.slug = newSlug + resolve() + }) + + }) // Generate sk32 - const sk32 = new Promise((resolve,reject) => { - debug('Creating sk32 for user...'); - crypto.randomBytes(32, (err,buf)=>{ + const sk32 = new Promise( (resolve, reject) => { + debug('Creating sk32 for user...') + crypto.randomBytes( 32, (err, buf) => { if (err) { - debug('Failed to create sk32!'); - mw.throwErr(err,req); - reject(); + debug('Failed to create sk32!') + mw.throwErr(err, req) + reject() } if (buf) { - user.sk32 = buf.toString('hex'); - debug(`Successfully created sk32: ${user.sk32}`); - resolve(); + user.sk32 = buf.toString('hex') + debug(`Successfully created sk32: ${user.sk32}`) + resolve() } - }); - }); + }) + }) // Save user and send the token by email Promise.all([slug, sk32]) - .then( ()=>{ sendToken(user); }) + .then( user.save ) + .then( () => { + debug(`User saved; sending token...`) + sendToken(user) + user.save() + }) .catch( (err)=>{ - debug('Failed to save user after creating slug and sk32!'); - mw.throwErr(err,req); - res.redirect('/login#signup'); - }); + debug('Failed to save user after creating slug and sk32! Token not sent') + mw.throwErr(err,req) + res.redirect('/login#signup') + }) } }) - .catch( (err)=>{ - debug(`Failed to check if somebody already has the email ${req.body.email}`); - mw.throwErr(err,req); - res.redirect('/signup'); - }); + .catch( (err) => { + debug(`Failed to check if somebody already has the email ${req.body.email}`) + mw.throwErr(err,req) + res.redirect('/login#signup') + }) - }); + }) // Forgot password app.route('/login/forgot') - - // Check if user is already logged in - .all( (req,res,next)=>{ - if (req.isAuthenticated()){ loginCallback(req,res); } - else { next(); } + .all( (req, res, next) => { + debug(`/login/fogot requested`) + + // Check if user is already logged in + if (req.isAuthenticated()) { + debug(`User is already logged in as ${req.user.id}`) + loginCallback(req,res) + } else { + next() + } } ) // Show forgot password page - .get( (req,res,next)=>{ - res.render('forgot', {email:req.query.email}); + .get( (req, res, next) => { + debug(`GET /login/forgot ; loading forgot password form...`) + res.render('forgot', {email:req.query.email}) } ) // Submitted forgot password form - .post( (req,res,next)=>{ + .post( (req, res, next) => { + debug(`POST /login/forgot ; checking email ${req.body.email}...`) // Validate email - req.checkBody('email', 'Please enter a valid email address.').isEmail(); + req.checkBody('email', 'Please enter a valid email address.').isEmail() // Check if somebody has that email User.findOne({'email':req.body.email}) - .then( (user)=>{ + .then( (user) => { // No user with that email if (!user) { + debug(`No user with that email exists; Ignoring request to reset password`) // Don't let on that no such user exists, to prevent dictionary attacks - req.flash('success', `If an account exists with the email ${req.body.email}, an email has been sent there with a password reset link. `); - res.redirect('/login'); - } + req.flash('success', `If an account exists with the email ${req.body.email}, an email has been sent there with a password reset link. `) + res.redirect('/login') // User with that email does exist - else { + } else { + debug(`User ${user.id} has that email; creating reset token...`) // Create reset token - user.createPassToken( (err,token)=>{ - if (err){ next(err); } + user.createPassToken( (err, token) => { + if (err) { + debug('Error creating password token') + next(err) + } - // Email reset link - mail.send({ - from: mail.noReply, - to: mail.to(user), - subject: 'Reset your Tracman password', - text: mail.text(`Hi, \n\nDid you request to reset your Tracman password? If so, follow this link to do so:\n${env.url}/settings/password/${token}\n\nIf you didn't initiate this request, just ignore this email. `), - html: mail.html(`Hi,
Did you request to reset your Tracman password? If so, follow this link to do so:
${env.url}/settings/password/${token}
If you didn't initiate this request, just ignore this email.
`) - }).then(()=>{ - req.flash('success', `If an account exists with the email ${req.body.email}, an email has been sent there with a password reset link. `); - res.redirect('/login'); - }).catch((err)=>{ - debug(`Failed to send reset link to ${user.email}`); - mw.throwErr(err,req); - res.redirect('/login'); - }); + // Token created successfully + if (token) { + debug(`Token ${token} created; sending email to ${user.email}...`) + + // Email reset link + mail.send({ + from: mail.noReply, + to: mail.to(user), + subject: 'Reset your Tracman password', + text: mail.text(`Hi, \n\nDid you request to reset your Tracman password? If so, follow this link to do so:\n${env.url}/settings/password/${token}\n\nIf you didn't initiate this request, just ignore this email. `), + html: mail.html(`Hi,
Did you request to reset your Tracman password? If so, follow this link to do so:
${env.url}/settings/password/${token}
If you didn't initiate this request, just ignore this email.
`) + }) + + // Successfully sent reset link + .then( () => { + debug(`Reset link sent successfully`) + req.flash('success', `If an account exists with the email ${req.body.email}, an email has been sent there with a password reset link. `) + res.redirect('/login') + }) + + // Failed to email reset link + .catch( (err) => { + debug(`Failed to send reset link`) + mw.throwErr(err, req) + res.redirect('/login') + }) + + } - }); + }) } - }).catch( (err)=>{ - debug(`Failed to check for if somebody has that email (in reset request)!`); - mw.throwErr(err,req); - res.redirect('/login/forgot'); - }); + }) + + // Failed to check if somebody has that email + .catch( (err) => { + debug(`Failed to check for if somebody has that email (in reset request)!`) + mw.throwErr(err,req) + res.redirect('/login/forgot') + }) - } ); + } ) // Android - app.post('/login/app', passport.authenticate('local'), appLoginCallback); + app.post('/login/app', passport.authenticate('local'), appLoginCallback) // Token-based (android social) - app.get(['/login/app/google','/auth/google/idtoken'], passport.authenticate('google-token'), appLoginCallback); - // app.get('/login/app/facebook', passport.authenticate('facebook-token'), appLoginCallback); - // app.get('/login/app/twitter', passport.authenticate('twitter-token'), appLoginCallback); + app.get(['/login/app/google','/auth/google/idtoken'], passport.authenticate('google-token'), appLoginCallback) + // app.get('/login/app/facebook', passport.authenticate('facebook-token'), appLoginCallback) + // app.get('/login/app/twitter', passport.authenticate('twitter-token'), appLoginCallback) // Social - app.get('/login/:service', (req,res,next)=>{ - let service = req.params.service, - sendParams = (service==='google')?{scope:['https://www.googleapis.com/auth/userinfo.profile']}:null; + app.get('/login/:service', (req, res, next) => { + debug(`GET /login/:service for ${service} service`) + + // Set params + let service = req.params.service + let sendParams = (service==='google')?{scope:['https://www.googleapis.com/auth/userinfo.profile']}:null // Social login if (!req.user) { - debug(`Attempting to login with ${service} with params: ${JSON.stringify(sendParams)}...`); - passport.authenticate(service, sendParams)(req,res,next); + debug(`Attempting to login with ${service} with params: ${JSON.stringify(sendParams)}...`) + passport.authenticate(service, sendParams)(req, res, next) } // Connect social account else if (!req.user.auth[service]) { - debug(`Attempting to connect ${service} account...`); - passport.authorize(service, sendParams)(req,res,next); + debug(`Attempting to connect ${service} account...`) + passport.authorize(service, sendParams)(req, res, next) } // Disconnect social account else { - debug(`Attempting to disconnect ${service} account...`); + debug(`Attempting to disconnect ${service} account...`) // Make sure the user has a password before they disconnect their google login account // This is because login used to only be through google, and some people might not have // set passwords yet... if (!req.user.auth.password && service==='google') { - req.flash('warning',`Hey, you need to set a password before you can disconnect your google account. Otherwise, you won't be able to log in! `); - res.redirect('/settings'); - } + debug(`User doesn't have a password yet and can't disconnect their google account`) + req.flash('warning',`Hey, you need to set a password before you can disconnect your google account. Otherwise, you won't be able to log in! `) + res.redirect('/settings') - else { - req.user.auth[service] = undefined; + } else { + debug(`Disconnecting ${service} account`) + req.user.auth[service] = undefined req.user.save() - .then(()=>{ - req.flash('success', `${mw.capitalize(service)} account disconnected. `); - res.redirect('/settings'); + .then( () => { + debug(`${mw.capitalize(service)} account disconnected successfully`) + req.flash('success',`${mw.capitalize(service)} account disconnected`) + res.redirect('/settings') + }) + .catch( (err) => { + debug(`Unable to disconnect ${service} account`) + mw.throwErr(err,req) + res.redirect('/settings') }) - .catch((err)=>{ - debug(`Failed to save user after disconnecting ${service} account!`); - mw.throwErr(err,req); - res.redirect('/settings'); - }); } } - }); - app.get('/login/google/cb', passport.authenticate('google',loginOutcome), loginCallback ); - app.get('/login/facebook/cb', passport.authenticate('facebook',loginOutcome), loginCallback ); - app.get('/login/twitter/cb', passport.authenticate('twitter',loginOutcome), loginCallback ); + }) -}; + // Login callbacks + app.get('/login/google/cb', passport.authenticate('google',loginOutcome), loginCallback ) + app.get('/login/facebook/cb', passport.authenticate('facebook',loginOutcome), loginCallback ) + app.get('/login/twitter/cb', passport.authenticate('twitter',loginOutcome), loginCallback ) + +} diff --git a/config/routes/contact.js b/config/routes/contact.js index eb20543..b11d50a 100644 --- a/config/routes/contact.js +++ b/config/routes/contact.js @@ -1,10 +1,9 @@ -'use strict'; - -const env = require('../env/env.js'), - request = require('request'), - mw = require('../middleware.js'), - mail = require('../mail.js'), - router = require('express').Router(); +const debut = require('debug')('tracman-routes-contact') +const env = require('../env/env.js') +const request = require('request') +const mw = require('../middleware.js') +const mail = require('../mail.js') +const router = require('express').Router() module.exports = router diff --git a/config/sockets.js b/config/sockets.js index ee16582..873b7cd 100644 --- a/config/sockets.js +++ b/config/sockets.js @@ -1,8 +1,5 @@ -'use strict'; - -// Imports -const debug = require('debug')('tracman-sockets'), - User = require('./models.js').user; +const debug = require('debug')('tracman-sockets') +const User = require('./models.js').user // Check for tracking clients function checkForUsers(io, user) { @@ -24,22 +21,24 @@ module.exports = { checkForUsers: checkForUsers, - init: (io)=>{ + init: (io) => { + debug(`Initiating socketio...`) + io.on('connection', (socket)=>{ - debug(`${socket.id} connected.`); + debug(`${socket.id} connected.`) // Set a few variables - //socket.ip = socket.client.request.headers['x-real-ip']; - //socket.ua = socket.client.request.headers['user-agent']; + socket.ip = socket.client.request.headers['x-real-ip'] + socket.ua = socket.client.request.headers['user-agent'] // Log and errors - socket.on('log', (text)=>{ - debug(`LOG: ${text}`); - }); - socket.on('error', (err)=>{ console.error('❌', err.stack); }); + //socket.on('log', (text)=>{ + // console.log(`log: ${text}`) + //}) + socket.on('error', (err) => { console.error('❌', err.stack); } ) // This socket can set location (app) - socket.on('can-set', (userId)=>{ + socket.on('can-set', (userId) => { debug(`${socket.id} can set updates for ${userId}.`); socket.join(userId, ()=>{ debug(`${socket.id} joined ${userId}`); @@ -48,77 +47,93 @@ module.exports = { }); // This socket can receive location (map) - socket.on('can-get', (userId)=>{ - socket.gets = userId; - debug(`${socket.id} can get updates for ${userId}.`); - socket.join(userId, ()=>{ - debug(`${socket.id} joined ${userId}`); - socket.to(userId).emit('activate', 'true'); - }); - }); + socket.on('can-get', (userId) => { + debug(`${socket.id} can get updates for ${userId}.`) + socket.gets = userId + socket.join(userId, () => { + debug(`${socket.id} joined ${userId}`) + socket.to(userId).emit('activate', 'true') + }) + }) // Set location - socket.on('set', (loc)=>{ - debug(`${socket.id} set location for ${loc.usr}`); - debug(`Location was set to: ${JSON.stringify(loc)}`); + socket.on('set', (loc) => { + debug(`${socket.id} set location for ${loc.usr} to: ${JSON.stringify(loc)}`) // Get android timestamp or use server timestamp - if (loc.ts){ loc.tim = Date(loc.ts); } - else { loc.tim = Date.now(); } + if (loc.ts){ + debug(`Using android timestamp of ${loc.ts} for loc`) + loc.tim = Date(loc.ts) + } else { + debug(`Using server time of ${Date.now()} for loc`) + loc.tim = Date.now() + } // Check for user and sk32 token if (!loc.usr){ - console.error("❌", new Error(`Recieved an update from ${socket.ip} without a usr!`).message); + console.error("❌", new Error(`Recieved an update from ${socket.ip} without a usr!`).message) } else if (!loc.tok){ - console.error("❌", new Error(`Recieved an update from ${socket.ip} for usr ${loc.usr} without an sk32!`).message); + console.error("❌", new Error(`Recieved an update from ${socket.ip} for usr ${loc.usr} without an sk32!`).message) } else { // Get loc.usr + debug(`Getting loc.user of ${loc.user}`) User.findById(loc.usr) .where('sk32').equals(loc.tok) .then( (user)=>{ if (!user){ - console.error("❌", new Error(`Recieved an update from ${socket.ip} for ${loc.usr} with tok of ${loc.tok}, but no such user was found in the db!`).message); + console.error("❌", new Error(`Recieved an update from ${socket.ip} for ${loc.usr} with tok of ${loc.tok}, but no such user was found in the db!`).message) } else { // Broadcast location - io.to(loc.usr).emit('get', loc); - debug(`Broadcasting ${loc.lat}, ${loc.lon} to ${loc.usr}`); + debug(`Broadcasting ${loc.lat}, ${loc.lon} to ${loc.usr}`) + io.to(loc.usr).emit('get', loc) // Save in db as last seen + debug(`Saving user.last for user ${user.id}`) user.last = { lat: parseFloat(loc.lat), lon: parseFloat(loc.lon), dir: parseFloat(loc.dir||0), spd: parseFloat(loc.spd||0), time: loc.tim - }; + } user.save() - .catch( (err)=>{ console.error("❌", err.stack); }); + .then( () => { + debug(`user.last with time of ${loc.tim} successfully saved for user ${user.id}`) + }) + .catch( (err) => { + debug(`Failed to save user.last for user ${user.id}`) + console.error("❌", err.stack) + }) } }) - .catch( (err)=>{ console.error("❌", err.stack); }); + .catch( (err) => { + debug(`Error finding user with id of ${loc.usr}`) + console.error("❌", err.stack) + }) } - }); + }) // Shutdown (check for remaining clients) - socket.on('disconnect', (reason)=>{ - debug(`${socket.id} disconnected because of a ${reason}.`); + socket.on('disconnect', (reason) => { + debug(`${socket.id} disconnected because of a ${reason}.`) // Check if client was receiving updates - if (socket.gets){ - debug(`${socket.id} left ${socket.gets}`); - checkForUsers( io, socket.gets ); + if (socket.gets) { + debug(`${socket.id} left ${socket.gets}`) + checkForUsers( io, socket.gets ) } - }); + }) - }); + }) + } -}; \ No newline at end of file +} diff --git a/nodemon.json b/nodemon.json index 40c8d36..d9c19b6 100644 --- a/nodemon.json +++ b/nodemon.json @@ -1,7 +1,4 @@ { "verbose": true, "ext": "html, js, json, css", - "events": { - "start": "npm run build & npm run minify" - } } diff --git a/package-lock.json b/package-lock.json index d3d360f..17f6fbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tracman", - "version": "0.7.8", + "version": "0.7.11", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -419,6 +419,12 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, "browserify-aes": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.8.tgz", @@ -591,7 +597,7 @@ "cookiejar": "2.0.6", "is-ip": "1.0.0", "methods": "1.1.2", - "qs": "6.4.0", + "qs": "6.5.1", "superagent": "2.3.0" } }, @@ -1149,6 +1155,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, "diffie-hellman": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", @@ -1824,6 +1836,12 @@ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -1912,6 +1930,12 @@ "sntp": "2.0.2" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -2804,6 +2828,56 @@ "minimist": "0.0.8" } }, + "mocha": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", + "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, "moment": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", @@ -3007,7 +3081,7 @@ "dev": true, "requires": { "chokidar": "1.7.0", - "debug": "2.6.8", + "debug": "2.6.9", "es6-promise": "3.2.1", "ignore-by-default": "1.0.1", "lodash.defaults": "3.1.2", @@ -3589,6 +3663,21 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, "postcss": { "version": "5.2.17", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz", @@ -4387,7 +4476,7 @@ "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", "dev": true, "requires": { - "rc": "1.1.7" + "rc": "1.2.1" } }, "regjsgen": { @@ -4471,15 +4560,6 @@ } } }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "2.0.0", - "semver": "5.3.0" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4490,6 +4570,15 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.3.0" + } + }, "resolve-from": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", @@ -4864,14 +4953,6 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", @@ -4891,6 +4972,14 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -4936,13 +5025,13 @@ "requires": { "component-emitter": "1.2.1", "cookiejar": "2.0.6", - "debug": "2.6.8", + "debug": "2.6.9", "extend": "3.0.1", "form-data": "1.0.0-rc4", "formidable": "1.1.1", "methods": "1.1.2", "mime": "1.3.4", - "qs": "6.4.0", + "qs": "6.5.1", "readable-stream": "2.3.3" }, "dependencies": { @@ -4983,13 +5072,13 @@ "requires": { "component-emitter": "1.2.1", "cookiejar": "2.0.6", - "debug": "2.6.8", + "debug": "2.6.9", "extend": "3.0.1", - "form-data": "2.1.4", + "form-data": "2.3.1", "formidable": "1.1.1", "methods": "1.1.2", "mime": "1.3.4", - "qs": "6.4.0", + "qs": "6.5.1", "readable-stream": "2.3.3" } } diff --git a/package.json b/package.json index 1f8e5fa..5739073 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "devDependencies": { "chai": "^4.0.2", "chai-http": "^3.0.0", + "mocha": "^4.0.1", "nodemon": "^1.11.0", "supertest": "^3.0.0" }, diff --git a/server.js b/server.js index 4d596c9..0889de5 100755 --- a/server.js +++ b/server.js @@ -1,25 +1,22 @@ -'use strict'; - /* IMPORTS */ -const - express = require('express'), - bodyParser = require('body-parser'), - expressValidator = require('express-validator'), - cookieParser = require('cookie-parser'), - cookieSession = require('cookie-session'), - debug = require('debug')('tracman-server'), - mongoose = require('mongoose'), - nunjucks = require('nunjucks'), - passport = require('passport'), - flash = require('connect-flash-plus'), - env = require('./config/env/env.js'), - User = require('./config/models.js').user, - mail = require('./config/mail.js'), - demo = require('./config/demo.js'), - app = express(), - http = require('http').Server(app), - io = require('socket.io')(http), - sockets = require('./config/sockets.js'); +const express = require('express') +const bodyParser = require('body-parser') +const expressValidator = require('express-validator') +const cookieParser = require('cookie-parser') +const cookieSession = require('cookie-session') +const debug = require('debug')('tracman-server') +const mongoose = require('mongoose') +const nunjucks = require('nunjucks') +const passport = require('passport') +const flash = require('connect-flash-plus') +const env = require('./config/env/env.js') +const User = require('./config/models.js').user +const mail = require('./config/mail.js') +const demo = require('./config/demo.js') +const app = express() +const http = require('http').Server(app) +const io = require('socket.io')(http) +const sockets = require('./config/sockets.js') /* SETUP */ { @@ -36,8 +33,8 @@ const replset:{socketOptions:{ keepAlive:1, connectTimeoutMS:30000 }} }) - .then( ()=>{ console.log(`💿 Mongoose connected to mongoDB`); }) - .catch( (err)=>{ console.error(`❌ ${err.stack}`); }); + .then( () => { console.log(`💿 Mongoose connected to mongoDB`); }) + .catch( (err) => { console.error(`❌ ${err.stack}`); }); } @@ -45,24 +42,24 @@ const nunjucks.configure(__dirname+'/views', { autoescape: true, express: app - }); - app.set('view engine','html'); + }) + app.set('view engine','html') } /* Session */ { - app.use(cookieParser(env.cookie)); + app.use(cookieParser(env.cookie)) app.use(cookieSession({ cookie: {maxAge:60000}, secret: env.session, saveUninitialized: true, resave: true - })); - app.use(bodyParser.json()); + })) + app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true - })); - app.use(expressValidator()); - app.use(flash()); + })) + app.use(expressValidator()) + app.use(flash()) } /* Auth */ { diff --git a/test.js b/test.js index b5ad665..26ef359 100755 --- a/test.js +++ b/test.js @@ -1,8 +1,8 @@ -const chai = require('chai'), - chaiHttp = require('chai-http'), - request = require('supertest'), - server = require('./server'); -chai.use(chaiHttp); +const chai = require('chai') +const chaiHttp = require('chai-http') +const request = require('supertest') +const server = require('./server') +const chai.use(chaiHttp); describe('Public Pages', () => { @@ -27,7 +27,8 @@ describe('Public Pages', () => { it('Displays privacy policy', (done) => { getPublicPage ('/privacy', done) - + }) + it('Displays robots.txt', done) => { request(server).get('/robots.txt') .expect(200) @@ -36,16 +37,22 @@ describe('Public Pages', () => { }) it('Displays demo map', (done) => { - getPublicPage ('/demo', done) + getPublicPage ('/map/demo', done) }) it('Displays help page', (done) => { getPublicPage ('/help', done) }) + it('Displays contact page', (done) => { + getPublicPage('/contact', done) + }) + + + }) -describe('User', () => { +describe('Accounts', () => { it('Creates an account', (done) => { request(server).post('/signup',{"email":"test@tracman.org"})