Added Social Authentication + fixed Agent Cron
This commit is contained in:
parent
fa7391ea4b
commit
dc6fc449f0
16
.snyk
16
.snyk
@ -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'
|
|
@ -20,13 +20,22 @@
|
|||||||
|
|
||||||
##### Milestones
|
##### Milestones
|
||||||
- [ ] Assets Management
|
- [ ] Assets Management
|
||||||
|
- [x] Images
|
||||||
|
- [ ] Files/Documents
|
||||||
- [ ] Authentication
|
- [ ] Authentication
|
||||||
|
- [ ] Local
|
||||||
|
- [x] Microsoft Account
|
||||||
|
- [x] Google ID
|
||||||
|
- [x] Facebook
|
||||||
- [x] Background Agent (git sync, cache purge, etc.)
|
- [x] Background Agent (git sync, cache purge, etc.)
|
||||||
- [x] Caching
|
- [x] Caching
|
||||||
- [x] Create Entry
|
- [x] Create Entry
|
||||||
- [x] Edit Entry
|
- [x] Edit Entry
|
||||||
- [x] Git Management
|
- [x] Git Management
|
||||||
- [ ] Markdown Editor
|
- [ ] Markdown Editor
|
||||||
|
- [x] Basic Formatting
|
||||||
|
- [ ] Links
|
||||||
|
- [ ] Table Editor
|
||||||
- [x] Move Entry
|
- [x] Move Entry
|
||||||
- [x] Navigation
|
- [x] Navigation
|
||||||
- [x] Parsing / Tree / Metadata
|
- [x] Parsing / Tree / Metadata
|
||||||
|
4
agent.js
4
agent.js
@ -167,7 +167,9 @@ var job = new cron({
|
|||||||
|
|
||||||
if(!jobUplWatchStarted) {
|
if(!jobUplWatchStarted) {
|
||||||
jobUplWatchStarted = true;
|
jobUplWatchStarted = true;
|
||||||
upl.initialScan();
|
upl.initialScan().then(() => {
|
||||||
|
job.start();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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
@ -205,6 +205,7 @@
|
|||||||
border-left: none;
|
border-left: none;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
padding-top: 52px;
|
padding-top: 52px;
|
||||||
|
font-family: $family-monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror .CodeMirror-code .cm-url {
|
.CodeMirror .CodeMirror-code .cm-url {
|
||||||
|
@ -36,6 +36,13 @@
|
|||||||
.mkcontent {
|
.mkcontent {
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
border-bottom: 1px dotted $blue;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: desaturate($blue, 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
border-bottom: 1px dotted $grey-light;
|
border-bottom: 1px dotted $grey-light;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@ -44,7 +51,7 @@
|
|||||||
|
|
||||||
a.toc-anchor {
|
a.toc-anchor {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
color: $purple;
|
color: $blue;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
|
||||||
&:visited {
|
&:visited {
|
||||||
@ -74,6 +81,7 @@
|
|||||||
|
|
||||||
pre {
|
pre {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
font-family: $family-monospace;
|
||||||
|
|
||||||
> code {
|
> code {
|
||||||
box-shadow: inset 0 0 5px 0 $grey-light;
|
box-shadow: inset 0 0 5px 0 $grey-light;
|
||||||
@ -94,6 +102,7 @@
|
|||||||
float: right;
|
float: right;
|
||||||
margin-top: -50px;
|
margin-top: -50px;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
|
background-color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
strong {
|
strong {
|
||||||
@ -104,6 +113,23 @@
|
|||||||
font-size: 120%;
|
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 {
|
.content a:not(.button):visited {
|
||||||
|
@ -20,7 +20,7 @@ $yellow: #fce473 !default
|
|||||||
|
|
||||||
// Typography
|
// 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";
|
$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
|
$size-1: 48px !default
|
||||||
|
@ -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 {
|
#copyright {
|
||||||
|
@ -31,6 +31,26 @@ paths:
|
|||||||
repo: ./repo
|
repo: ./repo
|
||||||
data: ./data
|
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
|
# Database Connection String
|
||||||
# ---------------------------------------------------------------------
|
# ---------------------------------------------------------------------
|
||||||
|
@ -59,6 +59,18 @@ router.post('/login', bruteforce.prevent, function(req, res, next) {
|
|||||||
})(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
|
* Logout
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
module.exports = (socket) => {
|
module.exports = (socket) => {
|
||||||
|
|
||||||
|
console.log(socket.request.user);
|
||||||
|
|
||||||
//-----------------------------------------
|
//-----------------------------------------
|
||||||
// SEARCH
|
// SEARCH
|
||||||
|
186
libs/auth.js
186
libs/auth.js
@ -1,66 +1,148 @@
|
|||||||
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) {
|
module.exports = function(passport, appconfig) {
|
||||||
|
|
||||||
// Serialization user methods
|
// Serialization user methods
|
||||||
|
|
||||||
passport.serializeUser(function(user, done) {
|
passport.serializeUser(function(user, done) {
|
||||||
done(null, user._id);
|
done(null, user._id);
|
||||||
});
|
});
|
||||||
|
|
||||||
passport.deserializeUser(function(id, done) {
|
passport.deserializeUser(function(id, done) {
|
||||||
let user = db.User.find({ id });
|
db.User.findById(id).then((user) => {
|
||||||
if(user) {
|
if(user) {
|
||||||
done(null, user);
|
done(null, user);
|
||||||
} else {
|
} 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(
|
if(appconfig.auth.local && appconfig.auth.local.enabled) {
|
||||||
'local',
|
|
||||||
new LocalStrategy({
|
|
||||||
usernameField : 'email',
|
|
||||||
passwordField : 'password',
|
|
||||||
passReqToCallback : true
|
|
||||||
},
|
|
||||||
function(req, uEmail, uPassword, done) {
|
|
||||||
db.User.findOne({ 'email' : uEmail }).then((user) => {
|
|
||||||
if (user) {
|
|
||||||
user.validatePassword(uPassword).then((isValid) => {
|
|
||||||
return (isValid) ? done(null, user) : done(null, false);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return done(null, false);
|
|
||||||
}
|
|
||||||
}).catch((err) => {
|
|
||||||
done(err);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check for admin access
|
passport.use('local',
|
||||||
|
new LocalStrategy({
|
||||||
|
usernameField : 'email',
|
||||||
|
passwordField : 'password',
|
||||||
|
passReqToCallback : true
|
||||||
|
},
|
||||||
|
function(req, uEmail, uPassword, done) {
|
||||||
|
db.User.findOne({ 'email' : uEmail }).then((user) => {
|
||||||
|
if (user) {
|
||||||
|
user.validatePassword(uPassword).then((isValid) => {
|
||||||
|
return (isValid) ? done(null, user) : done(null, false);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return done(null, false);
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
db.onReady.then(() => {
|
}
|
||||||
|
|
||||||
/*if(db.User.count() < 1) {
|
// Google ID
|
||||||
winston.info('No administrator account found. Creating a new one...');
|
|
||||||
if(db.User.insert({
|
|
||||||
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: ');
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return true;
|
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(() => {
|
||||||
|
|
||||||
|
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,
|
||||||
|
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;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
@ -21,15 +21,36 @@ module.exports = (confPath) => {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _.defaultsDeep(appconfig, {
|
// Merge with defaults
|
||||||
|
|
||||||
|
appconfig = _.defaultsDeep(appconfig, {
|
||||||
title: "Requarks Wiki",
|
title: "Requarks Wiki",
|
||||||
host: "http://localhost",
|
host: "http://localhost",
|
||||||
port: process.env.PORT,
|
port: process.env.PORT,
|
||||||
wsPort: 8080,
|
auth: {
|
||||||
|
local: { enabled: true },
|
||||||
|
microsoft: { enabled: false },
|
||||||
|
google: { enabled: false },
|
||||||
|
facebook: { enabled: false },
|
||||||
|
},
|
||||||
db: "mongodb://localhost/wiki",
|
db: "mongodb://localhost/wiki",
|
||||||
redis: null,
|
redis: null,
|
||||||
sessionSecret: null,
|
sessionSecret: null,
|
||||||
admin: 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;
|
||||||
|
|
||||||
};
|
};
|
@ -6,7 +6,7 @@ module.exports = (isDebug) => {
|
|||||||
|
|
||||||
winston.remove(winston.transports.Console);
|
winston.remove(winston.transports.Console);
|
||||||
winston.add(winston.transports.Console, {
|
winston.add(winston.transports.Console, {
|
||||||
level: (isDebug) ? 'info' : 'warn',
|
level: (isDebug) ? 'debug' : 'info',
|
||||||
prettyPrint: true,
|
prettyPrint: true,
|
||||||
colorize: true,
|
colorize: true,
|
||||||
silent: false,
|
silent: false,
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const modb = require('mongoose'),
|
const modb = require('mongoose'),
|
||||||
Promise = require('bluebird'),
|
Promise = require('bluebird'),
|
||||||
|
bcrypt = require('bcryptjs-then'),
|
||||||
_ = require('lodash');
|
_ = require('lodash');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,13 +13,75 @@ const modb = require('mongoose'),
|
|||||||
var userSchema = modb.Schema({
|
var userSchema = modb.Schema({
|
||||||
|
|
||||||
email: {
|
email: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
index: true
|
||||||
|
},
|
||||||
|
|
||||||
|
provider: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
}
|
},
|
||||||
|
|
||||||
|
providerId: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
|
||||||
|
password: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
|
||||||
|
rights: [{
|
||||||
|
type: String
|
||||||
|
}]
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: {}
|
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);
|
module.exports = modb.model('User', userSchema);
|
@ -73,7 +73,11 @@
|
|||||||
"mongoose": "^4.6.3",
|
"mongoose": "^4.6.3",
|
||||||
"multer": "^1.2.0",
|
"multer": "^1.2.0",
|
||||||
"passport": "^0.3.2",
|
"passport": "^0.3.2",
|
||||||
|
"passport-facebook": "^2.1.1",
|
||||||
|
"passport-google-oauth20": "^1.0.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
|
"passport-windowslive": "^1.0.2",
|
||||||
|
"passport.socketio": "^3.6.2",
|
||||||
"pug": "^2.0.0-beta6",
|
"pug": "^2.0.0-beta6",
|
||||||
"read-chunk": "^2.0.0",
|
"read-chunk": "^2.0.0",
|
||||||
"remove-markdown": "^0.1.0",
|
"remove-markdown": "^0.1.0",
|
||||||
|
35
server.js
35
server.js
@ -46,6 +46,7 @@ const http = require('http');
|
|||||||
const i18next_backend = require('i18next-node-fs-backend');
|
const i18next_backend = require('i18next-node-fs-backend');
|
||||||
const i18next_mw = require('i18next-express-middleware');
|
const i18next_mw = require('i18next-express-middleware');
|
||||||
const passport = require('passport');
|
const passport = require('passport');
|
||||||
|
const passportSocketIo = require('passport.socketio');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const session = require('express-session');
|
const session = require('express-session');
|
||||||
const sessionMongoStore = require('connect-mongo')(session);
|
const sessionMongoStore = require('connect-mongo')(session);
|
||||||
@ -81,15 +82,16 @@ app.use(express.static(path.join(ROOTPATH, 'assets')));
|
|||||||
// Session
|
// 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(cookieParser());
|
||||||
app.use(session({
|
app.use(session({
|
||||||
name: 'requarkswiki.sid',
|
name: 'requarkswiki.sid',
|
||||||
store: new sessionMongoStore({
|
store: sessionStore,
|
||||||
mongooseConnection: db.connection,
|
|
||||||
touchAfter: 15
|
|
||||||
}),
|
|
||||||
secret: appconfig.sessionSecret,
|
secret: appconfig.sessionSecret,
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false
|
saveUninitialized: false
|
||||||
@ -144,9 +146,9 @@ app.use(mw.flash);
|
|||||||
|
|
||||||
app.use('/', ctrl.auth);
|
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('/admin', mw.auth, ctrl.admin);
|
||||||
app.use('/', ctrl.pages);
|
app.use('/', mw.auth, ctrl.pages);
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
// Error handling
|
// 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);
|
io.on('connection', ctrl.ws);
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
|
@ -27,14 +27,33 @@ html
|
|||||||
|
|
||||||
body
|
body
|
||||||
#bg
|
#bg
|
||||||
each bg in [1, 2, 3]
|
each bg in _.sampleSize([1, 2, 3],3)
|
||||||
div(style="background-image:url(/images/bg_" + bg + ".jpg);")
|
div(style="background-image:url(/images/bg_" + bg + ".jpg);")
|
||||||
#root
|
#root
|
||||||
h1= appconfig.title
|
h1= appconfig.title
|
||||||
h2 Login required
|
h2 Login required
|
||||||
input#login-user(type='text', placeholder='Email address')
|
if appconfig.auth.local.enabled
|
||||||
input#login-pass(type='password', placeholder='Password')
|
input#login-user(type='text', placeholder='Email address')
|
||||||
button Log In
|
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
|
#copyright
|
||||||
= t('footer.poweredby') + ' '
|
= t('footer.poweredby') + ' '
|
||||||
a.icon(href='https://github.com/Requarks/wiki')
|
a.icon(href='https://github.com/Requarks/wiki')
|
||||||
|
Loading…
Reference in New Issue
Block a user