Added Social Authentication + fixed Agent Cron

This commit is contained in:
NGPixel 2016-10-30 18:41:10 -04:00
parent fa7391ea4b
commit dc6fc449f0
23 changed files with 428 additions and 111 deletions

16
.snyk
View File

@ -1,16 +0,0 @@
failThreshold: high
version: v1.5.2
ignore:
'npm:moment:20160126':
- express-brute-mongo > moment:
reason: None given
expires: '2016-11-16T22:23:46.921Z'
patch:
'npm:negotiator:20160616':
- socket.io > engine.io > accepts > negotiator:
patched: '2016-09-09T02:19:31.082Z'
'npm:ws:20160624':
- socket.io > engine.io > ws:
patched: '2016-09-09T02:19:31.082Z'
- socket.io > socket.io-client > engine.io-client > ws:
patched: '2016-09-09T02:19:31.082Z'

View File

@ -20,13 +20,22 @@
##### Milestones
- [ ] Assets Management
- [x] Images
- [ ] Files/Documents
- [ ] Authentication
- [ ] Local
- [x] Microsoft Account
- [x] Google ID
- [x] Facebook
- [x] Background Agent (git sync, cache purge, etc.)
- [x] Caching
- [x] Create Entry
- [x] Edit Entry
- [x] Git Management
- [ ] Markdown Editor
- [x] Basic Formatting
- [ ] Links
- [ ] Table Editor
- [x] Move Entry
- [x] Navigation
- [x] Parsing / Tree / Metadata

View File

@ -167,7 +167,9 @@ var job = new cron({
if(!jobUplWatchStarted) {
jobUplWatchStarted = true;
upl.initialScan();
upl.initialScan().then(() => {
job.start();
});
}
return true;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
#bg,#bg>div{width:100%;height:100%;top:0;left:0}#root,#root button,#root h1,a{color:#FFF}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}[v-cloak]{display:none}body{padding:0;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:14px}a{transition:color .4s ease;text-decoration:none}a:hover{color:#FB8C00;text-decoration:underline}#bg{position:fixed;z-index:1;background-color:#000}#bg>div{background-size:cover;background-position:center center;position:absolute;opacity:0;visibility:hidden;transition:opacity 3s ease,visibility 3s;animation:bg 30s linear infinite}#copyright,#root{display:flex;left:10vw;z-index:2}#bg>div:nth-child(1){animation-delay:10s}#bg>div:nth-child(2){animation-delay:20s}#root h1,#root h2{animation:headerIntro 3s ease;padding:0}#root{position:fixed;top:15vh;flex-direction:column}#root h1{font-size:4rem;margin:0}#root h2{font-size:1.5rem;font-weight:400;color:rgba(255,255,255,.7);margin:0 0 25px}#root input[type=password],#root input[type=text]{width:350px;max-width:80vw;border:1px solid rgba(255,255,255,.3);border-radius:3px;background-color:rgba(0,0,0,.2);padding:0 15px;height:40px;margin:0 0 10px;color:#FFF;font-weight:700;font-size:14px;transition:all .4s ease}#root input[type=password]:focus,#root input[type=text]:focus{outline:0;border-color:rgba(255,255,255,.8)}#root button{background-color:#FB8C00;border:1px solid #ffa32f;border-radius:3px;height:40px;width:125px;padding:0;font-weight:700;margin:15px 0 0;transition:all .4s ease;cursor:pointer}#root button:focus{outline:0;border-color:#FFF}#root button:hover{background-color:#c87000}#copyright{align-items:center;justify-content:flex-start;position:absolute;bottom:10vh;color:rgba(255,255,255,.5);font-weight:700}#copyright .icon{font-size:1.2rem;margin:0 8px}#copyright a{opacity:.75}@-webkit-keyframes bg{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);visibility:visible;opacity:0}33%,5%{opacity:.5}38%{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2);opacity:0}39%{visibility:hidden}100%{visibility:hidden;opacity:0}}@-moz-keyframes bg{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);visibility:visible;opacity:0}33%,5%{opacity:.5}38%{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2);opacity:0}39%{visibility:hidden}100%{visibility:hidden;opacity:0}}@-o-keyframes bg{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);visibility:visible;opacity:0}33%,5%{opacity:.5}38%{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2);opacity:0}39%{visibility:hidden}100%{visibility:hidden;opacity:0}}@keyframes bg{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);visibility:visible;opacity:0}33%,5%{opacity:.5}38%{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2);opacity:0}39%{visibility:hidden}100%{visibility:hidden;opacity:0}}@-webkit-keyframes headerIntro{0%{opacity:0}100%{opacity:1}}@-moz-keyframes headerIntro{0%{opacity:0}100%{opacity:1}}@-o-keyframes headerIntro{0%{opacity:0}100%{opacity:1}}@keyframes headerIntro{0%{opacity:0}100%{opacity:1}}
#bg,#bg>div{width:100%;height:100%;top:0;left:0}#root,#root button,#root h1,a{color:#FFF}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}[v-cloak]{display:none}body{padding:0;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:14px}a{transition:color .4s ease;text-decoration:none}a:hover{color:#FB8C00;text-decoration:underline}#bg{position:fixed;z-index:1;background-color:#000}#bg>div{background-size:cover;background-position:center center;position:absolute;opacity:0;visibility:hidden;transition:opacity 3s ease,visibility 3s;animation:bg 30s linear infinite}#copyright,#root{left:10vw;z-index:2}#bg>div:nth-child(1){animation-delay:10s}#bg>div:nth-child(2){animation-delay:20s}#root h1,#root h2{animation:headerIntro 3s ease;padding:0}#root{position:fixed;top:15vh;display:flex;flex-direction:column}#root h1{font-size:4rem;margin:0}#root h2{font-size:1.5rem;font-weight:400;color:rgba(255,255,255,.7);margin:0 0 25px}#root input[type=password],#root input[type=text]{width:350px;max-width:80vw;border:1px solid rgba(255,255,255,.3);border-radius:3px;background-color:rgba(0,0,0,.2);padding:0 15px;height:40px;margin:0 0 10px;color:#FFF;font-weight:700;font-size:14px;transition:all .4s ease}#root input[type=password]:focus,#root input[type=text]:focus{outline:0;border-color:rgba(255,255,255,.8)}#root button{background-color:#FB8C00;border:1px solid #ffa32f;border-radius:3px;height:40px;width:125px;padding:0;font-weight:700;margin:15px 0 0;transition:all .4s ease;cursor:pointer}#root button:focus{outline:0;border-color:#FFF}#root button:hover{background-color:#c87000}#root #social{margin-top:25px}#root #social>span{display:block;font-weight:700;color:rgba(255,255,255,.7)}#root #social button{margin-right:5px;width:auto;padding:0 15px}#root #social button>i{margin-right:10px;font-size:16px}#root #social button.ms{background-color:#009688;border-color:#00c9b6}#root #social button.ms:hover{background-color:#00635a}#root #social button.google{background-color:#2196F3;border-color:#51adf6}#root #social button.google:hover{background-color:#0c7cd5}#root #social button.facebook{background-color:#673AB7;border-color:#8259cb}#root #social button.facebook:hover{background-color:#512e90}#copyright{display:flex;align-items:center;justify-content:flex-start;position:absolute;bottom:10vh;color:rgba(255,255,255,.5);font-weight:700}#copyright .icon{font-size:1.2rem;margin:0 8px}#copyright a{opacity:.75}@-webkit-keyframes bg{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);visibility:visible;opacity:0}33%,5%{opacity:.5}38%{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2);opacity:0}39%{visibility:hidden}100%{visibility:hidden;opacity:0}}@-moz-keyframes bg{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);visibility:visible;opacity:0}33%,5%{opacity:.5}38%{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2);opacity:0}39%{visibility:hidden}100%{visibility:hidden;opacity:0}}@-o-keyframes bg{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);visibility:visible;opacity:0}33%,5%{opacity:.5}38%{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2);opacity:0}39%{visibility:hidden}100%{visibility:hidden;opacity:0}}@keyframes bg{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);visibility:visible;opacity:0}33%,5%{opacity:.5}38%{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2);opacity:0}39%{visibility:hidden}100%{visibility:hidden;opacity:0}}@-webkit-keyframes headerIntro{0%{opacity:0}100%{opacity:1}}@-moz-keyframes headerIntro{0%{opacity:0}100%{opacity:1}}@-o-keyframes headerIntro{0%{opacity:0}100%{opacity:1}}@keyframes headerIntro{0%{opacity:0}100%{opacity:1}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 134 KiB

File diff suppressed because one or more lines are too long

View File

@ -205,6 +205,7 @@
border-left: none;
border-right: none;
padding-top: 52px;
font-family: $family-monospace;
}
.CodeMirror .CodeMirror-code .cm-url {

View File

@ -36,6 +36,13 @@
.mkcontent {
h1 {
border-bottom: 1px dotted $blue;
padding-bottom: 4px;
font-weight: 400;
color: desaturate($blue, 20%);
}
h2 {
border-bottom: 1px dotted $grey-light;
padding-bottom: 4px;
font-weight: 400;
@ -44,7 +51,7 @@
a.toc-anchor {
font-size: 80%;
color: $purple;
color: $blue;
border-bottom: none;
&:visited {
@ -74,6 +81,7 @@
pre {
padding: 0;
font-family: $family-monospace;
> code {
box-shadow: inset 0 0 5px 0 $grey-light;
@ -94,6 +102,7 @@
float: right;
margin-top: -50px;
max-width: 200px;
background-color: #FFF;
}
strong {
@ -104,6 +113,23 @@
font-size: 120%;
}
table thead th {
background-color: $blue;
color: #FFF;
border-color: #FFF;
border-bottom-color: $blue;
border-top-color: $blue;
&:first-child {
border-left-color: $blue;
}
&:last-child {
border-right-color: $blue;
}
}
}
.content a:not(.button):visited {

View File

@ -20,7 +20,7 @@ $yellow: #fce473 !default
// Typography
$family-monospace: monospace;
$family-monospace: Consolas, "Liberation Mono", Menlo, Courier, monospace;
$family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
$size-1: 48px !default

View File

@ -125,6 +125,59 @@ a {
}
#social {
margin-top: 25px;
> span {
display: block;
font-weight: bold;
color: rgba(255,255,255,0.7);
}
button {
margin-right: 5px;
width: auto;
padding: 0 15px;
> i {
margin-right: 10px;
font-size: 16px;
}
&.ms {
background-color: #009688;
border-color: lighten(#009688, 10%);
&:hover {
background-color: darken(#009688, 10%);
}
}
&.google {
background-color: #2196F3;
border-color: lighten(#2196F3, 10%);
&:hover {
background-color: darken(#2196F3, 10%);
}
}
&.facebook {
background-color: #673AB7;
border-color: lighten(#673AB7, 10%);
&:hover {
background-color: darken(#673AB7, 10%);
}
}
}
}
}
#copyright {

View File

@ -31,6 +31,26 @@ paths:
repo: ./repo
data: ./data
# ---------------------------------------------------------------------
# Site Authentication
# ---------------------------------------------------------------------
auth:
local:
enabled: true
google:
enabled: true
clientId: GOOGLE_CLIENT_ID
clientSecret: GOOGLE_CLIENT_SECRET
microsoft:
enabled: true
clientId: MS_APP_ID
clientSecret: MS_APP_SECRET
facebook:
enabled: false
clientId: FACEBOOK_APP_ID
clientSecret: FACEBOOK_APP_SECRET
# ---------------------------------------------------------------------
# Database Connection String
# ---------------------------------------------------------------------

View File

@ -59,6 +59,18 @@ router.post('/login', bruteforce.prevent, function(req, res, next) {
})(req, res, next);
});
/**
* Social Login
*/
router.get('/login/ms', passport.authenticate('windowslive', { scope: ['wl.signin', 'wl.basic', 'wl.emails'] }));
router.get('/login/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
router.get('/login/facebook', passport.authenticate('facebook', { scope: ['public_profile', 'email'] }));
router.get('/login/ms/callback', passport.authenticate('windowslive', { failureRedirect: '/login', successRedirect: '/' }));
router.get('/login/google/callback', passport.authenticate('google', { failureRedirect: '/login', successRedirect: '/' }));
router.get('/login/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login', successRedirect: '/' }));
/**
* Logout
*/

View File

@ -2,6 +2,8 @@
module.exports = (socket) => {
console.log(socket.request.user);
//-----------------------------------------
// SEARCH
//-----------------------------------------

View File

@ -1,4 +1,10 @@
var LocalStrategy = require('passport-local').Strategy;
"use strict";
const LocalStrategy = require('passport-local').Strategy;
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const WindowsLiveStrategy = require('passport-windowslive').Strategy;
const FacebookStrategy = require('passport-facebook').Strategy;
const _ = require('lodash');
module.exports = function(passport, appconfig) {
@ -9,18 +15,23 @@ module.exports = function(passport, appconfig) {
});
passport.deserializeUser(function(id, done) {
let user = db.User.find({ id });
db.User.findById(id).then((user) => {
if(user) {
done(null, user);
} else {
done(err, null);
done(new Error('User not found.'), null);
}
return true;
}).catch((err) => {
done(err, null);
});
});
// Setup local user authentication strategy
// Local Account
passport.use(
'local',
if(appconfig.auth.local && appconfig.auth.local.enabled) {
passport.use('local',
new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
@ -41,23 +52,94 @@ module.exports = function(passport, appconfig) {
})
);
}
// Google ID
if(appconfig.auth.google && appconfig.auth.google.enabled) {
passport.use('google',
new GoogleStrategy({
clientID: appconfig.auth.google.clientId,
clientSecret: appconfig.auth.google.clientSecret,
callbackURL: appconfig.host + '/login/google/callback'
},
(accessToken, refreshToken, profile, cb) => {
db.User.processProfile(profile).then((user) => {
return cb(null, user) || true;
}).catch((err) => {
return cb(err, null) || true;
});
}
));
}
// Microsoft Accounts
if(appconfig.auth.microsoft && appconfig.auth.microsoft.enabled) {
passport.use('windowslive',
new WindowsLiveStrategy({
clientID: appconfig.auth.microsoft.clientId,
clientSecret: appconfig.auth.microsoft.clientSecret,
callbackURL: appconfig.host + '/login/ms/callback'
},
function(accessToken, refreshToken, profile, cb) {
db.User.processProfile(profile).then((user) => {
return cb(null, user) || true;
}).catch((err) => {
return cb(err, null) || true;
});
}
));
}
// Facebook
if(appconfig.auth.facebook && appconfig.auth.facebook.enabled) {
passport.use('facebook',
new FacebookStrategy({
clientID: appconfig.auth.facebook.clientId,
clientSecret: appconfig.auth.facebook.clientSecret,
callbackURL: appconfig.host + '/login/facebook/callback',
profileFields: ['id', 'displayName', 'email']
},
function(accessToken, refreshToken, profile, cb) {
db.User.processProfile(profile).then((user) => {
return cb(null, user) || true;
}).catch((err) => {
return cb(err, null) || true;
});
}
));
}
// Check for admin access
db.onReady.then(() => {
/*if(db.User.count() < 1) {
winston.info('No administrator account found. Creating a new one...');
if(db.User.insert({
db.User.count().then((c) => {
if(c < 1) {
winston.info('[' + PROCNAME + '][AUTH] No administrator account found. Creating a new one...');
db.User.hashPassword('admin123').then((pwd) => {
return db.User.create({
provider: 'local',
email: appconfig.admin,
firstName: "Admin",
lastName: "Admin",
password: "admin123"
})) {
winston.info('Administrator account created successfully!');
} else {
winston.error('An error occured while creating administrator account: ');
name: "Administrator",
password: pwd
});
}).then(() => {
winston.info('[' + PROCNAME + '][AUTH] Administrator account created successfully!');
}).catch((err) => {
winston.error('[' + PROCNAME + '][AUTH] An error occured while creating administrator account:');
winston.error(err);
});
}
}*/
});
return true;

View File

@ -21,15 +21,36 @@ module.exports = (confPath) => {
process.exit(1);
}
return _.defaultsDeep(appconfig, {
// Merge with defaults
appconfig = _.defaultsDeep(appconfig, {
title: "Requarks Wiki",
host: "http://localhost",
port: process.env.PORT,
wsPort: 8080,
auth: {
local: { enabled: true },
microsoft: { enabled: false },
google: { enabled: false },
facebook: { enabled: false },
},
db: "mongodb://localhost/wiki",
redis: null,
sessionSecret: null,
admin: null
});
// List authentication strategies
appconfig.authStrategies = {
list: _.filter(appconfig.auth, ['enabled', true]),
socialEnabled: (_.chain(appconfig.auth).omit('local').reject({ enabled: false }).value().length > 0)
}
if(appconfig.authStrategies.list.length < 1) {
winston.error(new Error('You must enable at least 1 authentication strategy!'));
process.exit(1);
}
return appconfig;
};

View File

@ -6,7 +6,7 @@ module.exports = (isDebug) => {
winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {
level: (isDebug) ? 'info' : 'warn',
level: (isDebug) ? 'debug' : 'info',
prettyPrint: true,
colorize: true,
silent: false,

View File

@ -2,6 +2,7 @@
const modb = require('mongoose'),
Promise = require('bluebird'),
bcrypt = require('bcryptjs-then'),
_ = require('lodash');
/**
@ -12,13 +13,75 @@ const modb = require('mongoose'),
var userSchema = modb.Schema({
email: {
type: String,
required: true,
index: true
},
provider: {
type: String,
required: true
}
},
providerId: {
type: String
},
password: {
type: String
},
name: {
type: String
},
rights: [{
type: String
}]
},
{
timestamps: {}
});
userSchema.statics.processProfile = (profile) => {
let primaryEmail = '';
if(_.isArray(profile.emails)) {
let e = _.find(profile.emails, ['primary', true]);
primaryEmail = (e) ? e.value : _.first(profile.emails).value;
} else if(_.isString(profile.email) && profile.email.length > 5) {
primaryEmail = profile.email;
} else {
return Promise.reject(new Error('Invalid User Email'));
}
return db.User.findOneAndUpdate({
email: primaryEmail,
provider: profile.provider
}, {
email: primaryEmail,
provider: profile.provider,
providerId: profile.id,
name: profile.displayName
}, {
new: true,
upsert: true
}).then((user) => {
return (user) ? user : Promise.reject(new Error('User Upsert failed.'));
});
};
userSchema.statics.hashPassword = (rawPwd) => {
return bcrypt.hash(rawPwd);
};
userSchema.methods.validatePassword = function(rawPwd) {
let self = this;
return bcrypt.hash(rawPwd).then((pwd) => {
return (self.password === pwd) ? true : Promise.reject(new Error('Invalid Password'));
});
};
module.exports = modb.model('User', userSchema);

View File

@ -73,7 +73,11 @@
"mongoose": "^4.6.3",
"multer": "^1.2.0",
"passport": "^0.3.2",
"passport-facebook": "^2.1.1",
"passport-google-oauth20": "^1.0.0",
"passport-local": "^1.0.0",
"passport-windowslive": "^1.0.2",
"passport.socketio": "^3.6.2",
"pug": "^2.0.0-beta6",
"read-chunk": "^2.0.0",
"remove-markdown": "^0.1.0",

View File

@ -46,6 +46,7 @@ const http = require('http');
const i18next_backend = require('i18next-node-fs-backend');
const i18next_mw = require('i18next-express-middleware');
const passport = require('passport');
const passportSocketIo = require('passport.socketio');
const path = require('path');
const session = require('express-session');
const sessionMongoStore = require('connect-mongo')(session);
@ -81,15 +82,16 @@ app.use(express.static(path.join(ROOTPATH, 'assets')));
// Session
// ----------------------------------------
var strategy = require('./libs/auth')(passport, appconfig);
const strategies = require('./libs/auth')(passport, appconfig);
var sessionStore = new sessionMongoStore({
mongooseConnection: db.connection,
touchAfter: 15
});
app.use(cookieParser());
app.use(session({
name: 'requarkswiki.sid',
store: new sessionMongoStore({
mongooseConnection: db.connection,
touchAfter: 15
}),
store: sessionStore,
secret: appconfig.sessionSecret,
resave: false,
saveUninitialized: false
@ -144,9 +146,9 @@ app.use(mw.flash);
app.use('/', ctrl.auth);
app.use('/uploads', ctrl.uploads);
app.use('/uploads', mw.auth, ctrl.uploads);
app.use('/admin', mw.auth, ctrl.admin);
app.use('/', ctrl.pages);
app.use('/', mw.auth, ctrl.pages);
// ----------------------------------------
// Error handling
@ -202,9 +204,26 @@ server.on('listening', () => {
});
// ----------------------------------------
// WebSocket handlers
// WebSocket
// ----------------------------------------
io.use(passportSocketIo.authorize({
key: 'requarkswiki.sid',
store: sessionStore,
secret: appconfig.sessionSecret,
passport,
cookieParser,
success: (data, accept) => {
accept();
},
fail: (data, message, error, accept) => {
if(error) {
throw new Error(message);
}
return accept(new Error(message));
}
}));
io.on('connection', ctrl.ws);
// ----------------------------------------

View File

@ -27,14 +27,33 @@ html
body
#bg
each bg in [1, 2, 3]
each bg in _.sampleSize([1, 2, 3],3)
div(style="background-image:url(/images/bg_" + bg + ".jpg);")
#root
h1= appconfig.title
h2 Login required
if appconfig.auth.local.enabled
input#login-user(type='text', placeholder='Email address')
input#login-pass(type='password', placeholder='Password')
button Log In
if appconfig.authStrategies.socialEnabled
#social
if appconfig.auth.local.enabled
span Or, log in using...
else
span Log in using...
if appconfig.auth.microsoft && appconfig.auth.microsoft.enabled
button.ms(onclick="window.location.assign('/login/ms')")
i.fa.fa-windows
span Microsoft Account
if appconfig.auth.google && appconfig.auth.google.enabled
button.google(onclick="window.location.assign('/login/google')")
i.fa.fa-google
span Google ID
if appconfig.auth.facebook && appconfig.auth.facebook.enabled
button.facebook(onclick="window.location.assign('/login/facebook')")
i.fa.fa-facebook
span Facebook
#copyright
= t('footer.poweredby') + ' '
a.icon(href='https://github.com/Requarks/wiki')