2014-12-23 16:48:28 +00:00
var _ = require ( 'lodash' ) ,
passport = require ( 'passport' ) ,
LocalStrategy = require ( 'passport-local' ) . Strategy ,
FacebookStrategy = require ( 'passport-facebook' ) . Strategy ,
TwitterStrategy = require ( 'passport-twitter' ) . Strategy ,
GitHubStrategy = require ( 'passport-github' ) . Strategy ,
GoogleStrategy = require ( 'passport-google-oauth' ) . OAuth2Strategy ,
LinkedInStrategy = require ( 'passport-linkedin-oauth2' ) . Strategy ,
OAuthStrategy = require ( 'passport-oauth' ) . OAuthStrategy ,
OAuth2Strategy = require ( 'passport-oauth' ) . OAuth2Strategy ,
User = require ( '../models/User' ) ,
2015-01-09 21:54:38 +00:00
nodemailer = require ( 'nodemailer' ) ,
2014-12-23 16:48:28 +00:00
secrets = require ( './secrets' ) ;
2013-11-19 00:43:45 +00:00
2013-11-14 07:29:55 +00:00
passport . serializeUser ( function ( user , done ) {
2014-12-23 16:48:28 +00:00
done ( null , user . id ) ;
2013-11-14 07:29:55 +00:00
} ) ;
2013-11-14 03:19:37 +00:00
2013-11-14 07:29:55 +00:00
passport . deserializeUser ( function ( id , done ) {
2015-01-09 22:02:21 +00:00
User . findById ( id , function ( err , user ) {
2015-01-01 08:26:09 +00:00
done ( err , user ) ;
2014-12-23 16:48:28 +00:00
} ) ;
2013-11-14 07:29:55 +00:00
} ) ;
2013-11-14 03:19:37 +00:00
2015-01-09 21:54:38 +00:00
// Sign in using Email and Password.
passport . use ( new LocalStrategy ( { usernameField : 'email' } , function ( email , password , done ) {
User . findOne ( { email : email } , function ( err , user ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-09 21:54:38 +00:00
if ( ! user ) return done ( null , false , { message : 'Email ' + email + ' not found' } ) ;
user . comparePassword ( password , function ( err , isMatch ) {
if ( isMatch ) {
return done ( null , user ) ;
} else {
return done ( null , false , { message : 'Invalid email or password.' } ) ;
}
} ) ;
} ) ;
} ) ) ;
2014-11-19 23:30:36 +00:00
/ * *
* OAuth Strategy Overview
*
* - User is already logged in .
* - Check if there is an existing account with a < provider > id .
* - If there is , return an error message . ( Account merging not supported )
* - Else link new OAuth account with currently logged - in user .
* - User is not logged in .
* - Check if it ' s a returning user .
* - If returning user , sign in and we are done .
* - Else check if there is an existing account with user ' s email .
* - If there is , return an error message .
* - Else create a new account .
* /
2015-01-09 21:54:38 +00:00
// Sign in with Facebook.
passport . use ( new FacebookStrategy ( secrets . facebook , function ( req , accessToken , refreshToken , profile , done ) {
if ( req . user ) {
User . findOne ( { facebook : profile . id } , function ( err , existingUser ) {
if ( existingUser ) {
req . flash ( 'errors' , { msg : 'There is already a Facebook account that belongs to you. Sign in with that account or delete it, then link it with your current account.' } ) ;
2015-03-23 05:07:58 +00:00
done ( ) ;
2015-01-09 21:54:38 +00:00
} else {
User . findById ( req . user . id , function ( err , user ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-09 21:54:38 +00:00
user . facebook = profile . id ;
user . tokens . push ( { kind : 'facebook' , accessToken : accessToken } ) ;
user . profile . name = user . profile . name || profile . displayName ;
user . profile . gender = user . profile . gender || profile . _json . gender ;
2015-03-12 06:58:16 +00:00
user . profile . picture = user . profile . picture || 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png' ;
2015-01-09 21:54:38 +00:00
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-09 21:54:38 +00:00
req . flash ( 'info' , { msg : 'Facebook account has been linked.' } ) ;
2015-03-23 05:07:58 +00:00
done ( null , user ) ;
2015-01-09 21:54:38 +00:00
} ) ;
} ) ;
}
} ) ;
} else {
User . findOne ( { facebook : profile . id } , function ( err , existingUser ) {
if ( existingUser ) return done ( null , existingUser ) ;
User . findOne ( { email : profile . _json . email } , function ( err , existingEmailUser ) {
2015-03-31 22:07:34 +00:00
if ( err ) { return done ( err ) ; }
2015-01-09 21:54:38 +00:00
if ( existingEmailUser ) {
req . flash ( 'errors' , { msg : 'There is already an account using this email address. Sign in to that account and link it with Facebook manually from Account Settings.' } ) ;
2015-03-23 05:07:58 +00:00
done ( ) ;
2015-01-09 21:54:38 +00:00
} else {
var user = new User ( ) ;
user . email = profile . _json . email ;
user . facebook = profile . id ;
user . tokens . push ( { kind : 'facebook' , accessToken : accessToken } ) ;
user . profile . name = profile . displayName ;
user . profile . gender = profile . _json . gender ;
user . profile . picture = 'https://graph.facebook.com/' + profile . id + '/picture?type=large' ;
user . profile . location = ( profile . _json . location ) ? profile . _json . location . name : '' ;
user . save ( function ( err ) {
2015-03-23 05:23:46 +00:00
done ( err , user ) ;
2015-03-31 22:07:34 +00:00
var transporter = nodemailer . createTransport ( {
service : 'Mandrill' ,
auth : {
user : secrets . mandrill . user ,
pass : secrets . mandrill . password
}
} ) ;
var mailOptions = {
to : user . email ,
from : 'Team@freecodecamp.com' ,
subject : 'Welcome to Free Code Camp!' ,
text : [
'Greetings from San Francisco!\n\n' ,
'Thank you for joining our community.\n' ,
'Feel free to email us at this address if you have any questions about Free Code Camp.\n' ,
"And if you have a moment, check out our blog: blog.freecodecamp.com.\n" ,
'Good luck with the challenges!\n\n' ,
'- Our All-Volunteer Team'
] . join ( '' )
} ;
transporter . sendMail ( mailOptions , function ( err ) {
if ( err ) { return err ; }
} ) ;
2015-01-09 21:54:38 +00:00
} ) ;
}
} ) ;
} ) ;
}
} ) ) ;
// Sign in with GitHub.
passport . use ( new GitHubStrategy ( secrets . github , function ( req , accessToken , refreshToken , profile , done ) {
if ( req . user ) {
User . findOne ( { github : profile . id } , function ( err , existingUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-09 21:54:38 +00:00
if ( existingUser ) {
req . flash ( 'errors' , { msg : 'There is already a GitHub account that belongs to you. Sign in with that account or delete it, then link it with your current account.' } ) ;
2015-03-23 05:07:58 +00:00
done ( ) ;
2015-01-09 21:54:38 +00:00
} else {
User . findById ( req . user . id , function ( err , user ) {
user . github = profile . id ;
user . tokens . push ( { kind : 'github' , accessToken : accessToken } ) ;
user . profile . name = user . profile . name || profile . displayName ;
user . profile . picture = user . profile . picture || profile . _json . avatar _url ;
user . profile . location = user . profile . location || profile . _json . location ;
user . profile . website = user . profile . website || profile . _json . blog ;
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-09 21:54:38 +00:00
req . flash ( 'info' , { msg : 'GitHub account has been linked.' } ) ;
2015-03-23 05:07:58 +00:00
done ( null , user ) ;
2015-01-09 21:54:38 +00:00
} ) ;
} ) ;
}
} ) ;
} else {
User . findOne ( { github : profile . id } , function ( err , existingUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-09 21:54:38 +00:00
if ( existingUser ) return done ( null , existingUser ) ;
User . findOne ( { email : profile . _json . email } , function ( err , existingEmailUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-09 21:54:38 +00:00
if ( existingEmailUser ) {
req . flash ( 'errors' , { msg : 'There is already an account using this email address. Sign in to that account and link it with GitHub manually from Account Settings.' } ) ;
2015-03-23 05:07:58 +00:00
done ( null ) ;
2015-01-09 21:54:38 +00:00
} else {
var user = new User ( ) ;
user . email = profile . _json . email ;
user . github = profile . id ;
user . tokens . push ( { kind : 'github' , accessToken : accessToken } ) ;
user . profile . name = profile . displayName ;
user . profile . picture = profile . _json . avatar _url ;
user . profile . location = profile . _json . location ;
user . profile . website = profile . _json . blog ;
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
var transporter = nodemailer . createTransport ( {
service : 'Mandrill' ,
auth : {
user : secrets . mandrill . user ,
pass : secrets . mandrill . password
}
} ) ;
var mailOptions = {
to : user . email ,
from : 'Team@freecodecamp.com' ,
subject : 'Welcome to Free Code Camp!' ,
text : [
'Greetings from San Francisco!\n\n' ,
'Thank you for joining our community.\n' ,
'Feel free to email us at this address if you have any questions about Free Code Camp.\n' ,
"And if you have a moment, check out our blog: blog.freecodecamp.com.\n" ,
'Good luck with the challenges!\n\n' ,
'- the Volunteer Camp Counselor Team'
] . join ( '' )
} ;
transporter . sendMail ( mailOptions , function ( err ) {
if ( err ) { return done ( err ) ; }
done ( null , user ) ;
} ) ;
2015-01-09 21:54:38 +00:00
} ) ;
}
} ) ;
} ) ;
}
} ) ) ;
2014-11-19 23:30:36 +00:00
// Sign in with Twitter.
2014-12-23 16:48:28 +00:00
2015-01-01 08:26:09 +00:00
passport . use ( new TwitterStrategy ( secrets . twitter , function ( req , accessToken , tokenSecret , profile , done ) {
if ( req . user ) {
User . findOne ( { twitter : profile . id } , function ( err , existingUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
if ( existingUser ) {
req . flash ( 'errors' , { msg : 'There is already a Twitter account that belongs to you. Sign in with that account or delete it, then link it with your current account.' } ) ;
2015-03-23 05:07:58 +00:00
done ( ) ;
2015-01-01 08:26:09 +00:00
} else {
User . findById ( req . user . id , function ( err , user ) {
user . twitter = profile . id ;
user . tokens . push ( { kind : 'twitter' , accessToken : accessToken , tokenSecret : tokenSecret } ) ;
2015-01-09 23:10:34 +00:00
user . profile . username = user . profile . username || profile . username . toLowerCase ( ) ;
2015-01-01 08:26:09 +00:00
user . profile . name = user . profile . name || profile . displayName ;
user . profile . location = user . profile . location || profile . _json . location ;
2015-01-09 21:02:00 +00:00
user . profile . picture = user . profile . picture || profile . _json . profile _image _url _https . replace ( '_normal' , '' ) ;
2015-01-09 23:10:34 +00:00
user . profile . twitterHandle = user . profile . twitterHandle || profile . username . toLowerCase ( ) ;
2015-01-01 08:26:09 +00:00
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
req . flash ( 'info' , { msg : 'Twitter account has been linked.' } ) ;
2015-03-23 05:07:58 +00:00
done ( null , user ) ;
2015-01-01 08:26:09 +00:00
} ) ;
} ) ;
}
} ) ;
2014-12-23 16:48:28 +00:00
2015-01-01 08:26:09 +00:00
} else {
User . findOne ( { twitter : profile . id } , function ( err , existingUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
if ( existingUser ) return done ( null , existingUser ) ;
var user = new User ( ) ;
2015-01-09 23:10:34 +00:00
user . profile . username = profile . username . toLowerCase ( ) ;
2015-01-01 08:26:09 +00:00
user . twitter = profile . id ;
user . tokens . push ( { kind : 'twitter' , accessToken : accessToken , tokenSecret : tokenSecret } ) ;
user . profile . name = profile . displayName ;
user . profile . location = profile . _json . location ;
2015-01-09 21:02:00 +00:00
user . profile . picture = profile . _json . profile _image _url _https . replace ( '_normal' , '' ) ;
2015-01-09 23:10:34 +00:00
user . profile . twitterHandle = user . profile . twitterHandle || profile . username . toLowerCase ( ) ;
2015-01-01 08:26:09 +00:00
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
done ( null , user ) ;
2015-01-01 08:26:09 +00:00
} ) ;
} ) ;
}
} ) ) ;
2014-12-23 16:48:28 +00:00
2015-01-01 08:26:09 +00:00
// Sign in with Google.
2014-11-19 23:30:36 +00:00
2015-01-01 08:26:09 +00:00
passport . use ( new GoogleStrategy ( secrets . google , function ( req , accessToken , refreshToken , profile , done ) {
if ( req . user ) {
User . findOne ( { google : profile . id } , function ( err , existingUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
if ( existingUser ) {
req . flash ( 'errors' , { msg : 'There is already a Google account that belongs to you. Sign in with that account or delete it, then link it with your current account.' } ) ;
2015-03-23 05:07:58 +00:00
done ( ) ;
2014-12-23 16:48:28 +00:00
} else {
2015-01-01 08:26:09 +00:00
User . findById ( req . user . id , function ( err , user ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
user . google = profile . id ;
user . tokens . push ( { kind : 'google' , accessToken : accessToken } ) ;
user . profile . name = user . profile . name || profile . displayName ;
user . profile . gender = user . profile . gender || profile . _json . gender ;
user . profile . picture = user . profile . picture || profile . _json . picture ;
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
req . flash ( 'info' , { msg : 'Google account has been linked.' } ) ;
2015-03-23 05:07:58 +00:00
done ( null , user ) ;
2015-01-01 08:26:09 +00:00
} ) ;
2014-11-19 23:30:36 +00:00
} ) ;
2014-12-23 16:48:28 +00:00
}
2015-01-01 08:26:09 +00:00
} ) ;
} else {
User . findOne ( { google : profile . id } , function ( err , existingUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
if ( existingUser ) return done ( null , existingUser ) ;
User . findOne ( { email : profile . _json . email } , function ( err , existingEmailUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
if ( existingEmailUser ) {
req . flash ( 'errors' , { msg : 'There is already an account using this email address. Sign in to that account and link it with Google manually from Account Settings.' } ) ;
2015-03-23 05:07:58 +00:00
done ( ) ;
2015-01-01 08:26:09 +00:00
} else {
var user = new User ( ) ;
user . email = profile . _json . email ;
user . google = profile . id ;
user . tokens . push ( { kind : 'google' , accessToken : accessToken } ) ;
user . profile . name = profile . displayName ;
user . profile . gender = profile . _json . gender ;
user . profile . picture = profile . _json . picture ;
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
var transporter = nodemailer . createTransport ( {
service : 'Mandrill' ,
auth : {
user : secrets . mandrill . user ,
pass : secrets . mandrill . password
}
} ) ;
var mailOptions = {
to : user . email ,
from : 'Team@freecodecamp.com' ,
subject : 'Welcome to Free Code Camp!' ,
text : [
'Greetings from San Francisco!\n\n' ,
'Thank you for joining our community.\n' ,
'Feel free to email us at this address if you have any questions about Free Code Camp.\n' ,
"And if you have a moment, check out our blog: blog.freecodecamp.com.\n" ,
'Good luck with the challenges!\n\n' ,
'- the Volunteer Camp Counselor Team'
] . join ( '' )
} ;
transporter . sendMail ( mailOptions , function ( err ) {
if ( err ) { return err ; }
done ( null , user ) ;
} ) ;
2015-01-09 21:54:38 +00:00
} ) ;
2015-01-01 08:26:09 +00:00
}
} ) ;
} ) ;
}
} ) ) ;
2014-10-15 21:53:36 +00:00
2014-11-19 23:30:36 +00:00
// Sign in with LinkedIn.
2014-12-23 16:48:28 +00:00
2015-01-01 08:26:09 +00:00
passport . use ( new LinkedInStrategy ( secrets . linkedin , function ( req , accessToken , refreshToken , profile , done ) {
if ( req . user ) {
User . findOne ( { linkedin : profile . id } , function ( err , existingUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
if ( existingUser ) {
req . flash ( 'errors' , { msg : 'There is already a LinkedIn account that belongs to you. Sign in with that account or delete it, then link it with your current account.' } ) ;
2015-03-23 05:07:58 +00:00
done ( ) ;
2014-12-23 16:48:28 +00:00
} else {
2015-01-01 08:26:09 +00:00
User . findById ( req . user . id , function ( err , user ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
user . linkedin = profile . id ;
user . tokens . push ( { kind : 'linkedin' , accessToken : accessToken } ) ;
user . profile . name = user . profile . name || profile . displayName ;
user . profile . location = user . profile . location || profile . _json . location . name ;
user . profile . picture = user . profile . picture || profile . _json . pictureUrl ;
user . profile . website = user . profile . website || profile . _json . publicProfileUrl ;
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
req . flash ( 'info' , { msg : 'LinkedIn account has been linked.' } ) ;
2015-03-23 05:07:58 +00:00
done ( null , user ) ;
2015-01-01 08:26:09 +00:00
} ) ;
} ) ;
}
} ) ;
} else {
User . findOne ( { linkedin : profile . id } , function ( err , existingUser ) {
if ( existingUser ) return done ( null , existingUser ) ;
User . findOne ( { email : profile . _json . emailAddress } , function ( err , existingEmailUser ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
2015-01-01 08:26:09 +00:00
if ( existingEmailUser ) {
req . flash ( 'errors' , { msg : 'There is already an account using this email address. Sign in to that account and link it with LinkedIn manually from Account Settings.' } ) ;
2015-03-23 05:07:58 +00:00
done ( ) ;
2015-01-01 08:26:09 +00:00
} else {
var user = new User ( ) ;
user . linkedin = profile . id ;
user . tokens . push ( { kind : 'linkedin' , accessToken : accessToken } ) ;
user . email = profile . _json . emailAddress ;
user . profile . name = profile . displayName ;
user . profile . location = profile . _json . location . name ;
user . profile . picture = profile . _json . pictureUrl ;
user . profile . website = profile . _json . publicProfileUrl ;
user . save ( function ( err ) {
2015-03-23 05:07:58 +00:00
if ( err ) { return done ( err ) ; }
var transporter = nodemailer . createTransport ( {
service : 'Mandrill' ,
auth : {
user : secrets . mandrill . user ,
pass : secrets . mandrill . password
}
} ) ;
var mailOptions = {
to : user . email ,
from : 'Team@freecodecamp.com' ,
subject : 'Welcome to Free Code Camp!' ,
text : [
'Greetings from San Francisco!\n\n' ,
'Thank you for joining our community.\n' ,
'Feel free to email us at this address if you have any questions about Free Code Camp.\n' ,
"And if you have a moment, check out our blog: blog.freecodecamp.com.\n" ,
'Good luck with the challenges!\n\n' ,
'- the Volunteer Camp Counselor Team'
] . join ( '' )
} ;
transporter . sendMail ( mailOptions , function ( err ) {
if ( err ) { return err ; }
done ( null , user ) ;
} ) ;
2015-01-01 08:26:09 +00:00
} ) ;
}
} ) ;
} ) ;
}
2014-11-19 23:30:36 +00:00
} ) ) ;
2015-01-09 22:02:21 +00:00
// Login Required middleware.
exports . isAuthenticated = function ( req , res , next ) {
2015-03-23 05:07:58 +00:00
if ( req . isAuthenticated ( ) ) { return next ( ) ; }
2014-11-30 06:30:02 +00:00
res . redirect ( '/login' ) ;
2015-01-09 22:02:21 +00:00
} ;
// Authorization Required middleware.
2014-11-30 06:30:02 +00:00
2015-01-09 22:02:21 +00:00
exports . isAuthorized = function ( req , res , next ) {
2014-11-30 06:30:02 +00:00
var provider = req . path . split ( '/' ) . slice ( - 1 ) [ 0 ] ;
if ( _ . find ( req . user . tokens , { kind : provider } ) ) {
2014-12-23 16:48:28 +00:00
next ( ) ;
2014-11-30 06:30:02 +00:00
} else {
2014-12-23 16:48:28 +00:00
res . redirect ( '/auth/' + provider ) ;
2014-11-30 06:30:02 +00:00
}
2015-03-23 05:07:58 +00:00
} ;