Merge branch 'hotfix-0.6.1'

master
Keith Irwin 2017-04-28 15:42:41 -04:00
commit 8847b8f402
No known key found for this signature in database
GPG Key ID: 378933C743E2BBC0
7 changed files with 163 additions and 120 deletions

55
CHANGELOG.md Normal file
View File

@ -0,0 +1,55 @@
# Tracman Server Changelog
###### v 0.6.1
#### v0.6.1
* [#77](https://github.com/Tracman-org/Server/issues/77) Fixed 500 after password change, swapped `bcrypt` for `bcrypt-nodejs`
* Removed extraneous packages
#### v0.6.0
* [#32](https://github.com/Tracman-org/Server/issues/32), [#57](https://github.com/Tracman-org/Server/issues/57), [#58](https://github.com/Tracman-org/Server/issues/58), [#60](https://github.com/Tracman-org/Server/issues/60) Added more login options
* [#50](https://github.com/Tracman-org/Server/issues/50) Replaced some callbacks with promises
* Minified static files
* [#51](https://github.com/Tracman-org/Server/issues/51), [#52](https://github.com/Tracman-org/Server/issues/52) Added settings validations
* [#54](https://github.com/Tracman-org/Server/issues/54), [#55](https://github.com/Tracman-org/Server/issues/55) Made map work better
* [#61](https://github.com/Tracman-org/Server/issues/61) New MongoDB security
* [#62](https://github.com/Tracman-org/Server/issues/62) Fixed error handling
#### v0.5.1
* Fixed broken controls
#### v0.5.0
* Updated libraries
* Fixed recognition of attached clients [#34](https://github.com/Tracman-org/Server/issues/21)
* Moved socket.io code to own file.
* Many minor fixes
#### v0.4.3
* Fixed memory store [#21](https://github.com/Tracman-org/Server/issues/21)
#### v0.4.2
* Fixed Streetview covering buttons
* Fixed error when viewing map of nonexistant user
#### v0.4.1
* Users can view/change email address
* Added linked accounts to admin
#### v0.4.0
* Opened registration
* Replaced 'Imperial' with 'Standard'
* Bug fixes
#### v0.3.0
* Unified map and dashboard UI
* Security updates
* New admin UI
*

View File

@ -1,8 +1,9 @@
# <img align="left" src="/static/img/icon/by/48.png" alt="[]" title="The Tracman Logo">Tracman
###### v 0.6.0
###### v 0.6.1
node.js application to display a sharable map with user's location.
## Installation
```sh
@ -15,11 +16,12 @@ A good method is to simply copy the sample configuration and point `config/env/e
```sh
$ cp config/env/sample.js config/env/my-config.js
$ echo "module.exports = require('./my-config.js');" > config/env/env.js
$ printf "'use strict';\n\nmodule.exports = require('./my-config.js');" > config/env/env.js
```
Then edit `config/env/my-config.js` to match your local environment.
## Usage
Run Tracman with npm:
@ -36,12 +38,21 @@ $ npm run nodemon
Nodemon will automatically minify files and restart the app when you make changes. Check out the `nodemon.json` configuration.
## Contributing
Tracman will be updated according to [this branching model](http://nvie.com/posts/a-successful-git-branching-model)... more or less. If you know anything about programming Android, [the Tracman android app](https://github.com/Tracman-org/Android) is more desperate for help.
## Changelog
[view full changelog](CHANGELOG.md)
#### v0.6.1
* [#77](https://github.com/Tracman-org/Server/issues/77) Fixed 500 after password change, swapped `bcrypt` for `bcrypt-nodejs`
* Removed extraneous packages
#### v0.6.0
* [#32](https://github.com/Tracman-org/Server/issues/32), [#57](https://github.com/Tracman-org/Server/issues/57), [#58](https://github.com/Tracman-org/Server/issues/58), [#60](https://github.com/Tracman-org/Server/issues/60) Added more login options
@ -52,47 +63,10 @@ Tracman will be updated according to [this branching model](http://nvie.com/post
* [#61](https://github.com/Tracman-org/Server/issues/61) New MongoDB security
* [#62](https://github.com/Tracman-org/Server/issues/62) Fixed error handling
#### v0.5.1
* Fixed broken controls
#### v0.5.0
* Updated libraries
* Fixed recognition of attached clients [#34](https://github.com/Tracman-org/Server/issues/21)
* Moved socket.io code to own file.
* Many minor fixes
#### v0.4.3
* Fixed memory store [#21](https://github.com/Tracman-org/Server/issues/21)
#### v0.4.2
* Fixed Streetview covering buttons
* Fixed error when viewing map of nonexistant user
#### v0.4.1
* Users can view/change email address
* Added linked accounts to admin
#### v0.4.0
* Opened registration
* Replaced 'Imperial' with 'Standard'
* Bug fixes
#### v0.3.0
* Unified map and dashboard UI
* Security updates
* New admin UI
## License
###### see [LICENSE.md](https://github.com/Tracman-org/Server/blob/master/LICENSE.md)
[view full license](LICENSE.md)
Tracman: GPS tracking service in node.js
Copyright © 2017 [Keith Irwin](https://keithirwin.us/)
@ -101,4 +75,4 @@ This program is free software: you can redistribute it and/or modify it under th
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/)>.
You should have received a copy of the GNU General Public License along with this program. If not, see <[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/)>.

View File

@ -2,7 +2,7 @@
const mongoose = require('mongoose'),
unique = require('mongoose-unique-validator'),
bcrypt = require('bcrypt-nodejs'),
bcrypt = require('bcrypt'),
crypto = require('crypto');
const userSchema = new mongoose.Schema({
@ -79,7 +79,7 @@ const userSchema = new mongoose.Schema({
// Reuse old token, resetting clock
if ( user.auth.passTokenExpires >= Date.now() ){
console.log(`Reusing old password token...`);
//console.log(`Reusing old password token...`);
user.auth.passTokenExpires = Date.now() + 3600000; // 1 hour
user.save()
.then( ()=>{
@ -92,7 +92,7 @@ const userSchema = new mongoose.Schema({
// Create new token
else {
console.log(`Creating new password token...`);
//console.log(`Creating new password token...`);
crypto.randomBytes(16, (err,buf)=>{
if (err){ return next(err,null,null); }
if (buf) {
@ -111,18 +111,31 @@ const userSchema = new mongoose.Schema({
};
// Generate hash for new password
userSchema.methods.generateHash = function(password,next){
// next(err,hash);
bcrypt.genSalt(8)
.then( (salt)=>{
bcrypt.hash(password, salt, null, next);
})
.catch( (err)=>{ return next(err,null); });
// Generate hash for new password and save it to the database
userSchema.methods.generateHashedPassword = function(password,next){
// next(err);
// Delete token
this.auth.passToken = undefined;
this.auth.passTokenExpires = undefined;
// Generate hash
bcrypt.genSalt(8, (err,salt)=>{
if (err){ return next(err); }
bcrypt.hash(password, salt, (err,hash)=>{
if (err){ return next(err); }
this.auth.password = hash;
this.save();
next();
});
});
};
// Check for valid password
userSchema.methods.validPassword = function(password,next){
// next(err,res);
// res = true/false
bcrypt.compare(password, this.auth.password, next);
};

View File

@ -5,6 +5,7 @@ const
mail = require('../mail.js'),
User = require('../models.js').user,
crypto = require('crypto'),
moment = require('moment'),
env = require('../env/env.js');
module.exports = (app, passport) => {
@ -61,26 +62,36 @@ module.exports = (app, passport) => {
function sendToken(user){
// Create a password token
user.createPassToken((err,token)=>{
if (err){ mw.throwErr(err,req); }
// Email the instructions to continue
mail.send({
from: mail.from,
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}`),
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>`)
})
.then(()=>{
req.flash('success', `An email has been sent to <u>${user.email}</u>. Check your inbox to complete your registration. `);
res.redirect('/login');
})
.catch((err)=>{
user.createPassToken((err,token,expires)=>{
if (err){
mw.throwErr(err,req);
res.redirect('/login#signup');
});
}
else {
// 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";
// Email the instructions to continue
mail.send({
from: mail.from,
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(()=>{
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)=>{
mw.throwErr(err,req);
res.redirect('/login#signup');
});
}
});
}

View File

@ -232,30 +232,32 @@ router.route('/password')
mw.throwErr(err,req);
res.redirect((req.user)?'/settings':'/login');
}
else {
// 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";
// Confirm password change request by email.
mail.send({
to: mail.to(req.user),
from: mail.from,
subject: 'Request to change your Tracman password',
text: mail.text(`A request has been made to change your tracman password. If you did not initiate this request, please contact support at keith@tracman.org. \n\nTo change your password, follow this link:\n${env.url}/settings/password/${token}. \n\nThis request will expire at ${expirationTimeString}. `),
html: mail.html(`<p>A request has been made to change your tracman password. If you did not initiate this request, please contact support at <a href="mailto:keith@tracman.org">keith@tracman.org</a>. </p><p>To change your password, follow this link:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a>. </p><p>This request will expire at ${expirationTimeString}. </p>`)
})
.then( ()=>{
// Alert user to check email.
req.flash('success',`An link has been sent to <u>${req.user.email}</u>. Click on the link to complete your password change. This link will expire in one hour (${expirationTimeString}). `);
res.redirect((req.user)?'/settings':'/login');
})
.catch( (err)=>{
mw.throwErr(err,req);
res.redirect((req.user)?'/settings':'/login');
});
// 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";
// Confirm password change request by email.
mail.send({
to: mail.to(req.user),
from: mail.from,
subject: 'Request to change your Tracman password',
text: mail.text(`A request has been made to change your tracman password. If you did not initiate this request, please contact support at keith@tracman.org. \n\nTo change your password, follow this link:\n${env.url}/settings/password/${token}. \n\nThis request will expire at ${expirationTimeString}. `),
html: mail.html(`<p>A request has been made to change your tracman password. If you did not initiate this request, please contact support at <a href="mailto:keith@tracman.org">keith@tracman.org</a>. </p><p>To change your password, follow this link:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a>. </p><p>This request will expire at ${expirationTimeString}. </p>`)
})
.then( ()=>{
// Alert user to check email.
req.flash('success',`An link has been sent to <u>${req.user.email}</u>. Click on the link to complete your password change. This link will expire in one hour (${expirationTimeString}). `);
res.redirect((req.user)?'/settings':'/login');
})
.catch( (err)=>{
mw.throwErr(err,req);
res.redirect((req.user)?'/settings':'/login');
});
}
});
} );
@ -299,31 +301,24 @@ router.route('/password/:token')
else {
// Delete token
res.locals.passwordUser.auth.passToken = undefined;
res.locals.passwordUser.auth.passTokenExpires = undefined;
// Create hash
res.locals.passwordUser.generateHash( req.body.password, (err,hash)=>{
// Create hashed password and save to db
res.locals.passwordUser.generateHashedPassword( req.body.password, (err)=>{
if (err){
mw.throwErr(err,req);
res.redirect(`/password/${req.params.token}`);
}
else {
// Save new password to db
res.locals.passwordUser.auth.password = hash;
res.locals.passwordUser.save()
.then( ()=>{
req.flash('success', 'Password set. You can use it to log in now. ');
res.redirect('/login#login');
})
.catch( (err)=>{
mw.throwErr(err,req);
res.redirect('/login#signup');
});
// User changed password
else if (req.user) {
req.flash('success', 'Your password has been changed. ');
res.redirect('/settings');
}
// New user created password
else {
req.flash('success', 'Password set. You can use it to log in now. ');
res.redirect('/login#login');
}
} );
}

View File

@ -1,25 +1,22 @@
{
"name": "tracman",
"version": "0.6.0",
"version": "0.6.1",
"description": "Tracks user's GPS location",
"main": "server.js",
"dependencies": {
"bcrypt-nodejs": "0.0.3",
"bcrypt": "^1.0.2",
"body-parser": "^1.17.1",
"connect-flash": "^0.1.1",
"connect-flash-plus": "^0.2.1",
"cookie-parser": "^1.4.1",
"cookie-session": "^2.0.0-alpha.1",
"express": "^4.15.2",
"express-validator": "^3.1.3",
"firebase": "^3.7.2",
"kerberos": "0.0.17",
"mellt": "^1.0.0",
"moment": "^2.12.0",
"mongodb": "^2.1.4",
"mongodb": "^2.2.26",
"mongoose": "^4.9.0",
"mongoose-unique-validator": "^1.0.5",
"node-jose": "^0.8.0",
"nodemailer": "^3.1.8",
"nunjucks": "^2.3.0",
"passport": "^0.3.2",

View File

@ -143,9 +143,7 @@ const
// Development handlers
else {
app.use( (err,req,res,next)=>{
if (err.status!==404) {
console.error(`${err.stack}`);
}
if (err.status!==404) { console.error(`${err.stack}`); }
if (res.headersSent) { return next(err); }
res.status(err.status||500);
res.render('error', {