Merge branch 'hotfix-0.6.1'
commit
8847b8f402
|
@ -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
|
||||||
|
*
|
56
README.md
56
README.md
|
@ -1,8 +1,9 @@
|
||||||
# <img align="left" src="/static/img/icon/by/48.png" alt="[]" title="The Tracman Logo">Tracman
|
# <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.
|
node.js application to display a sharable map with user's location.
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
@ -15,11 +16,12 @@ A good method is to simply copy the sample configuration and point `config/env/e
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ cp config/env/sample.js config/env/my-config.js
|
$ 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.
|
Then edit `config/env/my-config.js` to match your local environment.
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Run Tracman with npm:
|
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.
|
Nodemon will automatically minify files and restart the app when you make changes. Check out the `nodemon.json` configuration.
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## 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.
|
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
|
## 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
|
#### 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
|
* [#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
|
* [#61](https://github.com/Tracman-org/Server/issues/61) New MongoDB security
|
||||||
* [#62](https://github.com/Tracman-org/Server/issues/62) Fixed error handling
|
* [#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
|
## 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
|
Tracman: GPS tracking service in node.js
|
||||||
Copyright © 2017 [Keith Irwin](https://keithirwin.us/)
|
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.
|
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/)>.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
const mongoose = require('mongoose'),
|
const mongoose = require('mongoose'),
|
||||||
unique = require('mongoose-unique-validator'),
|
unique = require('mongoose-unique-validator'),
|
||||||
bcrypt = require('bcrypt-nodejs'),
|
bcrypt = require('bcrypt'),
|
||||||
crypto = require('crypto');
|
crypto = require('crypto');
|
||||||
|
|
||||||
const userSchema = new mongoose.Schema({
|
const userSchema = new mongoose.Schema({
|
||||||
|
@ -79,7 +79,7 @@ const userSchema = new mongoose.Schema({
|
||||||
|
|
||||||
// Reuse old token, resetting clock
|
// Reuse old token, resetting clock
|
||||||
if ( user.auth.passTokenExpires >= Date.now() ){
|
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.auth.passTokenExpires = Date.now() + 3600000; // 1 hour
|
||||||
user.save()
|
user.save()
|
||||||
.then( ()=>{
|
.then( ()=>{
|
||||||
|
@ -92,7 +92,7 @@ const userSchema = new mongoose.Schema({
|
||||||
|
|
||||||
// Create new token
|
// Create new token
|
||||||
else {
|
else {
|
||||||
console.log(`Creating new password token...`);
|
//console.log(`Creating new password token...`);
|
||||||
crypto.randomBytes(16, (err,buf)=>{
|
crypto.randomBytes(16, (err,buf)=>{
|
||||||
if (err){ return next(err,null,null); }
|
if (err){ return next(err,null,null); }
|
||||||
if (buf) {
|
if (buf) {
|
||||||
|
@ -111,18 +111,31 @@ const userSchema = new mongoose.Schema({
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate hash for new password
|
// Generate hash for new password and save it to the database
|
||||||
userSchema.methods.generateHash = function(password,next){
|
userSchema.methods.generateHashedPassword = function(password,next){
|
||||||
// next(err,hash);
|
// next(err);
|
||||||
bcrypt.genSalt(8)
|
|
||||||
.then( (salt)=>{
|
// Delete token
|
||||||
bcrypt.hash(password, salt, null, next);
|
this.auth.passToken = undefined;
|
||||||
})
|
this.auth.passTokenExpires = undefined;
|
||||||
.catch( (err)=>{ return next(err,null); });
|
|
||||||
|
// 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
|
// Check for valid password
|
||||||
userSchema.methods.validPassword = function(password,next){
|
userSchema.methods.validPassword = function(password,next){
|
||||||
|
// next(err,res);
|
||||||
|
// res = true/false
|
||||||
bcrypt.compare(password, this.auth.password, next);
|
bcrypt.compare(password, this.auth.password, next);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ const
|
||||||
mail = require('../mail.js'),
|
mail = require('../mail.js'),
|
||||||
User = require('../models.js').user,
|
User = require('../models.js').user,
|
||||||
crypto = require('crypto'),
|
crypto = require('crypto'),
|
||||||
|
moment = require('moment'),
|
||||||
env = require('../env/env.js');
|
env = require('../env/env.js');
|
||||||
|
|
||||||
module.exports = (app, passport) => {
|
module.exports = (app, passport) => {
|
||||||
|
@ -61,26 +62,36 @@ module.exports = (app, passport) => {
|
||||||
function sendToken(user){
|
function sendToken(user){
|
||||||
|
|
||||||
// Create a password token
|
// Create a password token
|
||||||
user.createPassToken((err,token)=>{
|
user.createPassToken((err,token,expires)=>{
|
||||||
if (err){ mw.throwErr(err,req); }
|
if (err){
|
||||||
|
|
||||||
// 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)=>{
|
|
||||||
mw.throwErr(err,req);
|
mw.throwErr(err,req);
|
||||||
res.redirect('/login#signup');
|
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');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,30 +232,32 @@ router.route('/password')
|
||||||
mw.throwErr(err,req);
|
mw.throwErr(err,req);
|
||||||
res.redirect((req.user)?'/settings':'/login');
|
res.redirect((req.user)?'/settings':'/login');
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
// Figure out expiration time
|
// Figure out expiration time
|
||||||
let expirationTimeString = (req.query.tz)?
|
let expirationTimeString = (req.query.tz)?
|
||||||
moment(expires).utcOffset(req.query.tz).toDate().toLocaleTimeString(req.acceptsLanguages[0]):
|
moment(expires).utcOffset(req.query.tz).toDate().toLocaleTimeString(req.acceptsLanguages[0]):
|
||||||
moment(expires).toDate().toLocaleTimeString(req.acceptsLanguages[0])+" UTC";
|
moment(expires).toDate().toLocaleTimeString(req.acceptsLanguages[0])+" UTC";
|
||||||
|
|
||||||
// Confirm password change request by email.
|
// Confirm password change request by email.
|
||||||
mail.send({
|
mail.send({
|
||||||
to: mail.to(req.user),
|
to: mail.to(req.user),
|
||||||
from: mail.from,
|
from: mail.from,
|
||||||
subject: 'Request to change your Tracman password',
|
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}. `),
|
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>`)
|
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( ()=>{
|
.then( ()=>{
|
||||||
// Alert user to check email.
|
// 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}). `);
|
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');
|
res.redirect((req.user)?'/settings':'/login');
|
||||||
})
|
})
|
||||||
.catch( (err)=>{
|
.catch( (err)=>{
|
||||||
mw.throwErr(err,req);
|
mw.throwErr(err,req);
|
||||||
res.redirect((req.user)?'/settings':'/login');
|
res.redirect((req.user)?'/settings':'/login');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
@ -299,31 +301,24 @@ router.route('/password/:token')
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// Delete token
|
// Create hashed password and save to db
|
||||||
res.locals.passwordUser.auth.passToken = undefined;
|
res.locals.passwordUser.generateHashedPassword( req.body.password, (err)=>{
|
||||||
res.locals.passwordUser.auth.passTokenExpires = undefined;
|
|
||||||
|
|
||||||
// Create hash
|
|
||||||
res.locals.passwordUser.generateHash( req.body.password, (err,hash)=>{
|
|
||||||
if (err){
|
if (err){
|
||||||
mw.throwErr(err,req);
|
mw.throwErr(err,req);
|
||||||
res.redirect(`/password/${req.params.token}`);
|
res.redirect(`/password/${req.params.token}`);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
// User changed password
|
||||||
// Save new password to db
|
else if (req.user) {
|
||||||
res.locals.passwordUser.auth.password = hash;
|
req.flash('success', 'Your password has been changed. ');
|
||||||
res.locals.passwordUser.save()
|
res.redirect('/settings');
|
||||||
.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');
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// New user created password
|
||||||
|
else {
|
||||||
|
req.flash('success', 'Password set. You can use it to log in now. ');
|
||||||
|
res.redirect('/login#login');
|
||||||
|
}
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
{
|
{
|
||||||
"name": "tracman",
|
"name": "tracman",
|
||||||
"version": "0.6.0",
|
"version": "0.6.1",
|
||||||
"description": "Tracks user's GPS location",
|
"description": "Tracks user's GPS location",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcrypt-nodejs": "0.0.3",
|
"bcrypt": "^1.0.2",
|
||||||
"body-parser": "^1.17.1",
|
"body-parser": "^1.17.1",
|
||||||
"connect-flash": "^0.1.1",
|
|
||||||
"connect-flash-plus": "^0.2.1",
|
"connect-flash-plus": "^0.2.1",
|
||||||
"cookie-parser": "^1.4.1",
|
"cookie-parser": "^1.4.1",
|
||||||
"cookie-session": "^2.0.0-alpha.1",
|
"cookie-session": "^2.0.0-alpha.1",
|
||||||
"express": "^4.15.2",
|
"express": "^4.15.2",
|
||||||
"express-validator": "^3.1.3",
|
"express-validator": "^3.1.3",
|
||||||
"firebase": "^3.7.2",
|
|
||||||
"kerberos": "0.0.17",
|
"kerberos": "0.0.17",
|
||||||
"mellt": "^1.0.0",
|
"mellt": "^1.0.0",
|
||||||
"moment": "^2.12.0",
|
"moment": "^2.12.0",
|
||||||
"mongodb": "^2.1.4",
|
"mongodb": "^2.2.26",
|
||||||
"mongoose": "^4.9.0",
|
"mongoose": "^4.9.0",
|
||||||
"mongoose-unique-validator": "^1.0.5",
|
"mongoose-unique-validator": "^1.0.5",
|
||||||
"node-jose": "^0.8.0",
|
|
||||||
"nodemailer": "^3.1.8",
|
"nodemailer": "^3.1.8",
|
||||||
"nunjucks": "^2.3.0",
|
"nunjucks": "^2.3.0",
|
||||||
"passport": "^0.3.2",
|
"passport": "^0.3.2",
|
||||||
|
|
|
@ -143,9 +143,7 @@ const
|
||||||
// Development handlers
|
// Development handlers
|
||||||
else {
|
else {
|
||||||
app.use( (err,req,res,next)=>{
|
app.use( (err,req,res,next)=>{
|
||||||
if (err.status!==404) {
|
if (err.status!==404) { console.error(`❌ ${err.stack}`); }
|
||||||
console.error(`❌ ${err.stack}`);
|
|
||||||
}
|
|
||||||
if (res.headersSent) { return next(err); }
|
if (res.headersSent) { return next(err); }
|
||||||
res.status(err.status||500);
|
res.status(err.status||500);
|
||||||
res.render('error', {
|
res.render('error', {
|
||||||
|
|
Loading…
Reference in New Issue