| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  | import { Observable } from 'rx'; | 
					
						
							|  |  |  | // import debug from 'debug';
 | 
					
						
							|  |  |  | import dedent from 'dedent'; | 
					
						
							| 
									
										
										
										
											2015-06-11 11:38:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-12 12:15:19 -07:00
										 |  |  | import { | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |   getSocialProvider, | 
					
						
							| 
									
										
										
										
											2015-08-21 16:08:49 -07:00
										 |  |  |   getUsernameFromProvider, | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |   createUserUpdatesFromProfile | 
					
						
							| 
									
										
										
										
											2015-08-12 12:15:19 -07:00
										 |  |  | } from '../../server/utils/auth'; | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  | import { observeMethod, observeQuery } from '../../server/utils/rx'; | 
					
						
							|  |  |  | import { wrapHandledError } from '../../server/utils/create-handled-error.js'; | 
					
						
							| 
									
										
										
										
											2015-08-12 12:15:19 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  | // const log = debug('fcc:models:userIdent');
 | 
					
						
							| 
									
										
										
										
											2015-06-11 11:38:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-04 14:52:06 -07:00
										 |  |  | export default function(UserIdent) { | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |   UserIdent.on('dataSourceAttached', () => { | 
					
						
							|  |  |  |     UserIdent.findOne$ = observeMethod(UserIdent, 'findOne'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-08-12 19:08:05 -07:00
										 |  |  |   // original source
 | 
					
						
							|  |  |  |   // github.com/strongloop/loopback-component-passport
 | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |   // find identity if it exist
 | 
					
						
							|  |  |  |   // if not redirect to email signup
 | 
					
						
							|  |  |  |   // if yes and github
 | 
					
						
							|  |  |  |   //   update profile
 | 
					
						
							|  |  |  |   //   update username
 | 
					
						
							|  |  |  |   //   update picture
 | 
					
						
							| 
									
										
										
										
											2015-08-12 19:08:05 -07:00
										 |  |  |   UserIdent.login = function( | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |     _provider, | 
					
						
							| 
									
										
										
										
											2015-08-12 19:08:05 -07:00
										 |  |  |     authScheme, | 
					
						
							|  |  |  |     profile, | 
					
						
							|  |  |  |     credentials, | 
					
						
							|  |  |  |     options, | 
					
						
							|  |  |  |     cb | 
					
						
							|  |  |  |   ) { | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |     const User = UserIdent.app.models.User; | 
					
						
							|  |  |  |     const AccessToken = UserIdent.app.models.AccessToken; | 
					
						
							|  |  |  |     const provider = getSocialProvider(_provider); | 
					
						
							| 
									
										
										
										
											2015-08-12 19:08:05 -07:00
										 |  |  |     options = options || {}; | 
					
						
							|  |  |  |     if (typeof options === 'function' && !cb) { | 
					
						
							|  |  |  |       cb = options; | 
					
						
							|  |  |  |       options = {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     profile.id = profile.id || profile.openid; | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |     const query = { | 
					
						
							| 
									
										
										
										
											2015-08-12 19:08:05 -07:00
										 |  |  |       where: { | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |         provider: provider, | 
					
						
							| 
									
										
										
										
											2015-08-12 19:08:05 -07:00
										 |  |  |         externalId: profile.id | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |       }, | 
					
						
							|  |  |  |       include: 'user' | 
					
						
							| 
									
										
										
										
											2016-04-21 20:35:19 -07:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |     return UserIdent.findOne$(query) | 
					
						
							|  |  |  |       .flatMap(identity => { | 
					
						
							|  |  |  |         if (!identity) { | 
					
						
							|  |  |  |           throw wrapHandledError( | 
					
						
							|  |  |  |             new Error('user identity account not found'), | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               message: dedent`
 | 
					
						
							|  |  |  |                 New accounts can only be created using an email address. | 
					
						
							|  |  |  |                 Please create an account below | 
					
						
							|  |  |  |               `,
 | 
					
						
							|  |  |  |               type: 'info', | 
					
						
							|  |  |  |               redirectTo: '/signup' | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           ); | 
					
						
							| 
									
										
										
										
											2016-04-21 20:35:19 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |         const modified = new Date(); | 
					
						
							|  |  |  |         const user = identity.user(); | 
					
						
							|  |  |  |         if (!user) { | 
					
						
							|  |  |  |           const username = getUsernameFromProvider(provider, profile); | 
					
						
							|  |  |  |           return observeQuery( | 
					
						
							|  |  |  |             identity, | 
					
						
							|  |  |  |             'updateAttributes', | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               isOrphaned: username || true | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           ) | 
					
						
							|  |  |  |             .do(() => { | 
					
						
							|  |  |  |               throw wrapHandledError( | 
					
						
							|  |  |  |                 new Error('user identity is not associated with a user'), | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   type: 'info', | 
					
						
							|  |  |  |                   redirectTo: '/signup', | 
					
						
							|  |  |  |                   message: dedent`
 | 
					
						
							|  |  |  |   The user account associated with the ${provider} user ${username || 'Anon'} | 
					
						
							|  |  |  |   no longer exists. | 
					
						
							|  |  |  |                   `
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               ); | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2016-04-21 20:35:19 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-07-13 11:39:07 -07:00
										 |  |  |         const updateUser = User.update$( | 
					
						
							|  |  |  |           { id: user.id }, | 
					
						
							|  |  |  |           createUserUpdatesFromProfile(provider, profile) | 
					
						
							|  |  |  |         ).map(() => user); | 
					
						
							|  |  |  |         // identity already exists
 | 
					
						
							|  |  |  |         // find user and log them in
 | 
					
						
							|  |  |  |         identity.credentials = credentials; | 
					
						
							|  |  |  |         const attributes = { | 
					
						
							|  |  |  |           // we no longer want to keep the profile
 | 
					
						
							|  |  |  |           // this is information we do not need or use
 | 
					
						
							|  |  |  |           profile: null, | 
					
						
							|  |  |  |           credentials: credentials, | 
					
						
							|  |  |  |           modified | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         const updateIdentity = observeQuery( | 
					
						
							|  |  |  |           identity, | 
					
						
							|  |  |  |           'updateAttributes', | 
					
						
							|  |  |  |           attributes | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         const createToken = observeQuery( | 
					
						
							|  |  |  |           AccessToken, | 
					
						
							|  |  |  |           'create', | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             userId: user.id, | 
					
						
							|  |  |  |             created: new Date(), | 
					
						
							|  |  |  |             ttl: user.constructor.settings.ttl | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         return Observable.combineLatest( | 
					
						
							|  |  |  |           updateUser, | 
					
						
							|  |  |  |           updateIdentity, | 
					
						
							|  |  |  |           createToken, | 
					
						
							|  |  |  |           (user, identity, token) => ({ user, identity, token }) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       .subscribe( | 
					
						
							|  |  |  |         ({ user, identity, token }) => cb(null, user, identity, token), | 
					
						
							|  |  |  |         cb | 
					
						
							|  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2015-08-12 19:08:05 -07:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2015-08-04 14:52:06 -07:00
										 |  |  | } |