added endpoint to update password
This commit is contained in:
parent
6ae9b78dbf
commit
f16abf08c2
7 changed files with 136 additions and 55 deletions
|
@ -14,31 +14,42 @@ module.exports = {
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
},
|
},
|
||||||
serializeSpeechUser (user, done) {
|
serializeSpeechUser (user, done) { // returns user id to be serialized into session token
|
||||||
|
logger.debug('serializing session');
|
||||||
done(null, user.id);
|
done(null, user.id);
|
||||||
},
|
},
|
||||||
deserializeSpeechUser (id, done) {
|
deserializeSpeechUser (id, done) { // deserializes session token and provides user from user id
|
||||||
let userInfo = {};
|
logger.debug('deserializing session');
|
||||||
db.User.findOne({ where: { id } })
|
return db.User.findOne({ where: { id } })
|
||||||
.then(user => {
|
.then(user => {
|
||||||
userInfo['id'] = user.id;
|
return module.exports.returnUserAndChannelInfo(user);
|
||||||
userInfo['userName'] = user.userName;
|
|
||||||
return user.getChannel();
|
|
||||||
})
|
})
|
||||||
.then(channel => {
|
.then((userInfo) => {
|
||||||
userInfo['channelName'] = channel.channelName;
|
return done(null, userInfo);
|
||||||
userInfo['channelClaimId'] = channel.channelClaimId;
|
})
|
||||||
return db.Certificate.getShortChannelIdFromLongChannelId(channel.channelClaimId, channel.channelName);
|
.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 => {
|
.then(shortChannelId => {
|
||||||
userInfo['shortChannelId'] = shortChannelId;
|
userInfo['shortChannelId'] = shortChannelId;
|
||||||
// return done(null, userInfo);
|
resolve(userInfo);
|
||||||
done(null, userInfo);
|
|
||||||
return null;
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
logger.error(error);
|
reject(error);
|
||||||
done(error, null);
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,13 +76,23 @@ module.exports = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cleanseChannelName (channelName) {
|
cleanseChannelName (channelName) {
|
||||||
if (channelName) {
|
if (!channelName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (channelName.indexOf('@') !== 0) {
|
if (channelName.indexOf('@') !== 0) {
|
||||||
channelName = `@${channelName}`;
|
channelName = `@${channelName}`;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 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) {
|
createPublishParams (filePath, name, title, description, license, nsfw, thumbnail, channelName) {
|
||||||
logger.debug(`Creating Publish Parameters`);
|
logger.debug(`Creating Publish Parameters`);
|
||||||
// provide defaults for title
|
// provide defaults for title
|
||||||
|
|
|
@ -28,9 +28,40 @@ module.exports = (sequelize, { STRING }) => {
|
||||||
bcrypt.compare(password, this.password, callback);
|
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.
|
// 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) => {
|
User.hook('beforeCreate', (user, options) => {
|
||||||
logger.debug('...beforeCreate hook...');
|
logger.debug('User.beforeCreate hook...');
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// generate a salt string to use for hashing
|
// generate a salt string to use for hashing
|
||||||
bcrypt.genSalt((saltError, salt) => {
|
bcrypt.genSalt((saltError, salt) => {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
const PassportLocalStrategy = require('passport-local').Strategy;
|
const PassportLocalStrategy = require('passport-local').Strategy;
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const logger = require('winston');
|
const logger = require('winston');
|
||||||
|
const { returnUserAndChannelInfo } = require('../helpers/authHelpers.js');
|
||||||
|
|
||||||
module.exports = new PassportLocalStrategy(
|
module.exports = new PassportLocalStrategy(
|
||||||
{
|
{
|
||||||
|
@ -11,43 +12,31 @@ module.exports = new PassportLocalStrategy(
|
||||||
passReqToCallback: true,
|
passReqToCallback: true,
|
||||||
},
|
},
|
||||||
(req, username, password, done) => {
|
(req, username, password, done) => {
|
||||||
logger.debug(`verifying loggin attempt ${username} ${password}`);
|
logger.debug('logging user in');
|
||||||
let userInfo = {};
|
return db
|
||||||
return db.User
|
.User
|
||||||
.findOne({where: {userName: username}})
|
.findOne({where: {userName: username}})
|
||||||
.then(user => {
|
.then(user => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
logger.debug('no user found');
|
// logger.debug('no user found');
|
||||||
return done(null, false, {message: 'Incorrect username or password.'});
|
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) => {
|
return user.comparePassword(password, (passwordErr, isMatch) => {
|
||||||
if (passwordErr) {
|
if (passwordErr) {
|
||||||
logger.error('passwordErr:', passwordErr);
|
logger.error('passwordErr:', passwordErr);
|
||||||
return done(passwordErr);
|
return done(null, false, {message: passwordErr});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMatch) {
|
if (!isMatch) {
|
||||||
logger.debug('incorrect password');
|
// logger.debug('incorrect password');
|
||||||
return done(null, false, {message: 'Incorrect username or password.'});
|
return done(null, false, {message: 'Incorrect username or password.'});
|
||||||
}
|
}
|
||||||
logger.debug('...password was a match...');
|
logger.debug('Password was a match, returning User');
|
||||||
userInfo['id'] = user.id;
|
return returnUserAndChannelInfo(user)
|
||||||
userInfo['userName'] = user.userName;
|
.then((userInfo) => {
|
||||||
// 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;
|
|
||||||
return done(null, userInfo);
|
return done(null, userInfo);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
throw error;
|
return done(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@ const multipartMiddleware = multipart({uploadDir: config.files.uploadDirectory})
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const { publish } = require('../controllers/publishController.js');
|
const { publish } = require('../controllers/publishController.js');
|
||||||
const { getClaimList, resolveUri } = require('../helpers/lbryApi.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 errorHandlers = require('../helpers/errorHandlers.js');
|
||||||
const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js');
|
const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js');
|
||||||
const { authenticateOrSkip } = require('../auth/authentication.js');
|
const { authenticateOrSkip } = require('../auth/authentication.js');
|
||||||
|
@ -185,4 +185,44 @@ module.exports = (app) => {
|
||||||
errorHandlers.handleApiError('short channel id', originalUrl, ip, error, res);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
// route for log in
|
// route for log in
|
||||||
app.post('/login', passport.authenticate('local-login'), (req, res) => {
|
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');
|
logger.debug('successful login');
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
success : true,
|
success : true,
|
||||||
|
|
14
speech.js
14
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(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
|
app.use((req, res, next) => { // custom logging middleware to log all incoming http requests
|
||||||
logger.verbose(`Request on ${req.originalUrl} from ${req.ip}`);
|
logger.verbose(`Request on ${req.originalUrl} from ${req.ip}`);
|
||||||
logger.debug('req.body:', req.body);
|
|
||||||
next();
|
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
|
// initialize passport
|
||||||
app.use(cookieSession({
|
app.use(cookieSession({
|
||||||
name : 'session',
|
name : 'session',
|
||||||
|
@ -45,12 +51,6 @@ app.use(cookieSession({
|
||||||
}));
|
}));
|
||||||
app.use(passport.initialize());
|
app.use(passport.initialize());
|
||||||
app.use(passport.session());
|
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
|
// configure handlebars & register it with express app
|
||||||
const hbs = expressHandlebars.create({
|
const hbs = expressHandlebars.create({
|
||||||
|
|
Loading…
Reference in a new issue