basic passport flow
This commit is contained in:
parent
242248c4f6
commit
3325faf063
13 changed files with 250 additions and 96 deletions
96
helpers/handlebarsHelpers.js
Normal file
96
helpers/handlebarsHelpers.js
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
const Handlebars = require('handlebars');
|
||||||
|
const config = require('config');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// define any extra helpers you may need
|
||||||
|
googleAnalytics () {
|
||||||
|
const googleApiKey = config.get('AnalyticsConfig.GoogleId');
|
||||||
|
return new Handlebars.SafeString(
|
||||||
|
`<script>
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||||
|
ga('create', '${googleApiKey}', 'auto');
|
||||||
|
ga('send', 'pageview');
|
||||||
|
</script>`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
addOpenGraph (title, mimeType, showUrl, source, description, thumbnail) {
|
||||||
|
let basicTags = `<meta property="og:title" content="${title}">
|
||||||
|
<meta property="og:url" content="${showUrl}" >
|
||||||
|
<meta property="og:site_name" content="Spee.ch" >
|
||||||
|
<meta property="og:description" content="${description}">`;
|
||||||
|
if (mimeType === 'video/mp4') {
|
||||||
|
return new Handlebars.SafeString(
|
||||||
|
`${basicTags} <meta property="og:image" content="${thumbnail}" >
|
||||||
|
<meta property="og:image:type" content="image/png" >
|
||||||
|
<meta property="og:image:width" content="600" >
|
||||||
|
<meta property="og:image:height" content="315" >
|
||||||
|
<meta property="og:type" content="video" >
|
||||||
|
<meta property="og:video" content="${source}" >
|
||||||
|
<meta property="og:video:secure_url" content="${source}" >
|
||||||
|
<meta property="og:video:type" content="${mimeType}" >`
|
||||||
|
);
|
||||||
|
} else if (mimeType === 'image/gif') {
|
||||||
|
return new Handlebars.SafeString(
|
||||||
|
`${basicTags} <meta property="og:image" content="${source}" >
|
||||||
|
<meta property="og:image:type" content="${mimeType}" >
|
||||||
|
<meta property="og:image:width" content="600" >
|
||||||
|
<meta property="og:image:height" content="315" >
|
||||||
|
<meta property="og:type" content="video.other" >`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return new Handlebars.SafeString(
|
||||||
|
`${basicTags} <meta property="og:image" content="${source}" >
|
||||||
|
<meta property="og:image:type" content="${mimeType}" >
|
||||||
|
<meta property="og:image:width" content="600" >
|
||||||
|
<meta property="og:image:height" content="315" >
|
||||||
|
<meta property="og:type" content="article" >`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addTwitterCard (mimeType, source, embedUrl, directFileUrl) {
|
||||||
|
let basicTwitterTags = `<meta name="twitter:site" content="@speechch" >`;
|
||||||
|
if (mimeType === 'video/mp4') {
|
||||||
|
return new Handlebars.SafeString(
|
||||||
|
`${basicTwitterTags} <meta name="twitter:card" content="player" >
|
||||||
|
<meta name="twitter:player" content="${embedUrl}>
|
||||||
|
<meta name="twitter:player:width" content="600" >
|
||||||
|
<meta name="twitter:text:player_width" content="600" >
|
||||||
|
<meta name="twitter:player:height" content="337" >
|
||||||
|
<meta name="twitter:player:stream" content="${directFileUrl}" >
|
||||||
|
<meta name="twitter:player:stream:content_type" content="video/mp4" >
|
||||||
|
`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return new Handlebars.SafeString(
|
||||||
|
`${basicTwitterTags} <meta name="twitter:card" content="summary_large_image" >`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ifConditional (varOne, operator, varTwo, options) {
|
||||||
|
switch (operator) {
|
||||||
|
case '===':
|
||||||
|
return (varOne === varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '!==':
|
||||||
|
return (varOne !== varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '<':
|
||||||
|
return (varOne < varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '<=':
|
||||||
|
return (varOne <= varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '>':
|
||||||
|
return (varOne > varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '>=':
|
||||||
|
return (varOne >= varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '&&':
|
||||||
|
return (varOne && varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case '||':
|
||||||
|
return (varOne || varTwo) ? options.fn(this) : options.inverse(this);
|
||||||
|
case 'mod3':
|
||||||
|
return ((parseInt(varOne) % 3) === 0) ? options.fn(this) : options.inverse(this);
|
||||||
|
default:
|
||||||
|
return options.inverse(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
|
@ -120,4 +120,15 @@ module.exports = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
createChannel (channelName) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
resolve({
|
||||||
|
tx : 'test',
|
||||||
|
txid : 'test',
|
||||||
|
nout : 'test',
|
||||||
|
fee : 'test',
|
||||||
|
claim_id: 'xxxxxxxxxxxxxxxxxx',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => {
|
module.exports = (sequelize, { STRING }) => {
|
||||||
const User = sequelize.define(
|
const User = sequelize.define(
|
||||||
'User',
|
'User',
|
||||||
{
|
{
|
||||||
channelName: {
|
channelName: {
|
||||||
type : STRING,
|
type : STRING,
|
||||||
|
@ -21,6 +21,11 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
freezeTableName: true,
|
freezeTableName: true,
|
||||||
|
instanceMethods: {
|
||||||
|
validPassword: function (password) {
|
||||||
|
return (password === this.password);
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
"helmet": "^3.8.1",
|
"helmet": "^3.8.1",
|
||||||
"mysql2": "^1.3.5",
|
"mysql2": "^1.3.5",
|
||||||
"nodemon": "^1.11.0",
|
"nodemon": "^1.11.0",
|
||||||
|
"passport": "^0.4.0",
|
||||||
|
"passport-local": "^1.0.0",
|
||||||
"sequelize": "^4.1.0",
|
"sequelize": "^4.1.0",
|
||||||
"sleep": "^5.1.1",
|
"sleep": "^5.1.1",
|
||||||
"socket.io": "^2.0.1",
|
"socket.io": "^2.0.1",
|
||||||
|
|
27
passport/local-login.js
Normal file
27
passport/local-login.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
const PassportLocalStrategy = require('passport-local').Strategy;
|
||||||
|
const db = require('./models');
|
||||||
|
|
||||||
|
module.exports = new PassportLocalStrategy(
|
||||||
|
{
|
||||||
|
usernameField : 'username', // username key in the request body
|
||||||
|
passwordField : 'password', // password key in the request body
|
||||||
|
session : false,
|
||||||
|
passReqToCallback: true,
|
||||||
|
},
|
||||||
|
(username, password, done) => {
|
||||||
|
return db.User
|
||||||
|
.findOne({where: {channelName: username}})
|
||||||
|
.then(user => {
|
||||||
|
if (!user) {
|
||||||
|
return done(null, false, {message: 'Incorrect username or password.'});
|
||||||
|
}
|
||||||
|
if (!user.validPassword(password)) {
|
||||||
|
return done(null, false, {message: 'Incorrect username or password.'});
|
||||||
|
}
|
||||||
|
return done(null, user);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
return done(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
32
passport/local-signup.js
Normal file
32
passport/local-signup.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
const db = require('./models');
|
||||||
|
const PassportLocalStrategy = require('passport-local').Strategy;
|
||||||
|
const lbryApi = require('../helpers/lbryApi.js');
|
||||||
|
|
||||||
|
module.exports = new PassportLocalStrategy(
|
||||||
|
{
|
||||||
|
usernameField : 'email', // 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
|
||||||
|
},
|
||||||
|
(req, username, password, done) => {
|
||||||
|
// create the channel and retrieve the metadata
|
||||||
|
lbryApi.createChannel(username)
|
||||||
|
.then(channelInfo => {
|
||||||
|
// define an object that contains all the user data
|
||||||
|
const userData = {
|
||||||
|
channelName: username,
|
||||||
|
channelId : channelInfo.claim_Id,
|
||||||
|
password : password,
|
||||||
|
email : req.body.email.trim(),
|
||||||
|
};
|
||||||
|
return db.User.create(userData);
|
||||||
|
})
|
||||||
|
.then(user => {
|
||||||
|
return done(null);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
return done(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
|
@ -1,8 +1,30 @@
|
||||||
const errorHandlers = require('../helpers/errorHandlers.js');
|
const errorHandlers = require('../helpers/errorHandlers.js');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const { postToStats, getStatsSummary, getTrendingClaims, getRecentClaims } = require('../controllers/statsController.js');
|
const { postToStats, getStatsSummary, getTrendingClaims, getRecentClaims } = require('../controllers/statsController.js');
|
||||||
|
const passport = require('passport');
|
||||||
|
const { deAuthenticate } = require('../auth/authentication.js');
|
||||||
|
|
||||||
module.exports = (app) => {
|
module.exports = (app) => {
|
||||||
|
// route to display login page
|
||||||
|
app.get('/login', (req, res) => {
|
||||||
|
res.status(200).render('login');
|
||||||
|
});
|
||||||
|
app.get('/signup', (req, res) => {
|
||||||
|
res.status(200).render('signup');
|
||||||
|
});
|
||||||
|
// route for auth
|
||||||
|
app.post('/login', passport.authenticate('local-login'), (req, res) => {
|
||||||
|
// If this function gets called, authentication was successful.
|
||||||
|
// `req.user` contains the authenticated user.
|
||||||
|
res.redirect('/@' + req.user.username);
|
||||||
|
});
|
||||||
|
// route to display login page
|
||||||
|
// app.get('/users/:name', isAuthenticated, (req, res) => {
|
||||||
|
// res.status(200).render('profile');
|
||||||
|
// });
|
||||||
|
app.get('/logout', deAuthenticate, (req, res) => {
|
||||||
|
res.status(200).render('/');
|
||||||
|
});
|
||||||
// route to show 'about' page for spee.ch
|
// route to show 'about' page for spee.ch
|
||||||
app.get('/about', (req, res) => {
|
app.get('/about', (req, res) => {
|
||||||
// get and render the content
|
// get and render the content
|
||||||
|
|
104
speech.js
104
speech.js
|
@ -4,6 +4,7 @@ const bodyParser = require('body-parser');
|
||||||
const siofu = require('socketio-file-upload');
|
const siofu = require('socketio-file-upload');
|
||||||
const expressHandlebars = require('express-handlebars');
|
const expressHandlebars = require('express-handlebars');
|
||||||
const Handlebars = require('handlebars');
|
const Handlebars = require('handlebars');
|
||||||
|
const handlebarsHelpers = require('./helpers/handlebarsHelpers.js');
|
||||||
const config = require('config');
|
const config = require('config');
|
||||||
const logger = require('winston');
|
const logger = require('winston');
|
||||||
const { getDownloadDirectory } = require('./helpers/lbryApi');
|
const { getDownloadDirectory } = require('./helpers/lbryApi');
|
||||||
|
@ -11,6 +12,7 @@ const helmet = require('helmet');
|
||||||
const PORT = 3000; // set port
|
const PORT = 3000; // set port
|
||||||
const app = express(); // create an Express application
|
const app = express(); // create an Express application
|
||||||
const db = require('./models'); // require our models for syncing
|
const db = require('./models'); // require our models for syncing
|
||||||
|
const passport = require('passport');
|
||||||
|
|
||||||
// configure logging
|
// configure logging
|
||||||
const logLevel = config.get('Logging.LogLevel');
|
const logLevel = config.get('Logging.LogLevel');
|
||||||
|
@ -30,103 +32,19 @@ app.use((req, res, next) => { // custom logging middleware to log all incomming
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// initialize passport
|
||||||
|
app.use(passport.initialize());
|
||||||
|
// Load passport strategies
|
||||||
|
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({
|
||||||
defaultLayout: 'main', // sets the default layout
|
defaultLayout: 'main', // sets the default layout
|
||||||
handlebars : Handlebars, // includes basic handlebars for access to that library
|
handlebars : Handlebars, // includes basic handlebars for access to that library
|
||||||
helpers : {
|
helpers : handlebarsHelpers, // custom defined helpers
|
||||||
// define any extra helpers you may need
|
|
||||||
googleAnalytics () {
|
|
||||||
const googleApiKey = config.get('AnalyticsConfig.GoogleId');
|
|
||||||
return new Handlebars.SafeString(
|
|
||||||
`<script>
|
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
||||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
|
||||||
ga('create', '${googleApiKey}', 'auto');
|
|
||||||
ga('send', 'pageview');
|
|
||||||
</script>`
|
|
||||||
);
|
|
||||||
},
|
|
||||||
addOpenGraph (title, mimeType, showUrl, source, description, thumbnail) {
|
|
||||||
let basicTags = `<meta property="og:title" content="${title}">
|
|
||||||
<meta property="og:url" content="${showUrl}" >
|
|
||||||
<meta property="og:site_name" content="Spee.ch" >
|
|
||||||
<meta property="og:description" content="${description}">`;
|
|
||||||
if (mimeType === 'video/mp4') {
|
|
||||||
return new Handlebars.SafeString(
|
|
||||||
`${basicTags} <meta property="og:image" content="${thumbnail}" >
|
|
||||||
<meta property="og:image:type" content="image/png" >
|
|
||||||
<meta property="og:image:width" content="600" >
|
|
||||||
<meta property="og:image:height" content="315" >
|
|
||||||
<meta property="og:type" content="video" >
|
|
||||||
<meta property="og:video" content="${source}" >
|
|
||||||
<meta property="og:video:secure_url" content="${source}" >
|
|
||||||
<meta property="og:video:type" content="${mimeType}" >`
|
|
||||||
);
|
|
||||||
} else if (mimeType === 'image/gif') {
|
|
||||||
return new Handlebars.SafeString(
|
|
||||||
`${basicTags} <meta property="og:image" content="${source}" >
|
|
||||||
<meta property="og:image:type" content="${mimeType}" >
|
|
||||||
<meta property="og:image:width" content="600" >
|
|
||||||
<meta property="og:image:height" content="315" >
|
|
||||||
<meta property="og:type" content="video.other" >`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return new Handlebars.SafeString(
|
|
||||||
`${basicTags} <meta property="og:image" content="${source}" >
|
|
||||||
<meta property="og:image:type" content="${mimeType}" >
|
|
||||||
<meta property="og:image:width" content="600" >
|
|
||||||
<meta property="og:image:height" content="315" >
|
|
||||||
<meta property="og:type" content="article" >`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addTwitterCard (mimeType, source, embedUrl, directFileUrl) {
|
|
||||||
let basicTwitterTags = `<meta name="twitter:site" content="@speechch" >`;
|
|
||||||
if (mimeType === 'video/mp4') {
|
|
||||||
return new Handlebars.SafeString(
|
|
||||||
`${basicTwitterTags} <meta name="twitter:card" content="player" >
|
|
||||||
<meta name="twitter:player" content="${embedUrl}>
|
|
||||||
<meta name="twitter:player:width" content="600" >
|
|
||||||
<meta name="twitter:text:player_width" content="600" >
|
|
||||||
<meta name="twitter:player:height" content="337" >
|
|
||||||
<meta name="twitter:player:stream" content="${directFileUrl}" >
|
|
||||||
<meta name="twitter:player:stream:content_type" content="video/mp4" >
|
|
||||||
`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return new Handlebars.SafeString(
|
|
||||||
`${basicTwitterTags} <meta name="twitter:card" content="summary_large_image" >`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ifConditional (varOne, operator, varTwo, options) {
|
|
||||||
switch (operator) {
|
|
||||||
case '===':
|
|
||||||
return (varOne === varTwo) ? options.fn(this) : options.inverse(this);
|
|
||||||
case '!==':
|
|
||||||
return (varOne !== varTwo) ? options.fn(this) : options.inverse(this);
|
|
||||||
case '<':
|
|
||||||
return (varOne < varTwo) ? options.fn(this) : options.inverse(this);
|
|
||||||
case '<=':
|
|
||||||
return (varOne <= varTwo) ? options.fn(this) : options.inverse(this);
|
|
||||||
case '>':
|
|
||||||
return (varOne > varTwo) ? options.fn(this) : options.inverse(this);
|
|
||||||
case '>=':
|
|
||||||
return (varOne >= varTwo) ? options.fn(this) : options.inverse(this);
|
|
||||||
case '&&':
|
|
||||||
return (varOne && varTwo) ? options.fn(this) : options.inverse(this);
|
|
||||||
case '||':
|
|
||||||
return (varOne || varTwo) ? options.fn(this) : options.inverse(this);
|
|
||||||
case 'mod3':
|
|
||||||
return ((parseInt(varOne) % 3) === 0) ? options.fn(this) : options.inverse(this);
|
|
||||||
default:
|
|
||||||
return options.inverse(this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
app.engine('handlebars', hbs.engine);
|
app.engine('handlebars', hbs.engine);
|
||||||
app.set('view engine', 'handlebars');
|
app.set('view engine', 'handlebars');
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
{{> topBar}}
|
{{> topBar}}
|
||||||
<div class="full">
|
<div class="full">
|
||||||
{{> publish}}
|
{{> publishForm}}
|
||||||
{{> learnMore}}
|
{{> learnMore}}
|
||||||
</div>
|
</div>
|
||||||
{{> footer}}
|
{{> footer}}
|
||||||
|
|
11
views/login.handlebars
Normal file
11
views/login.handlebars
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="wrapper">
|
||||||
|
{{> topBar}}
|
||||||
|
<div class="full">
|
||||||
|
{{#if isAuthenticated}}
|
||||||
|
{{> profile }}
|
||||||
|
{{else}}
|
||||||
|
{{> loginForm}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{> footer}}
|
||||||
|
</div>
|
11
views/profile.handlebars
Normal file
11
views/profile.handlebars
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="wrapper">
|
||||||
|
{{> topBar}}
|
||||||
|
<div class="full">
|
||||||
|
{{#if isAuthenticated}}
|
||||||
|
{{> profile }}
|
||||||
|
{{else}}
|
||||||
|
{{> loginForm}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{> footer}}
|
||||||
|
</div>
|
19
views/setup.handlebars
Normal file
19
views/setup.handlebars
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="wrapper">
|
||||||
|
{{> topBar}}
|
||||||
|
<div class="full">
|
||||||
|
<form action="/login" method="post">
|
||||||
|
<div>
|
||||||
|
<label>Username:</label>
|
||||||
|
<input type="text" name="username"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Password:</label>
|
||||||
|
<input type="password" name="password"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="submit" value="Log In"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{{> footer}}
|
||||||
|
</div>
|
Loading…
Reference in a new issue