Merge branch '281-unfurl-show-links' of github.com:lbryio/spee.ch into 281-unfurl-show-links

This commit is contained in:
bill bittner 2017-12-15 07:58:10 -08:00
commit e0c6210bc2
17 changed files with 164 additions and 109 deletions

View file

@ -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) {
@ -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);
});

View file

@ -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,31 +15,12 @@ module.exports = {
}
next();
},
serializeSpeechUser (user, done) {
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) {
let userInfo = {};
db.User.findOne({ where: { id } })
.then(user => {
userInfo['id'] = user.id;
userInfo['userName'] = user.userName;
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);
done(null, userInfo);
return null;
})
.catch(error => {
logger.error(error);
done(error, null);
});
deserializeSpeechUser (user, done) { // deserializes session and populates additional info to req.user
logger.debug('deserializing user');
done(null, user);
},
};

View file

@ -70,16 +70,12 @@ 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.');
}
},
cleanseChannelName (channelName) {
if (channelName) {
if (channelName.indexOf('@') !== 0) {
channelName = `@${channelName}`;
}
if (!channelName) {
return null;
}
if (channelName.indexOf('@') !== 0) {
channelName = `@${channelName}`;
}
return channelName;
},

View file

@ -93,7 +93,6 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
Certificate.associate = db => {
Certificate.belongsTo(db.Channel, {
onDelete : 'cascade',
foreignKey: {
allowNull: true,
},

View file

@ -235,7 +235,6 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
Claim.associate = db => {
Claim.belongsTo(db.File, {
onDelete : 'cascade',
foreignKey: {
allowNull: true,
},

View file

@ -27,7 +27,6 @@ module.exports = (sequelize, { STRING, BOOLEAN, TEXT }) => {
Request.associate = db => {
Request.belongsTo(db.File, {
onDelete : 'cascade',
foreignKey: {
allowNull: true,
},

View file

@ -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) => {

View file

@ -1,53 +1,60 @@
const PassportLocalStrategy = require('passport-local').Strategy;
const db = require('../models');
const logger = require('winston');
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', // username key in the request body
passwordField : 'password', // password key in the request body
session : false,
passReqToCallback: true,
usernameField: 'username',
passwordField: 'password',
},
(req, username, password, done) => {
logger.debug(`verifying loggin attempt ${username} ${password}`);
let userInfo = {};
return db.User
(username, password, done) => {
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) => {
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);
});
});
})

View file

@ -5,12 +5,10 @@ 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',
},
(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)

View file

@ -466,6 +466,10 @@ table {
display: inline-block;
}
.nav-bar-logo {
cursor: pointer;
}
/* PUBLISH FORM */
.dropzone {

View file

@ -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 = '/';
}

View file

@ -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 = '/';
}

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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.headers:', req.headers);
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({

View file

@ -0,0 +1,47 @@
// load dependencies
const logger = require('winston');
const db = require('../models/index'); // 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);
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 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);
});