added navbar channel select update on login from publish

This commit is contained in:
bill bittner 2017-10-10 16:00:08 -07:00
parent e8fcefc8bb
commit 0e8a45bdfc
9 changed files with 151 additions and 112 deletions

44
helpers/authHelpers.js Normal file
View file

@ -0,0 +1,44 @@
const db = require('../models'); // require our models for syncing
const logger = require('winston');
module.exports = {
populateLocalsDotUser (req, res, next) {
if (req.user) {
res.locals.user = {
id : req.user.id,
userName : req.user.userName,
channelName : req.user.channelName,
channelClaimId: req.user.channelClaimId,
shortChannelId: req.user.shortChannelId,
};
}
next();
},
serializeSpeechUser (user, done) {
done(null, user.id);
},
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.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);
});
},
};

View file

@ -80,6 +80,10 @@ function createProgressBar(element, size){
setInterval(addOne, 300);
}
function setCookie(key, value) {
document.cookie = `${key}=${value}`;
}
function getCookie(cname) {
const name = cname + "=";
const decodedCookie = decodeURIComponent(document.cookie);
@ -105,6 +109,10 @@ function checkCookie() {
}
}
function clearCookies() {
}
function copyToClipboard(event){
var elementToCopy = event.target.dataset.elementtocopy;
var element = document.getElementById(elementToCopy);

View file

@ -0,0 +1,73 @@
function setUserCookies(channelName, channelClaimId, shortChannelId) {
setCookie('channel_name', channelName)
setCookie('channel_claim_id', channelClaimId);
setCookie('short_channel_id', shortChannelId);
}
function replaceChannelOptionInPublishChannelSelect() {
// 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);
newChannelOption.setAttribute('id', 'publish-channel-select-channel-option');
newChannelOption.setAttribute('selected', '');
newChannelOption.innerText = loggedInChannel;
// add the new option
const channelSelect = document.getElementById('channel-name-select');
channelSelect.insertBefore(newChannelOption, channelSelect.firstChild);
// carry out channel selection
toggleSelectedChannel(loggedInChannel);
}
function replaceChannelOptionInNavBarChannelSelect () {
// 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);
newChannelOption.setAttribute('id', 'nav-bar-channel-select-channel-option');
newChannelOption.setAttribute('selected', '');
newChannelOption.innerText = loggedInChannel;
// add the new option
const channelSelect = document.getElementById('nav-bar-channel-select');
channelSelect.insertBefore(newChannelOption, channelSelect.firstChild);
}
function loginToChannel (event) {
const userName = document.getElementById('channel-login-name-input').value;
const password = document.getElementById('channel-login-password-input').value;
const loginErrorDisplayElement = document.getElementById('login-error-display-element');
// prevent default
event.preventDefault()
// send request
sendAuthRequest(userName, password, '/login')
// update session cookie with new channel name and id's
.then(result => {
setUserCookies(result.channelName, result.channelClaimId, result.shortChannelId); // replace the current cookies
return result;
})
// update channel selection
.then(result => {
// remove old channel and replace with new one & select it
replaceChannelOptionInPublishChannelSelect();
// remove old channel and replace with new one & select it
replaceChannelOptionInNavBarChannelSelect();
})
.catch(error => {
showError(loginErrorDisplayElement, error);
console.log('login failure:', error);
})
}

View file

@ -5,6 +5,7 @@ const siofu = require('socketio-file-upload');
const expressHandlebars = require('express-handlebars');
const Handlebars = require('handlebars');
const handlebarsHelpers = require('./helpers/handlebarsHelpers.js');
const { populateLocalsDotUser, serializeSpeechUser, deserializeSpeechUser } = require('./helpers/authHelpers.js');
const config = require('config');
const logger = require('winston');
const { getDownloadDirectory } = require('./helpers/lbryApi');
@ -42,32 +43,8 @@ app.use((req, res, next) => { // custom logging middleware to log all incoming
app.use(session({ secret: 'cats' }));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => { // this populates req.user
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.getShortChannelIdFromLongChannelId(channel.channelClaimId, channel.channelName);
})
.then(shortChannelId => {
userInfo['shortChannelId'] = shortChannelId;
done(null, userInfo);
return null; // note: why return null and not the done?
})
.catch(error => {
logger.error('sequelize error', error);
done(error, null);
});
});
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);
@ -83,19 +60,7 @@ app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
// middleware to pass user info back to client (for handlebars access), if user is logged in
app.use((req, res, next) => {
if (req.user) {
// logger.verbose(req.user);
res.locals.user = {
id : req.user.id,
userName : req.user.userName,
channelName : req.user.channelName,
channelClaimId: req.user.channelClaimId,
shortChannelId: req.user.shortChannelId,
};
}
next();
});
app.use(populateLocalsDotUser);
// start the server
db.sequelize

View file

@ -24,6 +24,7 @@
<script src="/assets/js/validationFunctions.js"></script>
<script src="/assets/js/publishFileFunctions.js"></script>
<script src="/assets/js/authFunctions.js"></script>
<script src="/assets/js/loginFunctions.js"></script>
{{{ body }}}
</body>
</html>

View file

@ -20,6 +20,7 @@
<script src="/assets/js/generalFunctions.js"></script>
<script src="/assets/js/validationFunctions.js"></script>
<script src="/assets/js/authFunctions.js"></script>
<script src="/assets/js/loginFunctions.js"></script>
{{{ body }}}
</body>
</html>

View file

@ -1,69 +1,23 @@
<form id="channel-login-form">
<div class="row row--wide row--short">
<div class="column column--3 column--sml-10">
<label class="label" for="login-channel-name">Name:</label>
<label class="label" for="channel-login-name-input">Name:</label>
</div><div class="column column--6 column--sml-10">
<div id="login-error-display-element" class="info-message info-message--failure"></div>
<div class="input-text--primary">
<span>@</span>
<input type="text" name="login-channel-name" id="login-channel-name" class="input-text" placeholder="" value="">
<input type="text" id="channel-login-name-input" class="input-text" placeholder="" value="">
</div>
</div>
</div>
<div class="row row--wide row--short">
<div class="column column--3 column--sml-10">
<label class="label" for="login-channel-password" >Password:</label>
<label class="label" for="channel-login-password-input" >Password:</label>
</div><div class="column column--6 column--sml-10">
<input type="password" name="login-channel-password" id="login-channel-password" class="input-text input-text--primary" placeholder="" value="">
<input type="password" id="channel-login-password-input" class="input-text input-text--primary" placeholder="" value="">
</div>
</div>
<div class="row row--wide">
<button class="button--primary" onclick="loginToChannel(event)">Authenticate</button>
</div>
</form>
<script type="text/javascript">
function loginToChannel (event) {
const userName = document.getElementById('login-channel-name').value;
const password = document.getElementById('login-channel-password').value;
const loginErrorDisplayElement = document.getElementById('login-error-display-element');
// prevent default
event.preventDefault()
// send request
sendAuthRequest(userName, password, '/login')
// update session cookie with new channel name and ids
.then(result => {
console.log('login success', result);
// replace the current cookies
document.cookie = `channel_name=${result.channelName}`;
document.cookie = `channel_claim_id=${result.channelClaimId}`;
document.cookie = `short_channel_id=${result.shortChannelId}`;
return result;
})
// update channel selection
.then(result => {
const channelSelect = document.getElementById('channel-name-select');
// remove the old channel option
const oldChannel = document.getElementById('channel-option')
if (oldChannel){
oldChannel.parentNode.removeChild(oldChannel);
}
// add new channel option & select it
const newChannelOption = document.createElement('option');
newChannelOption.setAttribute('value', result.channelName);
newChannelOption.setAttribute('id', 'channel-option');
newChannelOption.setAttribute('selected', '');
newChannelOption.innerText = result.channelName;
channelSelect.insertBefore(newChannelOption, channelSelect.firstChild);
// update selection
toggleSelectedChannel(result.channelName);
})
.catch(error => {
showError(loginErrorDisplayElement, error);
console.log('login failure:', error);
})
}
</script>
</form>

View file

@ -22,7 +22,7 @@
<div id="input-error-channel-select" class="info-message info-message--failure"></div>
<select type="text" id="channel-name-select" class="select select--primary select--arrow" onchange="toggleSelectedChannel(event.target.selectedOptions[0].value)">
{{#if user}}
<option value="{{user.channelName}}" id="channel-option">{{user.channelName}}</option>
<option value="{{user.channelName}}" id="publish-channel-select-channel-option">{{user.channelName}}</option>
{{/if}}
<option value="login">Existing</option>
<option value="new" >New</option>

View file

@ -7,10 +7,10 @@
<a class="nav-bar-link" href="/popular">Popular</a>
<a class="nav-bar-link" href="/about">About</a>
{{#if user}}
<select type="text" class="select select--no-arrow nav-bar-link" onchange="toggleLogin(event)">
<option value="{{user.channelName}}:{{user.channelClaimId}}">@{{user.userName}}</option>
<option value="view">View</option>
<option value="logout">Logout</option>
<select type="text" id="nav-bar-channel-select" class="select select--no-arrow nav-bar-link" onchange="toggleLogin(event.target.selectedOptions[0].value)">
<option id="nav-bar-channel-select-channel-option">@{{user.userName}}</option>
<option value="VIEW">View</option>
<option value="LOGOUT">Logout</option>
</select>
{{else}}
<a class="nav-bar-link" href="/login">Login</a>
@ -22,28 +22,21 @@
</div>
<script type="text/javascript">
function toggleLogin (event) {
console.log(event);
const selectedOption = event.target.selectedOptions[0].value;
if (selectedOption === 'logout') {
function toggleLogin (value) {
const selectedOption = value;
if (selectedOption === 'LOGOUT') {
console.log('log out');
// remove session cookies
clearCookies();
// send logout request to server
window.location.href = '/logout';
} else if (selectedOption === 'view') {
} else if (selectedOption === 'VIEW') {
console.log('view channel');
window.location.href = '/{{user.channelName}}:{{user.channelClaimId}}';
}
}
// highlight the link for the current page
const navBarLinks = document.getElementsByClassName('nav-bar-link');
for (let i = 0; i < navBarLinks.length; i++){
const link = navBarLinks[i];
if (link.href == window.location.href) {
link.setAttribute('class', 'nav-bar-link nav-bar-link--active');
} else if (`/${link.value}` === window.location.pathname) {
link.setAttribute('class', 'select select--no-arrow nav-bar-link nav-bar-link--active');
// get channel info
const channelName = getCookie('channel_name');
const channelClaimId = getCookie('channel_claim_id');
// redirect to channel page
window.location.href = `/${channelName}:${channelClaimId}`;
}
}
</script>