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,4 +1,4 @@
|
|||
module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => {
|
||||
module.exports = (sequelize, { STRING }) => {
|
||||
const User = sequelize.define(
|
||||
'User',
|
||||
{
|
||||
|
@ -21,6 +21,11 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => {
|
|||
},
|
||||
{
|
||||
freezeTableName: true,
|
||||
instanceMethods: {
|
||||
validPassword: function (password) {
|
||||
return (password === this.password);
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
"helmet": "^3.8.1",
|
||||
"mysql2": "^1.3.5",
|
||||
"nodemon": "^1.11.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"sequelize": "^4.1.0",
|
||||
"sleep": "^5.1.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 db = require('../models');
|
||||
const { postToStats, getStatsSummary, getTrendingClaims, getRecentClaims } = require('../controllers/statsController.js');
|
||||
const passport = require('passport');
|
||||
const { deAuthenticate } = require('../auth/authentication.js');
|
||||
|
||||
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
|
||||
app.get('/about', (req, res) => {
|
||||
// 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 expressHandlebars = require('express-handlebars');
|
||||
const Handlebars = require('handlebars');
|
||||
const handlebarsHelpers = require('./helpers/handlebarsHelpers.js');
|
||||
const config = require('config');
|
||||
const logger = require('winston');
|
||||
const { getDownloadDirectory } = require('./helpers/lbryApi');
|
||||
|
@ -11,6 +12,7 @@ const helmet = require('helmet');
|
|||
const PORT = 3000; // set port
|
||||
const app = express(); // create an Express application
|
||||
const db = require('./models'); // require our models for syncing
|
||||
const passport = require('passport');
|
||||
|
||||
// configure logging
|
||||
const logLevel = config.get('Logging.LogLevel');
|
||||
|
@ -30,103 +32,19 @@ app.use((req, res, next) => { // custom logging middleware to log all incomming
|
|||
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
|
||||
const hbs = expressHandlebars.create({
|
||||
defaultLayout: 'main', // sets the default layout
|
||||
handlebars : Handlebars, // includes basic handlebars for access to that library
|
||||
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);
|
||||
}
|
||||
},
|
||||
},
|
||||
helpers : handlebarsHelpers, // custom defined helpers
|
||||
});
|
||||
app.engine('handlebars', hbs.engine);
|
||||
app.set('view engine', 'handlebars');
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="wrapper">
|
||||
{{> topBar}}
|
||||
<div class="full">
|
||||
{{> publish}}
|
||||
{{> publishForm}}
|
||||
{{> learnMore}}
|
||||
</div>
|
||||
{{> 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