@ -16,23 +16,135 @@
hotswap = require ( '../hotswap' ) ,
utils = require ( '../../public/src/utils' ) ,
login _strategies = [ ] ,
controllers = require ( '../controllers' ) ;
loginStrategies = [ ] ;
function logout ( req , res ) {
if ( req . user && parseInt ( req . user . uid , 10 ) > 0 ) {
Auth . initialize = function ( app , middleware ) {
app . use ( passport . initialize ( ) ) ;
app . use ( passport . session ( ) ) ;
var ws = require ( '../socket.io' ) ;
ws . logoutUser ( req . user . uid ) ;
Auth . app = app ;
Auth . middleware = middleware ;
} ;
req . logout ( ) ;
Auth . getLoginStrategies = function ( ) {
return loginStrategies ;
} ;
Auth . reloadRoutes = function ( callback ) {
var router = express . Router ( ) ;
router . hotswapId = 'auth' ;
plugins . ready ( function ( ) {
loginStrategies . length = 0 ;
plugins . fireHook ( 'filter:auth.init' , loginStrategies , function ( err ) {
if ( err ) {
winston . error ( 'filter:auth.init - plugin failure' ) ;
return callback ( err ) ;
}
res . status ( 200 ) . send ( '' ) ;
loginStrategies . forEach ( function ( strategy ) {
if ( strategy . url ) {
router . get ( strategy . url , passport . authenticate ( strategy . name , {
scope : strategy . scope
} ) ) ;
}
router . get ( strategy . callbackURL , passport . authenticate ( strategy . name , {
successReturnToOrRedirect : nconf . get ( 'relative_path' ) + '/' ,
failureRedirect : nconf . get ( 'relative_path' ) + '/login'
} ) ) ;
} ) ;
router . post ( '/logout' , logout ) ;
router . post ( '/register' , Auth . middleware . applyCSRF , register ) ;
router . post ( '/login' , Auth . middleware . applyCSRF , login ) ;
hotswap . replace ( 'auth' , router ) ;
if ( typeof callback === 'function' ) {
callback ( ) ;
}
} ) ;
} ) ;
} ;
Auth . login = function ( username , password , next ) {
if ( ! username || ! password ) {
return next ( new Error ( '[[error:invalid-password]]' ) ) ;
}
var userslug = utils . slugify ( username ) ;
var uid ;
async . waterfall ( [
function ( next ) {
user . getUidByUserslug ( userslug , next ) ;
} ,
function ( _uid , next ) {
if ( ! _uid ) {
return next ( null , false , '[[error:no-user]]' ) ;
}
uid = _uid ;
user . auth . logAttempt ( uid , next ) ;
} ,
function ( next ) {
db . getObjectFields ( 'user:' + uid , [ 'password' , 'banned' ] , next ) ;
} ,
function ( userData , next ) {
if ( ! userData || ! userData . password ) {
return next ( new Error ( '[[error:invalid-user-data]]' ) ) ;
}
if ( userData . banned && parseInt ( userData . banned , 10 ) === 1 ) {
return next ( null , false , '[[error:user-banned]]' ) ;
}
Password . compare ( password , userData . password , next ) ;
} ,
function ( passwordMatch , next ) {
if ( ! passwordMatch ) {
return next ( null , false , '[[error:invalid-password]]' ) ;
}
user . auth . clearLoginAttempts ( uid ) ;
next ( null , { uid : uid } , '[[success:authentication-successful]]' ) ;
}
] , next ) ;
} ;
passport . use ( new passportLocal ( Auth . login ) ) ;
passport . serializeUser ( function ( user , done ) {
done ( null , user . uid ) ;
} ) ;
passport . deserializeUser ( function ( uid , done ) {
done ( null , {
uid : uid
} ) ;
} ) ;
function login ( req , res , next ) {
var continueLogin = function ( ) {
if ( parseInt ( meta . config . allowLocalLogin , 10 ) === 0 ) {
return res . status ( 404 ) . send ( '' ) ;
}
// Handle returnTo data
if ( req . body . hasOwnProperty ( 'returnTo' ) && ! req . session . returnTo ) {
req . session . returnTo = req . body . returnTo ;
}
if ( req . body . username && utils . isEmailValid ( req . body . username ) ) {
user . getUsernameByEmail ( req . body . username , function ( err , username ) {
if ( err ) {
return next ( err ) ;
}
req . body . username = username ? username : req . body . username ;
continueLogin ( req , res , next ) ;
} ) ;
} else {
continueLogin ( req , res , next ) ;
}
}
function continueLogin ( req , res , next ) {
passport . authenticate ( 'local' , function ( err , userData , info ) {
if ( err ) {
req . flash ( 'error' , info ) ;
@ -60,7 +172,11 @@
req . login ( {
uid : userData . uid
} , function ( ) {
} , function ( err ) {
if ( err ) {
req . flash ( 'error' , err . message ) ;
return res . redirect ( nconf . get ( 'relative_path' ) + '/login' ) ;
}
if ( userData . uid ) {
user . logIP ( userData . uid , req . ip ) ;
@ -76,32 +192,10 @@
}
} ) ;
} ) ( req , res , next ) ;
} ;
if ( meta . config . allowLocalLogin !== undefined && parseInt ( meta . config . allowLocalLogin , 10 ) === 0 ) {
return res . status ( 404 ) . send ( '' ) ;
}
// Handle returnTo data
if ( req . body . hasOwnProperty ( 'returnTo' ) && ! req . session . returnTo ) {
req . session . returnTo = req . body . returnTo ;
}
if ( req . body . username && utils . isEmailValid ( req . body . username ) ) {
user . getUsernameByEmail ( req . body . username , function ( err , username ) {
if ( err ) {
return next ( err ) ;
}
req . body . username = username ? username : req . body . username ;
continueLogin ( ) ;
} ) ;
} else {
continueLogin ( ) ;
}
}
function register ( req , res ) {
if ( meta . config . allowRegistration !== undefined && parseInt ( meta . config . allowRegistration , 10 ) === 0 ) {
if ( parseInt ( meta . config . allowRegistration , 10 ) === 0 ) {
return res . status ( 403 ) . send ( '' ) ;
}
@ -113,184 +207,50 @@
}
}
plugins . fireHook ( 'filter:register.check' , { req : req , res : res , userData : userData } , function ( err , data ) {
if ( err ) {
return res . redirect ( nconf . get ( 'relative_path' ) + '/register' + ( err . message ? '?error=' + err . message : '' ) ) ;
}
if ( userData . username . length < meta . config . minimumUsernameLength ) {
if ( ! userData . username || userData . username . length < meta . config . minimumUsernameLength ) {
return res . redirect ( nconf . get ( 'relative_path' ) + '/register?error=[[error:username-too-short]]' ) ;
} else if ( userData . username . length > meta . config . maximumUsernameLength ) {
} else if ( ! userData . username || userData . username . length > meta . config . maximumUsernameLength ) {
return res . redirect ( nconf . get ( 'relative_path' ) + '/register?error=[[error:username-too-long]]' ) ;
}
user . create ( userData , function ( err , uid ) {
if ( err || ! uid ) {
return res . redirect ( nconf . get ( 'relative_path' ) + '/register' ) ;
}
req . login ( {
uid : uid
} , function ( ) {
var uid ;
async . waterfall ( [
function ( next ) {
plugins . fireHook ( 'filter:register.check' , { req : req , res : res , userData : userData } , next ) ;
} ,
function ( data , next ) {
user . create ( data . userData , next ) ;
} ,
function ( _uid , next ) {
uid = _uid ;
req . login ( { uid : uid } , next ) ;
} ,
function ( next ) {
user . logIP ( uid , req . ip ) ;
require ( '../socket.io' ) . emitUserCount ( ) ;
user . notifications . sendWelcomeNotification ( uid ) ;
plugins . fireHook ( 'filter:register.complete' , { uid : uid , referrer : req . body . referrer } , function ( err , data ) {
if ( err ) {
return res . redirect ( nconf . get ( 'relative_path' ) + '/register' ) ;
plugins . fireHook ( 'filter:register.complete' , { uid : uid , referrer : req . body . referrer } , next ) ;
}
res . redirect ( nconf . get ( 'relative_path' ) + ( data . referrer ? data . referrer : '/' ) ) ;
} ) ;
} ) ;
} ) ;
} ) ;
}
Auth . initialize = function ( app , middleware ) {
app . use ( passport . initialize ( ) ) ;
app . use ( passport . session ( ) ) ;
Auth . app = app ;
Auth . middleware = middleware ;
} ;
Auth . get _login _strategies = function ( ) {
return login _strategies ;
} ;
Auth . reloadRoutes = function ( callback ) {
var router = express . Router ( ) ;
router . hotswapId = 'auth' ;
plugins . ready ( function ( ) {
// Reset the registered login strategies
login _strategies . length = 0 ;
plugins . fireHook ( 'filter:auth.init' , login _strategies , function ( err ) {
] , function ( err , data ) {
if ( err ) {
winston . error ( 'filter:auth.init - plugin failure' ) ;
}
var deprecList = [ ] ;
for ( var i in login _strategies ) {
if ( login _strategies . hasOwnProperty ( i ) ) {
var strategy = login _strategies [ i ] ;
/ *
Backwards compatibility block for v0 . 6.0
Remove this upon release of v0 . 6.0 - 1
Ref : nodebb / nodebb # 1849
* /
if ( strategy . icon . slice ( 0 , 3 ) !== 'fa-' ) {
deprecList . push ( strategy . name ) ;
strategy . icon = 'fa-' + strategy . icon + '-square' ;
}
/* End backwards compatibility block */
if ( strategy . url ) {
router . get ( strategy . url , passport . authenticate ( strategy . name , {
scope : strategy . scope
} ) ) ;
}
router . get ( strategy . callbackURL , passport . authenticate ( strategy . name , {
successReturnToOrRedirect : nconf . get ( 'relative_path' ) + '/' ,
failureRedirect : nconf . get ( 'relative_path' ) + '/login'
} ) ) ;
}
}
/ *
Backwards compatibility block for v0 . 6.0
Remove this upon release of v0 . 6.0 - 1
Ref : nodebb / nodebb # 1849
* /
if ( deprecList . length ) {
winston . warn ( '[plugins] Deprecation notice: SSO plugins should now pass in the full fontawesome icon name (e.g. "fa-facebook-o"). Please update the following plugins:' ) ;
for ( var x = 0 , numDeprec = deprecList . length ; x < numDeprec ; x ++ ) {
process . stdout . write ( ' * ' + deprecList [ x ] + '\n' ) ;
}
}
/* End backwards compatibility block */
router . post ( '/logout' , logout ) ;
router . post ( '/register' , Auth . middleware . applyCSRF , register ) ;
router . post ( '/login' , Auth . middleware . applyCSRF , login ) ;
hotswap . replace ( 'auth' , router ) ;
if ( typeof callback === 'function' ) {
callback ( ) ;
return res . redirect ( nconf . get ( 'relative_path' ) + '/register?error=' + err . message ) ;
}
res . redirect ( nconf . get ( 'relative_path' ) + ( data . referrer ? data . referrer : '/' ) ) ;
} ) ;
} ) ;
} ;
Auth . login = function ( username , password , next ) {
if ( ! username || ! password ) {
return next ( new Error ( '[[error:invalid-password]]' ) ) ;
}
var userslug = utils . slugify ( username ) ;
user . getUidByUserslug ( userslug , function ( err , uid ) {
if ( err ) {
return next ( err ) ;
}
if ( ! uid ) {
return next ( null , false , '[[error:no-user]]' ) ;
}
user . auth . logAttempt ( uid , function ( err ) {
if ( err ) {
return next ( null , false , err . message ) ;
}
db . getObjectFields ( 'user:' + uid , [ 'password' , 'banned' ] , function ( err , userData ) {
if ( err ) {
return next ( err ) ;
}
if ( ! userData || ! userData . password ) {
return next ( new Error ( '[[error:invalid-user-data]]' ) ) ;
}
function logout ( req , res ) {
if ( req . user && parseInt ( req . user . uid , 10 ) > 0 ) {
if ( userData . banned && parseInt ( userData . banned , 10 ) === 1 ) {
return next ( null , false , '[[error:user-banned]]' ) ;
}
require ( '../socket.io' ) . logoutUser ( req . user . uid ) ;
Password . compare ( password , userData . password , function ( err , res ) {
if ( err ) {
return next ( new Error ( 'bcrypt compare error' ) ) ;
req . logout ( ) ;
}
if ( ! res ) {
return next ( null , false , '[[error:invalid-password]]' ) ;
res . status ( 200 ) . send ( '' ) ;
}
user . auth . clearLoginAttempts ( uid ) ;
next ( null , {
uid : uid
} , '[[success:authentication-successful]]' ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ;
passport . use ( new passportLocal ( Auth . login ) ) ;
passport . serializeUser ( function ( user , done ) {
done ( null , user . uid ) ;
} ) ;
passport . deserializeUser ( function ( uid , done ) {
done ( null , {
uid : uid
} ) ;
} ) ;
} ( exports ) ) ;