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 `

+Tracman

${text}

Do not reply to this email. For information about why you recieved this email, see our privacy policy.

`; + return `

+Tracman

${text}

Do not reply to this email. For information about why you recieved this email, see our privacy policy.

` }, - noReply: `"Tracman" `, + noReply: '"Tracman" ', - to: (user)=>{ - return `"${user.name}" <${user.email}>`; + to: (user) => { + return `"${user.name}" <${user.email}>` } -}; \ No newline at end of file +} diff --git a/config/middleware.js b/config/middleware.js index 3d9853d..ee58f5b 100644 --- a/config/middleware.js +++ b/config/middleware.js @@ -1,11 +1,11 @@ -'use strict'; - -const env = require('./env/env.js'); +const env = require('./env/env.js') +const debug = require('debug')('tracman-middleware') module.exports = { // Throw error - throwErr: (err,req=null)=>{ + throwErr: (err, req=null) => { + debug(`throwErr(${err.message},${req.url})`) console.error(`❌️ ${err.stack}`); if (req){ if (env.mode==='production') { @@ -17,31 +17,35 @@ module.exports = { }, // Capitalize the first letter of a string - capitalize: (str)=>{ + capitalize: (str) => { + debug(`capitalize(${str})`) return str.charAt(0).toUpperCase() + str.slice(1); }, // Validate an email address - validateEmail: (email)=>{ - var re = /^(([^<>()\[\]\\.,;:\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,}))$/; + validateEmail: (email) => { + debug(`validateEmail(${email})`) + const re = /^(([^<>()\[\]\\.,;:\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,}))$/; return re.test(email); }, // Ensure authentication - ensureAuth: (req,res,next)=>{ + ensureAuth: (req, res, next) => { + debug(`ensureAuth(${req.url}, ${res.status}, ${next})`) if (req.isAuthenticated()) { return next(); } else { res.redirect('/login'); } }, // Ensure administrator - ensureAdmin: (req,res,next)=>{ + ensureAdmin: (req, res, next) => { + debug(`ensureAdmin(${req.url}, ${res.status}, ${next})`) if (req.isAuthenticated() && req.user.isAdmin){ return next(); } else { - let err = new Error("Unauthorized"); - err.status = 401; - next(err); + let err = new Error("Unauthorized") + err.status = 401 + next(err) } //TODO: test this by logging in as !isAdmin and go to /admin } -}; \ No newline at end of file +} diff --git a/config/passport.js b/config/passport.js index 5b19619..ecc118f 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,30 +1,29 @@ -'use strict'; - -const - LocalStrategy = require('passport-local').Strategy, - GoogleStrategy = require('passport-google-oauth20').Strategy, - FacebookStrategy = require('passport-facebook').Strategy, - TwitterStrategy = require('passport-twitter').Strategy, - GoogleTokenStrategy = require('passport-google-id-token'), - FacebookTokenStrategy = require('passport-facebook-token'), - TwitterTokenStrategy = require('passport-twitter-token'), - debug = require('debug')('tracman-passport'), - env = require('./env/env.js'), - mw = require('./middleware.js'), - User = require('./models.js').user; +const LocalStrategy = require('passport-local').Strategy +const GoogleStrategy = require('passport-google-oauth20').Strategy +const FacebookStrategy = require('passport-facebook').Strategy +const TwitterStrategy = require('passport-twitter').Strategy +const GoogleTokenStrategy = require('passport-google-id-token') +//const FacebookTokenStrategy = require('passport-facebook-token') +//const TwitterTokenStrategy = require('passport-twitter-token') +const debug = require('debug')('tracman-passport') +const env = require('./env/env.js') +const mw = require('./middleware.js') +const User = require('./models.js').user module.exports = (passport)=>{ // Serialize/deserialize users - passport.serializeUser((user,done)=>{ + passport.serializeUser( (user, done) => { + debug(`serializeUser(${user.id})`) done(null, user.id); - }); - passport.deserializeUser((id,done)=>{ + }) + passport.deserializeUser( (id, done) => { + debug(`deserializeUser(${user.id})`) User.findById(id, (err,user)=>{ if(!err){ done(null, user); } else { done(err, null); } - }); - }); + }) + }) // Local passport.use('local', new LocalStrategy({ @@ -38,12 +37,14 @@ module.exports = (passport)=>{ // No user with that email if (!user) { + debug(`No user with email ${email}`) req.session.next = undefined; return done( null, false, req.flash('warning','Incorrect email or password.') ); } // User exists else { + debug(`User ${user.id} has email ${email}. Checking password ${password}...`) // Check password user.validPassword( password, (err,res)=>{ @@ -51,22 +52,25 @@ module.exports = (passport)=>{ // Password incorrect if (!res) { + debug(`Password ${password} was incorrect`) req.session.next = undefined; return done( null, false, req.flash('warning','Incorrect email or password.') ); } // Successful login - else { + else { + debug(`User ${user.id} logged in with successful local login`) user.lastLogin = Date.now(); user.save(); - return done(null,user); + return done(null, user); } } ); } }) - .catch( (err)=>{ + .catch( (err) => { + debug(`Error searching for user with email ${email}`) return done(err); }); } @@ -86,9 +90,11 @@ module.exports = (passport)=>{ // Can't find user if (!user){ + debug("Can't find user") // Lazy update from old googleId field if (service==='google') { + debug('Checking for old googleId field') User.findOne({ 'googleID': parseInt(profileId,10) }) .then( (user)=>{ @@ -134,9 +140,9 @@ module.exports = (passport)=>{ } } - // Successfull social login + // Successful social login else { - debug(`Found user: ${user.id}; logging in...`); + debug(`Successfully logged in user ${user.id} using ${service}`); req.session.flashType = 'success'; req.session.flashMessage = "You have been logged in."; return done(null, user); @@ -144,7 +150,7 @@ module.exports = (passport)=>{ }) .catch( (err)=>{ - debug(`Failed to find user with query: ${query}`); + debug(`Failed to search for user with query: ${query}`); mw.throwErr(err,req); return done(err); }); @@ -220,15 +226,15 @@ module.exports = (passport)=>{ passReqToCallback: true }, (req, accessToken, refreshToken, profile, done)=>{ socialLogin(req, 'facebook', profile.id, done); - } - )).use('facebook-token', new FacebookTokenStrategy({ - clientID: env.facebookAppId, - clientSecret: env.facebookAppSecret, - passReqToCallback: true - }, (req, accessToken, refreshToken, profile, done)=>{ - socialLogin(req,'facebook', profile.id, done); - } - )); + })) +// .use('facebook-token', new FacebookTokenStrategy({ +// clientID: env.facebookAppId, +// clientSecret: env.facebookAppSecret, +// passReqToCallback: true +// }, (req, accessToken, refreshToken, profile, done)=>{ +// socialLogin(req,'facebook', profile.id, done); +// } +// )) // Twitter passport.use(new TwitterStrategy({ @@ -239,14 +245,15 @@ module.exports = (passport)=>{ }, (req, token, tokenSecret, profile, done)=>{ socialLogin(req, 'twitter', profile.id, done); } - )).use('twitter-token', new TwitterTokenStrategy({ - consumerKey: env.twitterConsumerKey, - consumerSecret: env.twitterConsumerSecret, - passReqToCallback: true - }, (req, token, tokenSecret, profile, done)=>{ - socialLogin(req,'twitter', profile.id, done); - } - )); + )) +// .use('twitter-token', new TwitterTokenStrategy({ +// consumerKey: env.twitterConsumerKey, +// consumerSecret: env.twitterConsumerSecret, +// passReqToCallback: true +// }, (req, token, tokenSecret, profile, done)=>{ +// socialLogin(req,'twitter', profile.id, done); +// } +// )) - return passport; -}; \ No newline at end of file + return passport +}; diff --git a/config/routes/admin.js b/config/routes/admin.js index 3622e11..7897f67 100644 --- a/config/routes/admin.js +++ b/config/routes/admin.js @@ -1,14 +1,14 @@ -'use strict'; +const router = require('express').Router() +const mw = require('../middleware.js') +const debug = require('debug')('tracman-routes-admin') +const User = require('../models.js').user -const router = require('express').Router(), - mw = require('../middleware.js'), - debug = require('debug')('tracman-routes-admin'), - User = require('../models.js').user; - -router.get('/', mw.ensureAdmin, (req,res)=>{ +router.get('/', mw.ensureAdmin, (req,res) => { + debug('Finding all users to populate admin page') User.find({}).sort({lastLogin:-1}) - .then( (found)=>{ + .then( (found) => { + debug(`Found ${found.length} users`) res.render('admin', { active: 'admin', noFooter: '1', @@ -16,24 +16,28 @@ router.get('/', mw.ensureAdmin, (req,res)=>{ total: found.length }); }) - .catch( (err)=>{ mw.throwErr(err,req); }); + .catch( (err) => { + debug('Error searching for all users for admin page') + mw.throwErr(err,req) + }) }); -router.get('/delete/:usrid', mw.ensureAdmin, (req,res,next)=>{ - - debug(`/delete/${req.params.usrid} called`); +router.get('/delete/:usrid', mw.ensureAdmin, (req, res, next) => { + debug(`/admin/delete/${req.params.usrid} called`) User.findOneAndRemove({'_id':req.params.usrid}) .then( (user)=>{ - req.flash('success', `${req.params.usrid} deleted.`); - res.redirect('/admin'); + debug(`Found user with id ${req.params.usrid}`) + req.flash('success', `${req.params.usrid} deleted.`) + res.redirect('/admin') + }) + .catch( (err) => { + debug(`Error searching for user to delete with id of ${req.params.usrid}`) + mw.throwErr(err, req) + res.redirect('/admin') }) - .catch( (err)=>{ - mw.throwErr(err,req); - res.redirect('/admin'); - }); -}); +}) -module.exports = router; +module.exports = router diff --git a/config/routes/auth.js b/config/routes/auth.js index 31eb927..eab4edc 100644 --- a/config/routes/auth.js +++ b/config/routes/auth.js @@ -1,345 +1,395 @@ -'use strict'; - -const - mw = require('../middleware.js'), - mail = require('../mail.js'), - User = require('../models.js').user, - crypto = require('crypto'), - moment = require('moment'), - slugify = require('slug'), - debug = require('debug')('tracman-routes-auth'), - env = require('../env/env.js'); +const mw = require('../middleware.js') +const mail = require('../mail.js') +const User = require('../models.js').user +const crypto = require('crypto') +const moment = require('moment') +const slugify = require('slug') +const debug = require('debug')('tracman-routes-auth') +const env = require('../env/env.js') module.exports = (app, passport) => { // Methods for success and failure - const - loginOutcome = { - failureRedirect: '/login', - failureFlash: true - }, - loginCallback = (req,res)=>{ - debug(`Login callback called... redirecting to ${req.session.next}`); - req.flash(req.session.flashType,req.session.flashMessage); - req.session.flashType = undefined; - req.session.flashMessage = undefined; - res.redirect( req.session.next || '/map' ); - }, - appLoginCallback = (req,res,next)=>{ - debug('appLoginCallback called.'); - if (req.user){ res.send(req.user); } - else { - let err = new Error("Unauthorized"); - err.status = 401; - next(err); - } - }; + const loginOutcome = { + failureRedirect: '/login', + failureFlash: true + } + const loginCallback = (req, res) => { + debug(`Login callback called... redirecting to ${req.session.next}`) + req.flash(req.session.flashType,req.session.flashMessage) + req.session.flashType = undefined + req.session.flashMessage = undefined + res.redirect( req.session.next || '/map' ) + } + const appLoginCallback = (req, res, next) => { + debug('appLoginCallback called.') + if (req.user){ res.send(req.user); } + else { + let err = new Error("Unauthorized") + err.status = 401 + next(err) + } + } - // Login/-out + // Login app.route('/login') - .get( (req,res)=>{ + .get( (req,res) => { + debug(`GET /login... checking if already logged in`) // Already logged in - if (req.isAuthenticated()) { loginCallback(req,res); } + if (req.isAuthenticated()) { + debug(`User is already logged in as ${req.user.id}`) + loginCallback(req,res) // Show login page - else { res.render('login'); } + } else { + debug(`Not logged in yet; showing login page`) + res.render('login') + } }) .post( passport.authenticate('local',loginOutcome), loginCallback ); - app.get('/logout', (req,res)=>{ - req.logout(); - req.flash('success',`You have been logged out.`); - res.redirect( req.session.next || '/' ); - }); + + // Logout + app.get('/logout', (req, res) => { + debug(`Logging out ${req.user.id}`) + req.logout() + req.flash('success',`You have been logged out.`) + res.redirect( req.session.next || '/' ) + }) // Signup app.route('/signup') - .get( (req,res)=>{ - res.redirect('/login#signup'); + .get( (req, res) => { + debug('GET /signup ; redirecting to /login#signup') + res.redirect('/login#signup') }) - .post( (req,res,next)=>{ + .post( (req, res, next) => { + debug('POST /signup') // Send token and alert user function sendToken(user){ - debug(`sendToken() called for user ${user.id}`); + debug(`sendToken() called for user ${user.id}`) // Create a password token - user.createPassToken( (err,token,expires)=>{ - if (err){ - debug(`Error creating password token for user ${user.id}!`); - mw.throwErr(err,req); - res.redirect('/login#signup'); - } - else { - debug(`Created password token for user ${user.id} successfully`); + user.createPassToken( (err, token, expires) => { + if (err) { debug(`Error creating password token for user ${user.id}!`) + mw.throwErr(err, req) + res.redirect('/login#signup') + } else { + debug(`Created password token for user ${user.id} successfully`) // Figure out expiration time let expirationTimeString = (req.query.tz)? moment(expires).utcOffset(req.query.tz).toDate().toLocaleTimeString(req.acceptsLanguages[0]): moment(expires).toDate().toLocaleTimeString(req.acceptsLanguages[0])+" UTC"; + debug(`expirationTimeString set to ${expirationTimeString}`) // Email the instructions to continue - 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}.

`) + 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"})