From fa37dc865d7165d90508b1d9b483095e1f568bec Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 11 Feb 2016 22:33:54 -0800 Subject: [PATCH] Reduce initial user query load Refactor passport to own file --- package.json | 1 + server/component-passport.js | 114 +++++++++++++++++++++++++++++++++++ server/server.js | 73 +--------------------- 3 files changed, 118 insertions(+), 70 deletions(-) create mode 100644 server/component-passport.js diff --git a/package.json b/package.json index 739e202db7..186a18056c 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,7 @@ "normalize-url": "^1.3.1", "normalizr": "^2.0.0", "object.assign": "^4.0.3", + "passport": "^0.2.1", "passport-facebook": "^2.0.0", "passport-github": "^1.0.0", "passport-google-oauth2": "~0.1.6", diff --git a/server/component-passport.js b/server/component-passport.js new file mode 100644 index 0000000000..b9e1635af9 --- /dev/null +++ b/server/component-passport.js @@ -0,0 +1,114 @@ +import passport from 'passport'; +import { PassportConfigurator } from 'loopback-component-passport'; +import passportProviders from './passport-providers'; +import uuid from 'node-uuid'; +import { generateKey } from 'loopback-component-passport/lib/models/utils'; + +import { + setProfileFromGithub, + getSocialProvider, + getUsernameFromProvider +} from './utils/auth'; + +const passportOptions = { + emailOptional: true, + profileToUser(provider, profile) { + var emails = profile.emails; + // NOTE(berks): get email or set to null. + // MongoDB indexs email but can be sparse(blank) + var email = emails && emails[0] && emails[0].value ? + emails[0].value : + null; + + // create random username + // username will be assigned when camper signups for Github + var username = 'fcc' + uuid.v4().slice(0, 8); + var password = generateKey('password'); + var userObj = { + username: username, + password: password + }; + + if (email) { + userObj.email = email; + } + + if (!(/github/).test(provider)) { + userObj[getSocialProvider(provider)] = getUsernameFromProvider( + getSocialProvider(provider), + profile + ); + } + + if (/github/.test(provider)) { + setProfileFromGithub(userObj, profile, profile._json); + } + 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) => { + + this.userModel.findById(id, { fields }, (err, user) => { + if (err || !user) { + return done(err, user); + } + 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; + done(null, user); + }); + }); + }); +}; + +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 + } + ); + }); +} diff --git a/server/server.js b/server/server.js index 1f711cd92e..1d5f9aefda 100755 --- a/server/server.js +++ b/server/server.js @@ -3,96 +3,29 @@ var pmx = require('pmx'); pmx.init(); var _ = require('lodash'), - uuid = require('node-uuid'), - assign = require('lodash').assign, loopback = require('loopback'), boot = require('loopback-boot'), expressState = require('express-state'), path = require('path'), - passportProviders = require('./passport-providers'); + setupPassport = require('./component-passport'); -var setProfileFromGithub = require('./utils/auth').setProfileFromGithub; -var getSocialProvider = require('./utils/auth').getSocialProvider; -var getUsernameFromProvider = require('./utils/auth').getUsernameFromProvider; -var generateKey = - require('loopback-component-passport/lib/models/utils').generateKey; - -var isBeta = !!process.env.BETA; var app = loopback(); +var isBeta = !!process.env.BETA; expressState.extend(app); app.set('state namespace', '__fcc__'); - -var PassportConfigurator = - require('loopback-component-passport').PassportConfigurator; -var passportConfigurator = new PassportConfigurator(app); - app.set('port', process.env.PORT || 3000); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); app.use(loopback.token()); app.disable('x-powered-by'); -// adds passport initialization after session middleware phase is complete -passportConfigurator.init(); - boot(app, { appRootDir: __dirname, dev: process.env.NODE_ENV }); - -passportConfigurator.setupModels({ - userModel: app.models.user, - userIdentityModel: app.models.userIdentity, - userCredentialModel: app.models.userCredential -}); - -var passportOptions = { - emailOptional: true, - profileToUser: function(provider, profile) { - var emails = profile.emails; - // NOTE(berks): get email or set to null. - // MongoDB indexs email but can be sparse(blank) - var email = emails && emails[0] && emails[0].value ? - emails[0].value : - null; - - // create random username - // username will be assigned when camper signups for GitHub - var username = 'fcc' + uuid.v4().slice(0, 8); - var password = generateKey('password'); - var userObj = { - username: username, - password: password - }; - - if (email) { - userObj.email = email; - } - - if (!(/github/).test(provider)) { - userObj[getSocialProvider(provider)] = getUsernameFromProvider( - getSocialProvider(provider), - profile - ); - } - - if (/github/.test(provider)) { - setProfileFromGithub(userObj, profile, profile._json); - } - return userObj; - } -}; - -Object.keys(passportProviders).map(function(strategy) { - var config = passportProviders[strategy]; - config.session = config.session !== false; - passportConfigurator.configureProvider( - strategy, - assign(config, passportOptions) - ); -}); +setupPassport(app); app.start = _.once(function() { app.listen(app.get('port'), function() {