From f16abf08c24674ea204aa2e696da6b587d9c78dc Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 30 Nov 2017 14:46:32 -0800 Subject: [PATCH 1/8] added endpoint to update password --- helpers/authHelpers.js | 49 ++++++++++++++++++++++++--------------- helpers/publishHelpers.js | 18 ++++++++++---- models/user.js | 33 +++++++++++++++++++++++++- passport/local-login.js | 33 +++++++++----------------- routes/api-routes.js | 42 ++++++++++++++++++++++++++++++++- routes/auth-routes.js | 2 +- speech.js | 14 +++++------ 7 files changed, 136 insertions(+), 55 deletions(-) diff --git a/helpers/authHelpers.js b/helpers/authHelpers.js index 455ddd9a..dc2f5548 100644 --- a/helpers/authHelpers.js +++ b/helpers/authHelpers.js @@ -14,31 +14,42 @@ module.exports = { } next(); }, - serializeSpeechUser (user, done) { + serializeSpeechUser (user, done) { // returns user id to be serialized into session token + logger.debug('serializing session'); done(null, user.id); }, - deserializeSpeechUser (id, done) { - let userInfo = {}; - db.User.findOne({ where: { id } }) + deserializeSpeechUser (id, done) { // deserializes session token and provides user from user id + logger.debug('deserializing session'); + return db.User.findOne({ where: { id } }) .then(user => { - userInfo['id'] = user.id; - userInfo['userName'] = user.userName; - return user.getChannel(); + return module.exports.returnUserAndChannelInfo(user); }) - .then(channel => { - userInfo['channelName'] = channel.channelName; - userInfo['channelClaimId'] = channel.channelClaimId; - return db.Certificate.getShortChannelIdFromLongChannelId(channel.channelClaimId, channel.channelName); - }) - .then(shortChannelId => { - userInfo['shortChannelId'] = shortChannelId; - // return done(null, userInfo); - done(null, userInfo); - return null; + .then((userInfo) => { + return done(null, userInfo); }) .catch(error => { - logger.error(error); - done(error, null); + return done(error); + }); + }, + returnUserAndChannelInfo (userInstance) { + return new Promise((resolve, reject) => { + let userInfo = {}; + userInfo['id'] = userInstance.id; + userInfo['userName'] = userInstance.userName; + userInstance + .getChannel() + .then(({channelName, channelClaimId}) => { + userInfo['channelName'] = channelName; + userInfo['channelClaimId'] = channelClaimId; + return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName); + }) + .then(shortChannelId => { + userInfo['shortChannelId'] = shortChannelId; + resolve(userInfo); + }) + .catch(error => { + reject(error); + }); }); }, }; diff --git a/helpers/publishHelpers.js b/helpers/publishHelpers.js index 25c715c1..d218c844 100644 --- a/helpers/publishHelpers.js +++ b/helpers/publishHelpers.js @@ -76,13 +76,23 @@ module.exports = { } }, cleanseChannelName (channelName) { - if (channelName) { - if (channelName.indexOf('@') !== 0) { - channelName = `@${channelName}`; - } + if (!channelName) { + return null; + } + if (channelName.indexOf('@') !== 0) { + channelName = `@${channelName}`; } return channelName; }, + cleanseUserName (userName) { + if (!userName) { + return null; + } + if (userName.indexOf('@') !== -1) { + userName = userName.substring(userName.indexOf('@')); + } + return userName; + }, createPublishParams (filePath, name, title, description, license, nsfw, thumbnail, channelName) { logger.debug(`Creating Publish Parameters`); // provide defaults for title diff --git a/models/user.js b/models/user.js index 7c7bfe13..55f75114 100644 --- a/models/user.js +++ b/models/user.js @@ -28,9 +28,40 @@ module.exports = (sequelize, { STRING }) => { bcrypt.compare(password, this.password, callback); }; + User.prototype.changePassword = function (newPassword) { + return new Promise((resolve, reject) => { + // generate a salt string to use for hashing + bcrypt.genSalt((saltError, salt) => { + if (saltError) { + logger.error('salt error', saltError); + reject(saltError); + return; + } + // generate a hashed version of the user's password + bcrypt.hash(newPassword, salt, (hashError, hash) => { + // if there is an error with the hash generation return the error + if (hashError) { + logger.error('hash error', hashError); + reject(hashError); + return; + } + // replace the current password with the new hash + this + .update({password: hash}) + .then(() => { + resolve(); + }) + .catch(error => { + reject(error); + }); + }); + }); + }); + }; + // pre-save hook method to hash the user's password before the user's info is saved to the db. User.hook('beforeCreate', (user, options) => { - logger.debug('...beforeCreate hook...'); + logger.debug('User.beforeCreate hook...'); return new Promise((resolve, reject) => { // generate a salt string to use for hashing bcrypt.genSalt((saltError, salt) => { diff --git a/passport/local-login.js b/passport/local-login.js index 473f875a..37a1cb67 100644 --- a/passport/local-login.js +++ b/passport/local-login.js @@ -2,6 +2,7 @@ const PassportLocalStrategy = require('passport-local').Strategy; const db = require('../models'); const logger = require('winston'); +const { returnUserAndChannelInfo } = require('../helpers/authHelpers.js'); module.exports = new PassportLocalStrategy( { @@ -11,43 +12,31 @@ module.exports = new PassportLocalStrategy( passReqToCallback: true, }, (req, username, password, done) => { - logger.debug(`verifying loggin attempt ${username} ${password}`); - let userInfo = {}; - return db.User + logger.debug('logging user in'); + return db + .User .findOne({where: {userName: username}}) .then(user => { if (!user) { - logger.debug('no user found'); + // logger.debug('no user found'); return done(null, false, {message: 'Incorrect username or password.'}); } - logger.debug('user found:', user.dataValues); - logger.debug('...comparing password...'); return user.comparePassword(password, (passwordErr, isMatch) => { if (passwordErr) { logger.error('passwordErr:', passwordErr); - return done(passwordErr); + return done(null, false, {message: passwordErr}); } - if (!isMatch) { - logger.debug('incorrect password'); + // logger.debug('incorrect password'); return done(null, false, {message: 'Incorrect username or password.'}); } - logger.debug('...password was a match...'); - userInfo['id'] = user.id; - userInfo['userName'] = user.userName; - // get the User's channel info - return user.getChannel() - .then(channel => { - userInfo['channelName'] = channel.channelName; - userInfo['channelClaimId'] = channel.channelClaimId; - return db.Certificate.getShortChannelIdFromLongChannelId(channel.channelClaimId, channel.channelName); - }) - .then(shortChannelId => { - userInfo['shortChannelId'] = shortChannelId; + logger.debug('Password was a match, returning User'); + return returnUserAndChannelInfo(user) + .then((userInfo) => { return done(null, userInfo); }) .catch(error => { - throw error; + return done(error); }); }); }) diff --git a/routes/api-routes.js b/routes/api-routes.js index 38b5b1e8..3326f137 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -5,7 +5,7 @@ const multipartMiddleware = multipart({uploadDir: config.files.uploadDirectory}) const db = require('../models'); const { publish } = require('../controllers/publishController.js'); const { getClaimList, resolveUri } = require('../helpers/lbryApi.js'); -const { createPublishParams, validateApiPublishRequest, validatePublishSubmission, cleanseChannelName, checkClaimNameAvailability, checkChannelAvailability } = require('../helpers/publishHelpers.js'); +const { createPublishParams, validateApiPublishRequest, validatePublishSubmission, cleanseChannelName, cleanseUserName, checkClaimNameAvailability, checkChannelAvailability } = require('../helpers/publishHelpers.js'); const errorHandlers = require('../helpers/errorHandlers.js'); const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js'); const { authenticateOrSkip } = require('../auth/authentication.js'); @@ -185,4 +185,44 @@ module.exports = (app) => { errorHandlers.handleApiError('short channel id', originalUrl, ip, error, res); }); }); + app.put('/api/password', ({ body, ip, originalUrl }, res) => { + let userName; + let { channelName, oldPassword, newPassword } = body; + // validate all necessary params were provided + if (!channelName || !oldPassword || !newPassword) { + res.status(400).json({success: false, message: 'provide channelName, oldPassword, and newPassword'}); + } + // cleanse channel name + userName = cleanseUserName(channelName); + // validate password and respond + db + .User + .findOne({where: {userName: userName}}) + .then(user => { + if (!user) { + return res.status(401).json({success: false, message: 'Incorrect username or password.'}); + } + return user.comparePassword(oldPassword, (passwordErr, isMatch) => { + if (passwordErr) { + throw passwordErr; + } + if (!isMatch) { + return res.status(401).json({success: false, message: 'Incorrect username or password.'}); + } + logger.debug('Password was a match, updating password'); + return user + .changePassword(newPassword) + .then(() => { + logger.debug('Password successfully updated'); + res.status(200).json({success: true, message: 'password successfully changed'}); + }) + .catch(error => { + throw error; + }); + }); + }) + .catch(error => { + errorHandlers.handleApiError('password reset', originalUrl, ip, error, res); + }); + }); }; diff --git a/routes/auth-routes.js b/routes/auth-routes.js index c1650009..01419e1b 100644 --- a/routes/auth-routes.js +++ b/routes/auth-routes.js @@ -14,7 +14,7 @@ module.exports = (app) => { }); // route for log in app.post('/login', passport.authenticate('local-login'), (req, res) => { - logger.debug('req.user:', req.user); + // logger.debug('req.user:', req.user); // req.user contains the authenticated user's info logger.debug('successful login'); res.status(200).json({ success : true, diff --git a/speech.js b/speech.js index 7e7a4e5f..3b03adea 100644 --- a/speech.js +++ b/speech.js @@ -33,10 +33,16 @@ app.use(bodyParser.json()); // 'body parser' for parsing application/json app.use(bodyParser.urlencoded({ extended: true })); // 'body parser' for parsing application/x-www-form-urlencoded app.use((req, res, next) => { // custom logging middleware to log all incoming http requests logger.verbose(`Request on ${req.originalUrl} from ${req.ip}`); - logger.debug('req.body:', req.body); next(); }); +// configure passport +passport.serializeUser(serializeSpeechUser); +passport.deserializeUser(deserializeSpeechUser); +const localSignupStrategy = require('./passport/local-signup.js'); +const localLoginStrategy = require('./passport/local-login.js'); +passport.use('local-signup', localSignupStrategy); +passport.use('local-login', localLoginStrategy); // initialize passport app.use(cookieSession({ name : 'session', @@ -45,12 +51,6 @@ app.use(cookieSession({ })); app.use(passport.initialize()); app.use(passport.session()); -passport.serializeUser(serializeSpeechUser); // takes the user id from the db and serializes it -passport.deserializeUser(deserializeSpeechUser); // this deserializes id then populates req.user with info -const localSignupStrategy = require('./passport/local-signup.js'); -const localLoginStrategy = require('./passport/local-login.js'); -passport.use('local-signup', localSignupStrategy); -passport.use('local-login', localLoginStrategy); // configure handlebars & register it with express app const hbs = expressHandlebars.create({ -- 2.45.2 From 7b7627ab2751edae3c535ce0669f64ccc9e6fdf1 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 30 Nov 2017 15:13:17 -0800 Subject: [PATCH 2/8] removed unnecessary local strategy options; --- passport/local-login.js | 9 ++++----- passport/local-signup.js | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/passport/local-login.js b/passport/local-login.js index 37a1cb67..5910d96a 100644 --- a/passport/local-login.js +++ b/passport/local-login.js @@ -6,12 +6,11 @@ const { returnUserAndChannelInfo } = require('../helpers/authHelpers.js'); module.exports = new PassportLocalStrategy( { - usernameField : 'username', // username key in the request body - passwordField : 'password', // password key in the request body - session : false, - passReqToCallback: true, + usernameField: 'username', + passwordField: 'password', + // session : false, }, - (req, username, password, done) => { + (username, password, done) => { logger.debug('logging user in'); return db .User diff --git a/passport/local-signup.js b/passport/local-signup.js index 48f48e37..def287a1 100644 --- a/passport/local-signup.js +++ b/passport/local-signup.js @@ -5,12 +5,11 @@ const logger = require('winston'); module.exports = new PassportLocalStrategy( { - usernameField : 'username', // sets the custom name of parameters in the POST body message - passwordField : 'password', // sets the custom name of parameters in the POST body message - session : false, // set to false because we will use token approach to auth - passReqToCallback: true, // we want to be able to read the post body message parameters in the callback + usernameField: 'username', + passwordField: 'password', + // session: false, // set to false because we will use token approach to auth }, - (req, username, password, done) => { + (username, password, done) => { logger.verbose(`new channel signup request. user: ${username} pass: ${password} .`); let userInfo = {}; // server-side validaton of inputs (username, password) -- 2.45.2 From c509c35926d35448185e4c54eb260a6a974a1db8 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 30 Nov 2017 17:24:48 -0800 Subject: [PATCH 3/8] changed passport session strategy to store user info --- helpers/authHelpers.js | 45 +++++++--------------------------------- passport/local-login.js | 27 ++++++++++++++++++++---- passport/local-signup.js | 1 - 3 files changed, 31 insertions(+), 42 deletions(-) diff --git a/helpers/authHelpers.js b/helpers/authHelpers.js index dc2f5548..e9bf0210 100644 --- a/helpers/authHelpers.js +++ b/helpers/authHelpers.js @@ -1,9 +1,10 @@ -const db = require('../models'); // require our models for syncing +// const db = require('../models'); // require our models for syncing const logger = require('winston'); module.exports = { populateLocalsDotUser (req, res, next) { if (req.user) { + logger.debug('populating res.locals.user'); res.locals.user = { id : req.user.id, userName : req.user.userName, @@ -14,42 +15,12 @@ module.exports = { } next(); }, - serializeSpeechUser (user, done) { // returns user id to be serialized into session token - logger.debug('serializing session'); - done(null, user.id); + serializeSpeechUser (user, done) { // returns user data to be serialized into session + logger.debug('serializing user'); + done(null, user); }, - deserializeSpeechUser (id, done) { // deserializes session token and provides user from user id - logger.debug('deserializing session'); - return db.User.findOne({ where: { id } }) - .then(user => { - return module.exports.returnUserAndChannelInfo(user); - }) - .then((userInfo) => { - return done(null, userInfo); - }) - .catch(error => { - return done(error); - }); - }, - returnUserAndChannelInfo (userInstance) { - return new Promise((resolve, reject) => { - let userInfo = {}; - userInfo['id'] = userInstance.id; - userInfo['userName'] = userInstance.userName; - userInstance - .getChannel() - .then(({channelName, channelClaimId}) => { - userInfo['channelName'] = channelName; - userInfo['channelClaimId'] = channelClaimId; - return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName); - }) - .then(shortChannelId => { - userInfo['shortChannelId'] = shortChannelId; - resolve(userInfo); - }) - .catch(error => { - reject(error); - }); - }); + deserializeSpeechUser (user, done) { // deserializes session and populates additional info to req.user + logger.debug('deserializing user'); + done(null, user); }, }; diff --git a/passport/local-login.js b/passport/local-login.js index 5910d96a..e3d72e88 100644 --- a/passport/local-login.js +++ b/passport/local-login.js @@ -1,14 +1,33 @@ - const PassportLocalStrategy = require('passport-local').Strategy; const db = require('../models'); const logger = require('winston'); -const { returnUserAndChannelInfo } = require('../helpers/authHelpers.js'); + +function returnUserAndChannelInfo (userInstance) { + return new Promise((resolve, reject) => { + let userInfo = {}; + userInfo['id'] = userInstance.id; + userInfo['userName'] = userInstance.userName; + userInstance + .getChannel() + .then(({channelName, channelClaimId}) => { + userInfo['channelName'] = channelName; + userInfo['channelClaimId'] = channelClaimId; + return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName); + }) + .then(shortChannelId => { + userInfo['shortChannelId'] = shortChannelId; + resolve(userInfo); + }) + .catch(error => { + reject(error); + }); + }); +} module.exports = new PassportLocalStrategy( { usernameField: 'username', passwordField: 'password', - // session : false, }, (username, password, done) => { logger.debug('logging user in'); @@ -20,7 +39,7 @@ module.exports = new PassportLocalStrategy( // logger.debug('no user found'); return done(null, false, {message: 'Incorrect username or password.'}); } - return user.comparePassword(password, (passwordErr, isMatch) => { + user.comparePassword(password, (passwordErr, isMatch) => { if (passwordErr) { logger.error('passwordErr:', passwordErr); return done(null, false, {message: passwordErr}); diff --git a/passport/local-signup.js b/passport/local-signup.js index def287a1..83639248 100644 --- a/passport/local-signup.js +++ b/passport/local-signup.js @@ -7,7 +7,6 @@ module.exports = new PassportLocalStrategy( { usernameField: 'username', passwordField: 'password', - // session: false, // set to false because we will use token approach to auth }, (username, password, done) => { logger.verbose(`new channel signup request. user: ${username} pass: ${password} .`); -- 2.45.2 From 272e4747ab03f2e94b4f50a85825cd33ed2d318c Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 30 Nov 2017 18:23:27 -0800 Subject: [PATCH 4/8] minimized cookie usage as state --- public/assets/js/createChannelFunctions.js | 12 +++++------ public/assets/js/loginFunctions.js | 23 +++++++--------------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/public/assets/js/createChannelFunctions.js b/public/assets/js/createChannelFunctions.js index dbcf4e49..fb0129d8 100644 --- a/public/assets/js/createChannelFunctions.js +++ b/public/assets/js/createChannelFunctions.js @@ -33,15 +33,13 @@ function publishNewChannel (event) { return sendAuthRequest(userName, password, '/signup') // post the request }) .then(result => { + setUserCookies(result.channelName, result.channelClaimId, result.shortChannelId); showChannelCreateDoneDisplay(); - // refresh window logged in as the channel - setUserCookies(result.channelName, result.channelClaimId, result.shortChannelId); // set cookies - }) - .then(() => { + // if user is on the home page, update the needed elements without reloading if (window.location.pathname === '/') { - // remove old channel and replace with new one & select it - replaceChannelOptionInPublishChannelSelect(); - replaceChannelOptionInNavBarChannelSelect(); + replaceChannelOptionInPublishChannelSelect(result.channelName); + replaceChannelOptionInNavBarChannelSelect(result.channelName); + // if user is not on home page, redirect to home page } else { window.location = '/'; } diff --git a/public/assets/js/loginFunctions.js b/public/assets/js/loginFunctions.js index 5f3a13b0..569cbb53 100644 --- a/public/assets/js/loginFunctions.js +++ b/public/assets/js/loginFunctions.js @@ -1,11 +1,9 @@ -function replaceChannelOptionInPublishChannelSelect() { +function replaceChannelOptionInPublishChannelSelect(loggedInChannel) { // remove the old channel option const oldChannel = document.getElementById('publish-channel-select-channel-option') if (oldChannel){ oldChannel.parentNode.removeChild(oldChannel); } - // get channel details from cookies - const loggedInChannel = getCookie('channel_name'); // create new channel option const newChannelOption = document.createElement('option'); newChannelOption.setAttribute('value', loggedInChannel); @@ -19,14 +17,12 @@ function replaceChannelOptionInPublishChannelSelect() { toggleSelectedChannel(loggedInChannel); } -function replaceChannelOptionInNavBarChannelSelect () { +function replaceChannelOptionInNavBarChannelSelect (loggedInChannel) { // remove the old channel option const oldChannel = document.getElementById('nav-bar-channel-select-channel-option'); if (oldChannel){ oldChannel.parentNode.removeChild(oldChannel); } - // get channel details from cookies - const loggedInChannel = getCookie('channel_name'); // create new channel option & select it const newChannelOption = document.createElement('option'); newChannelOption.setAttribute('value', loggedInChannel); @@ -49,20 +45,15 @@ function loginToChannel (event) { event.preventDefault() validationFunctions.validateNewChannelLogin(userName, password) .then(() => { - // send request return sendAuthRequest(userName, password, '/login') }) .then(result => { - // update session cookie with new channel name and id's - setUserCookies(result.channelName, result.channelClaimId, result.shortChannelId); // replace the current cookies - }) - .then(() => { - // update channel selection + setUserCookies(result.channelName, result.channelClaimId, result.shortChannelId); + // if user is on the home page, update the needed elements without reloading if (window.location.pathname === '/') { - // remove old channel and replace with new one & select it - replaceChannelOptionInPublishChannelSelect(); - // remove old channel and replace with new one & select it - replaceChannelOptionInNavBarChannelSelect(); + replaceChannelOptionInPublishChannelSelect(result.channelName); + replaceChannelOptionInNavBarChannelSelect(result.channelName); + // if user is not on home page, redirect to home page } else { window.location = '/'; } -- 2.45.2 From 9ad99c5ac1e78ae752a479897502d5aead0645a2 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 08:55:02 -0800 Subject: [PATCH 5/8] removed change password api route --- helpers/publishHelpers.js | 14 ------------- routes/api-routes.js | 42 +-------------------------------------- 2 files changed, 1 insertion(+), 55 deletions(-) diff --git a/helpers/publishHelpers.js b/helpers/publishHelpers.js index d218c844..329f6787 100644 --- a/helpers/publishHelpers.js +++ b/helpers/publishHelpers.js @@ -70,11 +70,6 @@ module.exports = { throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"'); } }, - validateLicense (license) { - if ((license.indexOf('Public Domain') === -1) && (license.indexOf('Creative Commons') === -1)) { - throw new Error('Only posts with a "Public Domain" or "Creative Commons" license are eligible for publishing through spee.ch'); - } - }, cleanseChannelName (channelName) { if (!channelName) { return null; @@ -84,15 +79,6 @@ module.exports = { } return channelName; }, - cleanseUserName (userName) { - if (!userName) { - return null; - } - if (userName.indexOf('@') !== -1) { - userName = userName.substring(userName.indexOf('@')); - } - return userName; - }, createPublishParams (filePath, name, title, description, license, nsfw, thumbnail, channelName) { logger.debug(`Creating Publish Parameters`); // provide defaults for title diff --git a/routes/api-routes.js b/routes/api-routes.js index 03f35454..95bf222b 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -5,7 +5,7 @@ const multipartMiddleware = multipart({uploadDir: config.files.uploadDirectory}) const db = require('../models'); const { publish } = require('../controllers/publishController.js'); const { getClaimList, resolveUri, getClaim } = require('../helpers/lbryApi.js'); -const { createPublishParams, validateApiPublishRequest, validatePublishSubmission, cleanseChannelName, cleanseUserName, checkClaimNameAvailability, checkChannelAvailability } = require('../helpers/publishHelpers.js'); +const { createPublishParams, validateApiPublishRequest, validatePublishSubmission, cleanseChannelName, checkClaimNameAvailability, checkChannelAvailability } = require('../helpers/publishHelpers.js'); const errorHandlers = require('../helpers/errorHandlers.js'); const { authenticateOrSkip } = require('../auth/authentication.js'); @@ -234,44 +234,4 @@ module.exports = (app) => { errorHandlers.handleApiError(originalUrl, ip, error, res); }); }); - app.put('/api/password', ({ body, ip, originalUrl }, res) => { - let userName; - let { channelName, oldPassword, newPassword } = body; - // validate all necessary params were provided - if (!channelName || !oldPassword || !newPassword) { - res.status(400).json({success: false, message: 'provide channelName, oldPassword, and newPassword'}); - } - // cleanse channel name - userName = cleanseUserName(channelName); - // validate password and respond - db - .User - .findOne({where: {userName: userName}}) - .then(user => { - if (!user) { - return res.status(401).json({success: false, message: 'Incorrect username or password.'}); - } - return user.comparePassword(oldPassword, (passwordErr, isMatch) => { - if (passwordErr) { - throw passwordErr; - } - if (!isMatch) { - return res.status(401).json({success: false, message: 'Incorrect username or password.'}); - } - logger.debug('Password was a match, updating password'); - return user - .changePassword(newPassword) - .then(() => { - logger.debug('Password successfully updated'); - res.status(200).json({success: true, message: 'password successfully changed'}); - }) - .catch(error => { - throw error; - }); - }); - }) - .catch(error => { - errorHandlers.handleApiError('password reset', originalUrl, ip, error, res); - }); - }); }; -- 2.45.2 From c7ad52216dd31c0ba948e28768b292dd79405ec4 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 09:21:20 -0800 Subject: [PATCH 6/8] added update-passwords script --- update-password.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 update-password.js diff --git a/update-password.js b/update-password.js new file mode 100644 index 00000000..5b94e93c --- /dev/null +++ b/update-password.js @@ -0,0 +1,41 @@ +// load dependencies +const logger = require('winston'); +const db = require('./models'); // require our models for syncing + +const userName = process.argv[2]; +logger.debug('user name:', userName); +const oldPassword = process.argv[3]; +logger.debug('old password:', oldPassword); +const newPassword = process.argv[4]; +logger.debug('new password:', newPassword); + +db.sequelize.sync() // sync sequelize + .then(() => { + logger.info('finding user profile'); + return db.User.findOne({ + where: { + userName: userName, + }, + }); + }) + .then(user => { + if (!user) { + throw new Error('no user found'); + } + return user.comparePassword(oldPassword, (passwordErr, isMatch) => { + if (passwordErr) { + throw passwordErr; + } + if (!isMatch) { + throw new Error('Incorrect old password.'); + } + logger.debug('Password was a match, updating password'); + return user.changePassword(newPassword); + }); + }) + .then(() => { + logger.debug('Password successfully updated'); + }) + .catch((error) => { + logger.error('error:', error); + }); -- 2.45.2 From b7a38dd099669cb2fed5632ed94b7862a33578d1 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 10:51:29 -0800 Subject: [PATCH 7/8] wrapped comparePassword in a promise --- update-password.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/update-password.js b/update-password.js index 5b94e93c..fbafe10b 100644 --- a/update-password.js +++ b/update-password.js @@ -1,6 +1,10 @@ // load dependencies const logger = require('winston'); const db = require('./models'); // require our models for syncing +// configure logging +const config = require('./config/speechConfig.js'); +const logLevel = config.logging.logLevel; +require('./config/loggerConfig.js')(logger, logLevel); const userName = process.argv[2]; logger.debug('user name:', userName); @@ -22,20 +26,22 @@ db.sequelize.sync() // sync sequelize if (!user) { throw new Error('no user found'); } - return user.comparePassword(oldPassword, (passwordErr, isMatch) => { - if (passwordErr) { - throw passwordErr; - } - if (!isMatch) { - throw new Error('Incorrect old password.'); - } - logger.debug('Password was a match, updating password'); - return user.changePassword(newPassword); + return new Promise((resolve, reject) => { + user.comparePassword(oldPassword, (passwordErr, isMatch) => { + if (passwordErr) { + return reject(passwordErr); + } + if (!isMatch) { + return reject('Incorrect old password.'); + } + logger.debug('Password was a match, updating password'); + return resolve(user.changePassword(newPassword)); + }); }); }) .then(() => { logger.debug('Password successfully updated'); }) .catch((error) => { - logger.error('error:', error); + logger.error(error); }); -- 2.45.2 From 8d90499f03aa20c21d5b01fde5c2378e6fa66c89 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 15:35:46 -0800 Subject: [PATCH 8/8] moved update password script --- update-password.js => task-scripts/update-password.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename update-password.js => task-scripts/update-password.js (86%) diff --git a/update-password.js b/task-scripts/update-password.js similarity index 86% rename from update-password.js rename to task-scripts/update-password.js index fbafe10b..c2cca20c 100644 --- a/update-password.js +++ b/task-scripts/update-password.js @@ -1,10 +1,10 @@ // load dependencies const logger = require('winston'); -const db = require('./models'); // require our models for syncing +const db = require('../models/index'); // require our models for syncing // configure logging -const config = require('./config/speechConfig.js'); +const config = require('../config/speechConfig.js'); const logLevel = config.logging.logLevel; -require('./config/loggerConfig.js')(logger, logLevel); +require('../config/loggerConfig.js')(logger, logLevel); const userName = process.argv[2]; logger.debug('user name:', userName); -- 2.45.2