From f16abf08c24674ea204aa2e696da6b587d9c78dc Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 30 Nov 2017 14:46:32 -0800 Subject: [PATCH 01/12] 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({ From 7b7627ab2751edae3c535ce0669f64ccc9e6fdf1 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 30 Nov 2017 15:13:17 -0800 Subject: [PATCH 02/12] 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) From c509c35926d35448185e4c54eb260a6a974a1db8 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 30 Nov 2017 17:24:48 -0800 Subject: [PATCH 03/12] 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} .`); From 272e4747ab03f2e94b4f50a85825cd33ed2d318c Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 30 Nov 2017 18:23:27 -0800 Subject: [PATCH 04/12] 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 = '/'; } From 43d8402643cbe9db04c5601cae67efbcc431d27a Mon Sep 17 00:00:00 2001 From: bill bittner Date: Mon, 11 Dec 2017 14:43:25 -0800 Subject: [PATCH 05/12] removed cascading delete from models and added logs --- controllers/publishController.js | 1 + models/certificate.js | 1 - models/claim.js | 1 - models/request.js | 1 - routes/api-routes.js | 1 + 5 files changed, 2 insertions(+), 3 deletions(-) diff --git a/controllers/publishController.js b/controllers/publishController.js index d832c814..ae1af9ba 100644 --- a/controllers/publishController.js +++ b/controllers/publishController.js @@ -79,6 +79,7 @@ module.exports = { resolve(publishResults); // resolve the promise with the result from lbryApi.publishClaim; }) .catch(error => { + logger.error('PUBLISH ERROR', error); publishHelpers.deleteTemporaryFile(publishParams.file_path); // delete the local file reject(error); }); diff --git a/models/certificate.js b/models/certificate.js index 206b3e40..50a24479 100644 --- a/models/certificate.js +++ b/models/certificate.js @@ -93,7 +93,6 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { Certificate.associate = db => { Certificate.belongsTo(db.Channel, { - onDelete : 'cascade', foreignKey: { allowNull: true, }, diff --git a/models/claim.js b/models/claim.js index 5ec31da7..0517f550 100644 --- a/models/claim.js +++ b/models/claim.js @@ -234,7 +234,6 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { Claim.associate = db => { Claim.belongsTo(db.File, { - onDelete : 'cascade', foreignKey: { allowNull: true, }, diff --git a/models/request.js b/models/request.js index 846e12c6..501fb441 100644 --- a/models/request.js +++ b/models/request.js @@ -27,7 +27,6 @@ module.exports = (sequelize, { STRING, BOOLEAN, TEXT }) => { Request.associate = db => { Request.belongsTo(db.File, { - onDelete : 'cascade', foreignKey: { allowNull: true, }, diff --git a/routes/api-routes.js b/routes/api-routes.js index 95bf222b..05a0ae26 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -134,6 +134,7 @@ module.exports = (app) => { res.status(400).json({success: false, message: error.message}); return; } + logger.debug('publish req.files:', files); // validate file, name, license, and nsfw file = files.file; fileName = file.path.substring(file.path.lastIndexOf('/') + 1); From 97eae1a183b5e5795e2ecc0bb630fc3e9e372dd0 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 08:10:14 -0800 Subject: [PATCH 06/12] updated logging --- controllers/publishController.js | 2 +- models/claim.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/controllers/publishController.js b/controllers/publishController.js index ae1af9ba..fa82a525 100644 --- a/controllers/publishController.js +++ b/controllers/publishController.js @@ -10,7 +10,7 @@ module.exports = { // publish the file return lbryApi.publishClaim(publishParams) .then(tx => { - logger.info(`Successfully published ${fileName}`, tx); + logger.info(`Successfully published ${publishParams.name} ${fileName}`, tx); publishResults = tx; // get the channel information if (publishParams.channel_name) { diff --git a/models/claim.js b/models/claim.js index 0517f550..483f9671 100644 --- a/models/claim.js +++ b/models/claim.js @@ -16,7 +16,7 @@ function determineFileExtensionFromContentType (contentType) { case 'video/mp4': return 'mp4'; default: - logger.info('setting unknown file type as file extension jpg'); + logger.debug('setting unknown file type as file extension jpg'); return 'jpg'; } }; @@ -33,7 +33,7 @@ function determineContentTypeFromFileExtension (fileExtension) { case 'mp4': return 'video/mp4'; default: - logger.info('setting unknown file type as type image/jpg'); + logger.debug('setting unknown file type as type image/jpg'); return 'image/jpg'; } }; From 9ad99c5ac1e78ae752a479897502d5aead0645a2 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 08:55:02 -0800 Subject: [PATCH 07/12] 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); - }); - }); }; From c7ad52216dd31c0ba948e28768b292dd79405ec4 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 09:21:20 -0800 Subject: [PATCH 08/12] 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); + }); From b7a38dd099669cb2fed5632ed94b7862a33578d1 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 10:51:29 -0800 Subject: [PATCH 09/12] 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); }); From 8d90499f03aa20c21d5b01fde5c2378e6fa66c89 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 15:35:46 -0800 Subject: [PATCH 10/12] 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); From 09f7ea58acd8d8f1c0b654c4f8ea893ef127eaf9 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Tue, 12 Dec 2017 21:55:07 -0800 Subject: [PATCH 11/12] added a check for 502 response on publish --- public/assets/js/publishFileFunctions.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/public/assets/js/publishFileFunctions.js b/public/assets/js/publishFileFunctions.js index 1f552bb8..15a4c5a9 100644 --- a/public/assets/js/publishFileFunctions.js +++ b/public/assets/js/publishFileFunctions.js @@ -123,12 +123,14 @@ const publishFileFunctions = { xhr.open("POST", uri, true); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { + console.log('publish response:', xhr.response) if (xhr.status == 200) { - console.log('publish complete!'); - that.showFilePublishComplete(JSON.parse(xhr.response).message); + console.log('publish complete!'); + that.showFilePublishComplete(JSON.parse(xhr.response).message); + } else if (xhr.status == 502){ + that.showFilePublishFailure('Spee.ch was not able to get a response from the LBRY network.'); } else { - console.log(xhr.response); - that.showFilePublishFailure(JSON.parse(xhr.response).message); + that.showFilePublishFailure(JSON.parse(xhr.response).message); } } else { console.log('xhr.readyState', xhr.readyState, 'xhr.status', xhr.status); From 6266b1bb5b6e1b414e7160f04ebc8af098ead15e Mon Sep 17 00:00:00 2001 From: Joshua Strobl Date: Thu, 14 Dec 2017 21:16:30 +0200 Subject: [PATCH 12/12] Set logo link in navbar to use pointer cursor to be consistent with other links in navbar. --- public/assets/css/general.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/assets/css/general.css b/public/assets/css/general.css index 57c26354..629a999c 100644 --- a/public/assets/css/general.css +++ b/public/assets/css/general.css @@ -466,6 +466,10 @@ table { display: inline-block; } +.nav-bar-logo { + cursor: pointer; +} + /* PUBLISH FORM */ .dropzone {