#107 Cleaned up code and added debugging
parent
706e340c47
commit
9b433afb75
|
@ -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
|
||||
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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 `<h1><a href="/" style="text-decoration:none;"><span style="color:#000;font-family:sans-serif;font-size:36px;font-weight:bold"><img src="${env.url}/static/img/icon/by/32.png" alt="+" style="margin-right:10px">Tracman</span></a></h1>${text}<p style="font-size:8px;">Do not reply to this email. For information about why you recieved this email, see our <a href="${env.url}/privacy#email">privacy policy</a>. </p>`;
|
||||
return `<h1><a href="/" style="text-decoration:none;"><span style="color:#000;font-family:sans-serif;font-size:36px;font-weight:bold"><img src="${env.url}/static/img/icon/by/32.png" alt="+" style="margin-right:10px">Tracman</span></a></h1>${text}<p style="font-size:8px;">Do not reply to this email. For information about why you recieved this email, see our <a href="${env.url}/privacy#email">privacy policy</a>. </p>`
|
||||
},
|
||||
|
||||
noReply: `"Tracman" <NoReply@tracman.org>`,
|
||||
noReply: '"Tracman" <NoReply@tracman.org>',
|
||||
|
||||
to: (user)=>{
|
||||
return `"${user.name}" <${user.email}>`;
|
||||
to: (user) => {
|
||||
return `"${user.name}" <${user.email}>`
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
return passport
|
||||
};
|
||||
|
|
|
@ -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', `<i>${req.params.usrid}</i> deleted.`);
|
||||
res.redirect('/admin');
|
||||
debug(`Found user with id ${req.params.usrid}`)
|
||||
req.flash('success', `<i>${req.params.usrid}</i> 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
|
||||
|
|
|
@ -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(`<p>Welcome to Tracman! </p><p>To complete your registration, follow this link and set your password:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a></p><p>This link will expire at ${expirationTimeString}. </p>`)
|
||||
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(`<p>Welcome to Tracman! </p><p>To complete your registration, follow this link and set your password:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a></p><p>This link will expire at ${expirationTimeString}. </p>`)
|
||||
})
|
||||
.then(()=>{
|
||||
debug(`Successfully emailed new user ${user.id} instructions to continue`);
|
||||
req.flash('success', `An email has been sent to <u>${user.email}</u>. 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 <u>${user.email}</u>. 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 <u>${user.email}</u>. 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 <a href="/login/forgot?email=${req.body.email}">reset it here</a>.`);
|
||||
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 <a href="/login/forgot?email=${req.body.email}">reset it here</a>.`)
|
||||
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 <u>${req.body.email}</u>, an email has been sent there with a password reset link. `);
|
||||
res.redirect('/login');
|
||||
}
|
||||
req.flash('success', `If an account exists with the email <u>${req.body.email}</u>, 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(`<p>Hi, </p><p>Did you request to reset your Tracman password? If so, follow this link to do so:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a></p><p>If you didn't initiate this request, just ignore this email. </p>`)
|
||||
}).then(()=>{
|
||||
req.flash('success', `If an account exists with the email <u>${req.body.email}</u>, 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(`<p>Hi, </p><p>Did you request to reset your Tracman password? If so, follow this link to do so:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a></p><p>If you didn't initiate this request, just ignore this email. </p>`)
|
||||
})
|
||||
|
||||
// Successfully sent reset link
|
||||
.then( () => {
|
||||
debug(`Reset link sent successfully`)
|
||||
req.flash('success', `If an account exists with the email <u>${req.body.email}</u>, 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 <a href="/settings/password">set a password</a> 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 <a href="/settings/password">set a password</a> 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 )
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 )
|
||||
}
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
{
|
||||
"verbose": true,
|
||||
"ext": "html, js, json, css",
|
||||
"events": {
|
||||
"start": "npm run build & npm run minify"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
59
server.js
59
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 */ {
|
||||
|
|
23
test.js
23
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"})
|
||||
|
|
Loading…
Reference in New Issue