import loopback from 'loopback'; import debugFactory from 'debug'; import { setProfileFromGithub, getFirstImageFromProfile, getUsernameFromProvider, getSocialProvider } from '../../server/utils/auth'; const { defaultProfileImage } = require('../utils/constantStrings.json'); const githubRegex = (/github/i); const debug = debugFactory('freecc:models:userIdent'); function createAccessToken(user, ttl, cb) { if (arguments.length === 2 && typeof ttl === 'function') { cb = ttl; ttl = 0; } user.accessTokens.create({ created: new Date(), ttl: Math.min(ttl || user.constructor.settings.ttl, user.constructor.settings.maxTTL) }, cb); } export default function(UserIdent) { // original source // github.com/strongloop/loopback-component-passport UserIdent.login = function( provider, authScheme, profile, credentials, options, cb ) { options = options || {}; if (typeof options === 'function' && !cb) { cb = options; options = {}; } var autoLogin = options.autoLogin || !options.autoLogin; var userIdentityModel = UserIdent; profile.id = profile.id || profile.openid; userIdentityModel.findOne({ where: { provider: getSocialProvider(provider), externalId: profile.id } }, function(err, identity) { if (err) { return cb(err); } if (identity) { identity.credentials = credentials; return identity.updateAttributes({ profile: profile, credentials: credentials, modified: new Date() }, function(err) { if (err) { return cb(err); } // Find the user for the given identity return identity.user(function(err, user) { // Create access token if the autoLogin flag is set to true if (!err && user && autoLogin) { return (options.createAccessToken || createAccessToken)( user, function(err, token) { cb(err, user, identity, token); } ); } cb(err, user, identity); }); }); } // Find the user model var userModel = userIdentityModel.relations.user && userIdentityModel.relations.user.modelTo || loopback.getModelByType(loopback.User); var userObj = options.profileToUser(provider, profile, options); if (!userObj.email && !options.emailOptional) { process.nextTick(function() { return cb('email is missing from the user profile'); }); } var query; if (userObj.email) { query = { or: [ { username: userObj.username }, { email: userObj.email } ]}; } else { query = { username: userObj.username }; } userModel.findOrCreate({ where: query }, userObj, function(err, user) { if (err) { return cb(err); } var date = new Date(); userIdentityModel.create({ provider: getSocialProvider(provider), externalId: profile.id, authScheme: authScheme, profile: profile, credentials: credentials, userId: user.id, created: date, modified: date }, function(err, identity) { if (!err && user && autoLogin) { return (options.createAccessToken || createAccessToken)( user, function(err, token) { cb(err, user, identity, token); } ); } cb(err, user, identity); }); }); }); }; UserIdent.observe('before save', function(ctx, next) { var userIdent = ctx.currentInstance || ctx.instance; if (!userIdent) { debug('no user identity instance found'); return next(); } userIdent.user(function(err, user) { let userChanged = false; if (err) { return next(err); } if (!user) { debug('no user attached to identity!'); return next(); } const { profile, provider } = userIdent; const picture = getFirstImageFromProfile(profile); debug('picture', picture, user.picture); // check if picture was found // check if user has no picture // check if user has default picture // set user.picture from oauth provider if ( picture && (!user.picture || user.picture === defaultProfileImage) ) { debug('setting user picture'); user.picture = picture; userChanged = true; } if (!githubRegex.test(provider) && profile) { user[provider] = getUsernameFromProvider(provider, profile); userChanged = true; } // if user signed in with github refresh their info if (githubRegex.test(provider) && profile && profile._json) { debug("user isn't github cool or username from github is different"); setProfileFromGithub(user, profile, profile._json); userChanged = true; } if (userChanged) { return user.save(function(err) { if (err) { return next(err); } next(); }); } debug('exiting after user identity before save'); next(); }); }); }