| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  | import _ from 'lodash'; | 
					
						
							|  |  |  | import dedent from 'dedent'; | 
					
						
							|  |  |  | import { Observable } from 'rx'; | 
					
						
							|  |  |  | import debugFactory from 'debug'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   ifNoUser401, | 
					
						
							|  |  |  |   ifNoUserSend | 
					
						
							|  |  |  | } from '../utils/middleware'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   saveUser, | 
					
						
							|  |  |  |   observeQuery | 
					
						
							|  |  |  | } from '../utils/rx'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-05 19:58:44 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   frontEndChallangeId, | 
					
						
							|  |  |  |   fullStackChallangeId | 
					
						
							|  |  |  | } from '../utils/constantStrings.json'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-06 21:08:24 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   completeCommitment$ | 
					
						
							|  |  |  | } from '../utils/commit'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  | const debug = debugFactory('freecc:certification'); | 
					
						
							|  |  |  | const sendMessageToNonUser = ifNoUserSend( | 
					
						
							|  |  |  |   'must be logged in to complete.' | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function isCertified(frontEndIds, { completedChallenges, isFrontEndCert }) { | 
					
						
							|  |  |  |   if (isFrontEndCert) { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-10-07 16:30:51 -07:00
										 |  |  |   return _.every(frontEndIds, ({ id }) => { | 
					
						
							|  |  |  |     return _.some(completedChallenges, (challenge) => { | 
					
						
							|  |  |  |       return challenge.id === id || challenge._id === id; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default function certificate(app) { | 
					
						
							|  |  |  |   const router = app.loopback.Router(); | 
					
						
							|  |  |  |   const { Challenge } = app.models; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const frontEndChallangeIds$ = observeQuery( | 
					
						
							|  |  |  |     Challenge, | 
					
						
							|  |  |  |     'findById', | 
					
						
							|  |  |  |     frontEndChallangeId, | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-10-05 19:58:44 -07:00
										 |  |  |       id: true, | 
					
						
							|  |  |  |       tests: true, | 
					
						
							|  |  |  |       name: true, | 
					
						
							|  |  |  |       challengeType: true | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  |     .shareReplay(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const fullStackChallangeIds$ = observeQuery( | 
					
						
							|  |  |  |     Challenge, | 
					
						
							|  |  |  |     'findById', | 
					
						
							|  |  |  |     fullStackChallangeId, | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-10-05 19:58:44 -07:00
										 |  |  |       id: true, | 
					
						
							|  |  |  |       tests: true, | 
					
						
							|  |  |  |       name: true, | 
					
						
							|  |  |  |       challengeType: true | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  |     .shareReplay(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   router.post( | 
					
						
							|  |  |  |     '/certificate/verify/front-end', | 
					
						
							|  |  |  |     ifNoUser401, | 
					
						
							|  |  |  |     verifyCert | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   router.post( | 
					
						
							|  |  |  |     '/certificate/verify/full-stack', | 
					
						
							|  |  |  |     ifNoUser401, | 
					
						
							|  |  |  |     verifyCert | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   router.post( | 
					
						
							|  |  |  |     '/certificate/honest', | 
					
						
							|  |  |  |     sendMessageToNonUser, | 
					
						
							|  |  |  |     postHonest | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   app.use(router); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function verifyCert(req, res, next) { | 
					
						
							|  |  |  |     const isFront = req.path.split('/').pop() === 'front-end'; | 
					
						
							|  |  |  |     Observable.just({}) | 
					
						
							|  |  |  |       .flatMap(() => { | 
					
						
							|  |  |  |         if (isFront) { | 
					
						
							|  |  |  |           return frontEndChallangeIds$; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return fullStackChallangeIds$; | 
					
						
							|  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2015-10-05 19:58:44 -07:00
										 |  |  |       .flatMap(challenge => { | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |         const { user } = req; | 
					
						
							| 
									
										
										
										
											2015-10-05 19:58:44 -07:00
										 |  |  |         const { | 
					
						
							|  |  |  |           id, | 
					
						
							|  |  |  |           tests, | 
					
						
							|  |  |  |           name, | 
					
						
							|  |  |  |           challengeType | 
					
						
							|  |  |  |         } = challenge; | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |         if ( | 
					
						
							|  |  |  |           isFront && !user.isFrontEndCert && isCertified(tests, user) || | 
					
						
							|  |  |  |           !isFront && !user.isFullStackCert && isCertified(tests, user) | 
					
						
							|  |  |  |         ) { | 
					
						
							|  |  |  |           debug('certified'); | 
					
						
							|  |  |  |           if (isFront) { | 
					
						
							|  |  |  |             user.isFrontEndCert = true; | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             user.isFullStackCert = true; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2015-10-05 19:58:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |           user.completedChallenges.push({ | 
					
						
							|  |  |  |             id, | 
					
						
							|  |  |  |             name, | 
					
						
							|  |  |  |             completedDate: new Date(), | 
					
						
							|  |  |  |             challengeType | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2015-10-06 21:08:24 -07:00
										 |  |  |           return saveUser(user) | 
					
						
							|  |  |  |             // If user has commited to nonprofit,
 | 
					
						
							|  |  |  |             // this will complete his pledge
 | 
					
						
							|  |  |  |             .flatMap( | 
					
						
							|  |  |  |               user => completeCommitment$(user), | 
					
						
							|  |  |  |               (user, pledgeOrMessage) => { | 
					
						
							|  |  |  |                 if (typeof pledgeOrMessage === 'string') { | 
					
						
							|  |  |  |                   debug(pledgeOrMessage); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 // we are only interested in the user object
 | 
					
						
							|  |  |  |                 // so we ignore return from completeCommitment$
 | 
					
						
							|  |  |  |                 return user; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |         return Observable.just(user); | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       .subscribe( | 
					
						
							|  |  |  |         user => { | 
					
						
							|  |  |  |           if ( | 
					
						
							|  |  |  |             isFront && user.isFrontEndCert || | 
					
						
							|  |  |  |             !isFront && user.isFullStackCert | 
					
						
							|  |  |  |           ) { | 
					
						
							|  |  |  |             return res.status(200).send(true); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           return res.status(200).send( | 
					
						
							|  |  |  |             dedent`
 | 
					
						
							| 
									
										
										
										
											2015-10-07 02:22:04 -07:00
										 |  |  |               Looks like you have not completed the neccessary steps. | 
					
						
							|  |  |  |               Please return to the challenge map. | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |             `
 | 
					
						
							|  |  |  |           ); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         next | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function postHonest(req, res, next) { | 
					
						
							|  |  |  |     const { user } = req; | 
					
						
							|  |  |  |     user.isHonest = true; | 
					
						
							|  |  |  |     saveUser(user) | 
					
						
							|  |  |  |       .subscribe( | 
					
						
							|  |  |  |         (user) => { | 
					
						
							|  |  |  |           res.status(200).send(!!user.isHonest); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         next | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |