| 
									
										
										
										
											2016-02-11 22:33:54 -08:00
										 |  |  | import passport from 'passport'; | 
					
						
							|  |  |  | import { PassportConfigurator } from 'loopback-component-passport'; | 
					
						
							|  |  |  | import passportProviders from './passport-providers'; | 
					
						
							| 
									
										
										
										
											2016-12-30 13:05:29 -06:00
										 |  |  | import uuid from 'uuid'; | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:54 -08:00
										 |  |  | import { generateKey } from 'loopback-component-passport/lib/models/utils'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   setProfileFromGithub, | 
					
						
							|  |  |  |   getSocialProvider, | 
					
						
							|  |  |  |   getUsernameFromProvider | 
					
						
							|  |  |  | } from './utils/auth'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const passportOptions = { | 
					
						
							|  |  |  |   emailOptional: true, | 
					
						
							|  |  |  |   profileToUser(provider, profile) { | 
					
						
							| 
									
										
										
										
											2016-04-21 20:35:19 -07:00
										 |  |  |     const emails = profile.emails; | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:54 -08:00
										 |  |  |     // NOTE(berks): get email or set to null.
 | 
					
						
							|  |  |  |     // MongoDB indexs email but can be sparse(blank)
 | 
					
						
							| 
									
										
										
										
											2016-04-21 20:35:19 -07:00
										 |  |  |     const email = emails && emails[0] && emails[0].value ? | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:54 -08:00
										 |  |  |       emails[0].value : | 
					
						
							|  |  |  |       null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // create random username
 | 
					
						
							|  |  |  |     // username will be assigned when camper signups for Github
 | 
					
						
							| 
									
										
										
										
											2016-04-21 20:35:19 -07:00
										 |  |  |     const username = 'fcc' + uuid.v4().slice(0, 8); | 
					
						
							|  |  |  |     const password = generateKey('password'); | 
					
						
							|  |  |  |     let userObj = { | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:54 -08:00
										 |  |  |       username: username, | 
					
						
							|  |  |  |       password: password | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (email) { | 
					
						
							|  |  |  |       userObj.email = email; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!(/github/).test(provider)) { | 
					
						
							|  |  |  |       userObj[getSocialProvider(provider)] = getUsernameFromProvider( | 
					
						
							|  |  |  |         getSocialProvider(provider), | 
					
						
							|  |  |  |         profile | 
					
						
							|  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2016-07-05 19:20:12 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2016-04-21 20:35:19 -07:00
										 |  |  |       userObj = setProfileFromGithub(userObj, profile, profile._json); | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:54 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return userObj; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const fields = { | 
					
						
							|  |  |  |   progressTimestamps: false, | 
					
						
							|  |  |  |   completedChallenges: false, | 
					
						
							|  |  |  |   challengeMap: false | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PassportConfigurator.prototype.init = function passportInit(noSession) { | 
					
						
							|  |  |  |   this.app.middleware('session:after', passport.initialize()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (noSession) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   this.app.middleware('session:after', passport.session()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Serialization and deserialization is only required if passport session is
 | 
					
						
							|  |  |  |   // enabled
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   passport.serializeUser((user, done) => { | 
					
						
							|  |  |  |     done(null, user.id); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   passport.deserializeUser((id, done) => { | 
					
						
							| 
									
										
										
										
											2016-04-14 17:07:40 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     this.userModel.findById(id, { fields }, (err, user) => { | 
					
						
							|  |  |  |       if (err || !user) { | 
					
						
							|  |  |  |         return done(err, user); | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:54 -08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-04-14 17:07:40 -07:00
										 |  |  |       return this.app.dataSources.db.connector | 
					
						
							|  |  |  |         .collection('user') | 
					
						
							|  |  |  |         .aggregate([ | 
					
						
							|  |  |  |           { $match: { _id: user.id } }, | 
					
						
							|  |  |  |           { $project: { points: { $size: '$progressTimestamps' } } } | 
					
						
							|  |  |  |         ], function(err, [{ points = 1 } = {}]) { | 
					
						
							|  |  |  |           if (err) { return done(err); } | 
					
						
							|  |  |  |           user.points = points; | 
					
						
							|  |  |  |           return done(null, user); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:54 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default function setupPassport(app) { | 
					
						
							|  |  |  |   const configurator = new PassportConfigurator(app); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   configurator.setupModels({ | 
					
						
							|  |  |  |     userModel: app.models.user, | 
					
						
							|  |  |  |     userIdentityModel: app.models.userIdentity, | 
					
						
							|  |  |  |     userCredentialModel: app.models.userCredential | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   configurator.init(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Object.keys(passportProviders).map(function(strategy) { | 
					
						
							|  |  |  |     var config = passportProviders[strategy]; | 
					
						
							|  |  |  |     config.session = config.session !== false; | 
					
						
							|  |  |  |     configurator.configureProvider( | 
					
						
							|  |  |  |       strategy, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         ...config, | 
					
						
							|  |  |  |         ...passportOptions | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } |