Permalink
| 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('fcc: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); | |
| } | |
| ); | |
| } | |
| return 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 }; | |
| } | |
| return userModel.findOrCreate({ where: query }, userObj, (err, user) => { | |
| if (err) { | |
| return cb(err); | |
| } | |
| var date = new Date(); | |
| return 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); | |
| } | |
| ); | |
| } | |
| return 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(); | |
| } | |
| return 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); } | |
| return next(); | |
| }); | |
| } | |
| debug('exiting after user identity before save'); | |
| return next(); | |
| }); | |
| }); | |
| } |