| 
									
										
										
										
											2015-10-01 20:55:55 -07:00
										 |  |  |  | import dedent from 'dedent'; | 
					
						
							| 
									
										
										
										
											2016-01-19 21:11:20 -05:00
										 |  |  |  | import moment from 'moment-timezone'; | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  | import { Observable } from 'rx'; | 
					
						
							| 
									
										
										
										
											2015-08-20 09:40:03 -07:00
										 |  |  |  | import debugFactory from 'debug'; | 
					
						
							| 
									
										
										
										
											2016-09-20 18:24:43 +01:00
										 |  |  |  | import emoji from 'node-emoji'; | 
					
						
							| 
									
										
										
										
											2015-08-07 13:31:48 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-05 20:00:25 -07:00
										 |  |  |  | import { | 
					
						
							| 
									
										
										
										
											2015-12-09 12:28:19 -08:00
										 |  |  |  |   frontEndChallengeId, | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |   dataVisChallengeId, | 
					
						
							| 
									
										
										
										
											2015-12-09 12:28:19 -08:00
										 |  |  |  |   backEndChallengeId | 
					
						
							| 
									
										
										
										
											2015-10-05 20:00:25 -07:00
										 |  |  |  | } from '../utils/constantStrings.json'; | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  | import certTypes from '../utils/certTypes.json'; | 
					
						
							| 
									
										
										
										
											2016-06-23 20:05:30 -07:00
										 |  |  |  | import { | 
					
						
							|  |  |  |  |   ifNoUser401, | 
					
						
							| 
									
										
										
										
											2016-12-15 02:54:59 +05:30
										 |  |  |  |   ifNoUserRedirectTo, | 
					
						
							|  |  |  |  |   ifNotVerifiedRedirectToSettings | 
					
						
							| 
									
										
										
										
											2016-06-23 20:05:30 -07:00
										 |  |  |  | } from '../utils/middleware'; | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  | import { observeQuery } from '../utils/rx'; | 
					
						
							| 
									
										
										
										
											2016-02-09 09:10:18 -08:00
										 |  |  |  | import { | 
					
						
							|  |  |  |  |   prepUniqueDays, | 
					
						
							|  |  |  |  |   calcCurrentStreak, | 
					
						
							|  |  |  |  |   calcLongestStreak | 
					
						
							|  |  |  |  | } from '../utils/user-stats'; | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  | import supportedLanguages from '../../common/utils/supported-languages'; | 
					
						
							|  |  |  |  | import createNameIdMap from '../../common/utils/create-name-id-map'; | 
					
						
							|  |  |  |  | import { cachedMap } from '../utils/map'; | 
					
						
							| 
									
										
										
										
											2015-08-07 13:31:48 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-27 11:34:44 -08:00
										 |  |  |  | const debug = debugFactory('fcc:boot:user'); | 
					
						
							| 
									
										
										
										
											2015-10-01 20:55:55 -07:00
										 |  |  |  | const sendNonUserToMap = ifNoUserRedirectTo('/map'); | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  | const certIds = { | 
					
						
							|  |  |  |  |   [certTypes.frontEnd]: frontEndChallengeId, | 
					
						
							|  |  |  |  |   [certTypes.dataVis]: dataVisChallengeId, | 
					
						
							|  |  |  |  |   [certTypes.backEnd]: backEndChallengeId | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const certViews = { | 
					
						
							|  |  |  |  |   [certTypes.frontEnd]: 'certificate/front-end.jade', | 
					
						
							|  |  |  |  |   [certTypes.dataVis]: 'certificate/data-vis.jade', | 
					
						
							|  |  |  |  |   [certTypes.backEnd]: 'certificate/back-end.jade', | 
					
						
							|  |  |  |  |   [certTypes.fullStack]: 'certificate/full-stack.jade' | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const certText = { | 
					
						
							| 
									
										
										
										
											2016-04-03 09:53:40 +02:00
										 |  |  |  |   [certTypes.frontEnd]: 'Front End certified', | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |   [certTypes.dataVis]: 'Data Vis Certified', | 
					
						
							|  |  |  |  |   [certTypes.backEnd]: 'Back End Certified', | 
					
						
							|  |  |  |  |   [certTypes.fullStack]: 'Full Stack Certified' | 
					
						
							|  |  |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-08-19 13:05:53 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-19 21:11:20 -05:00
										 |  |  |  | const dateFormat = 'MMM DD, YYYY'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-06 16:39:15 -07:00
										 |  |  |  | function replaceScriptTags(value) { | 
					
						
							|  |  |  |  |   return value | 
					
						
							|  |  |  |  |     .replace(/<script>/gi, 'fccss') | 
					
						
							|  |  |  |  |     .replace(/<\/script>/gi, 'fcces'); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 11:30:47 -08:00
										 |  |  |  | function replaceFormAction(value) { | 
					
						
							|  |  |  |  |   return value.replace(/<form[^>]*>/, function(val) { | 
					
						
							|  |  |  |  |     return val.replace(/action(\s*?)=/, 'fccfaa$1='); | 
					
						
							|  |  |  |  |   }); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function encodeFcc(value = '') { | 
					
						
							|  |  |  |  |   return replaceScriptTags(replaceFormAction(value)); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  | function isAlgorithm(challenge) { | 
					
						
							|  |  |  |  |   // test if name starts with hike/waypoint/basejump/zipline
 | 
					
						
							|  |  |  |  |   // fix for bug that saved different challenges with incorrect
 | 
					
						
							|  |  |  |  |   // challenge types
 | 
					
						
							|  |  |  |  |   return !(/^(waypoint|hike|zipline|basejump)/i).test(challenge.name) && | 
					
						
							|  |  |  |  |     +challenge.challengeType === 5; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function isProject(challenge) { | 
					
						
							|  |  |  |  |   return +challenge.challengeType === 3 || | 
					
						
							|  |  |  |  |     +challenge.challengeType === 4; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function getChallengeGroup(challenge) { | 
					
						
							|  |  |  |  |   if (isProject(challenge)) { | 
					
						
							|  |  |  |  |     return 'projects'; | 
					
						
							|  |  |  |  |   } else if (isAlgorithm(challenge)) { | 
					
						
							|  |  |  |  |     return 'algorithms'; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   return 'challenges'; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  | // buildDisplayChallenges(
 | 
					
						
							|  |  |  |  | //   entities: { challenge: Object, challengeIdToName: Object },
 | 
					
						
							|  |  |  |  | //   challengeMap: Object,
 | 
					
						
							|  |  |  |  | //   tz: String
 | 
					
						
							|  |  |  |  | // ) => Observable[{
 | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  | //   algorithms: Array,
 | 
					
						
							|  |  |  |  | //   projects: Array,
 | 
					
						
							|  |  |  |  | //   challenges: Array
 | 
					
						
							|  |  |  |  | // }]
 | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  | function buildDisplayChallenges( | 
					
						
							|  |  |  |  |   { challenge: challengeMap = {}, challengeIdToName }, | 
					
						
							|  |  |  |  |   userChallengeMap = {}, | 
					
						
							|  |  |  |  |   timezone | 
					
						
							|  |  |  |  | ) { | 
					
						
							|  |  |  |  |   return Observable.from(Object.keys(userChallengeMap)) | 
					
						
							|  |  |  |  |     .map(challengeId => userChallengeMap[challengeId]) | 
					
						
							|  |  |  |  |     .map(userChallenge => { | 
					
						
							|  |  |  |  |       const challengeId = userChallenge.id; | 
					
						
							|  |  |  |  |       const challenge = challengeMap[ challengeIdToName[challengeId] ]; | 
					
						
							|  |  |  |  |       let finalChallenge = { ...userChallenge, ...challenge }; | 
					
						
							|  |  |  |  |       if (userChallenge.completedDate) { | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |         finalChallenge.completedDate = moment | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  |           .tz(userChallenge.completedDate, timezone) | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |           .format(dateFormat); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  |       if (userChallenge.lastUpdated) { | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |         finalChallenge.lastUpdated = moment | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  |           .tz(userChallenge.lastUpdated, timezone) | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |           .format(dateFormat); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       return finalChallenge; | 
					
						
							|  |  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2016-02-14 17:10:26 -08:00
										 |  |  |  |     .filter(({ challengeType }) => challengeType !== 6) | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |     .groupBy(getChallengeGroup) | 
					
						
							|  |  |  |  |     .flatMap(group$ => { | 
					
						
							|  |  |  |  |       return group$.toArray().map(challenges => ({ | 
					
						
							|  |  |  |  |         [getChallengeGroup(challenges[0])]: challenges | 
					
						
							|  |  |  |  |       })); | 
					
						
							|  |  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2016-02-10 17:28:45 -08:00
										 |  |  |  |     .reduce((output, group) => ({ ...output, ...group}), {}) | 
					
						
							|  |  |  |  |     .map(groups => ({ | 
					
						
							|  |  |  |  |       algorithms: groups.algorithms || [], | 
					
						
							| 
									
										
										
										
											2016-12-03 14:07:54 +00:00
										 |  |  |  |       projects: groups.projects ? groups.projects.reverse() : [], | 
					
						
							|  |  |  |  |       challenges: groups.challenges ? groups.challenges.reverse() : [] | 
					
						
							| 
									
										
										
										
											2016-02-10 17:28:45 -08:00
										 |  |  |  |     })); | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  | module.exports = function(app) { | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   const router = app.loopback.Router(); | 
					
						
							|  |  |  |  |   const api = app.loopback.Router(); | 
					
						
							|  |  |  |  |   const User = app.models.User; | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  |   const Block = app.models.Block; | 
					
						
							| 
									
										
										
										
											2016-12-15 02:54:59 +05:30
										 |  |  |  |   const { Email } = app.models; | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  |   const map$ = cachedMap(Block); | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |   function findUserByUsername$(username, fields) { | 
					
						
							|  |  |  |  |     return observeQuery( | 
					
						
							|  |  |  |  |       User, | 
					
						
							|  |  |  |  |       'findOne', | 
					
						
							|  |  |  |  |       { | 
					
						
							|  |  |  |  |         where: { username }, | 
					
						
							|  |  |  |  |         fields | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     ); | 
					
						
							|  |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-11-14 02:29:55 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |   router.get('/login', function(req, res) { | 
					
						
							|  |  |  |  |     res.redirect(301, '/signin'); | 
					
						
							|  |  |  |  |   }); | 
					
						
							|  |  |  |  |   router.get('/logout', function(req, res) { | 
					
						
							|  |  |  |  |     res.redirect(301, '/signout'); | 
					
						
							|  |  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-09-02 21:40:37 -07:00
										 |  |  |  |   router.get('/signup', getEmailSignup); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |   router.get('/signin', getSignin); | 
					
						
							|  |  |  |  |   router.get('/signout', signout); | 
					
						
							|  |  |  |  |   router.get('/forgot', getForgot); | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   api.post('/forgot', postForgot); | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |   router.get('/reset-password', getReset); | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   api.post('/reset-password', postReset); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |   router.get('/email-signup', getEmailSignup); | 
					
						
							|  |  |  |  |   router.get('/email-signin', getEmailSignin); | 
					
						
							| 
									
										
										
										
											2016-04-18 15:43:35 +00:00
										 |  |  |  |   router.get('/deprecated-signin', getDepSignin); | 
					
						
							| 
									
										
										
										
											2016-05-02 17:20:41 -07:00
										 |  |  |  |   router.get('/update-email', getUpdateEmail); | 
					
						
							| 
									
										
										
										
											2016-09-01 15:40:32 -07:00
										 |  |  |  |   router.get( | 
					
						
							|  |  |  |  |     '/delete-my-account', | 
					
						
							|  |  |  |  |     sendNonUserToMap, | 
					
						
							|  |  |  |  |     showDelete | 
					
						
							|  |  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   api.post( | 
					
						
							| 
									
										
										
										
											2015-08-20 09:40:03 -07:00
										 |  |  |  |     '/account/delete', | 
					
						
							|  |  |  |  |     ifNoUser401, | 
					
						
							|  |  |  |  |     postDeleteAccount | 
					
						
							|  |  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   api.get( | 
					
						
							| 
									
										
										
										
											2015-10-01 20:55:55 -07:00
										 |  |  |  |     '/account', | 
					
						
							|  |  |  |  |     sendNonUserToMap, | 
					
						
							|  |  |  |  |     getAccount | 
					
						
							|  |  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2016-09-20 12:43:34 -05:00
										 |  |  |  |   router.get( | 
					
						
							|  |  |  |  |     '/reset-my-progress', | 
					
						
							|  |  |  |  |     sendNonUserToMap, | 
					
						
							|  |  |  |  |     showResetProgress | 
					
						
							|  |  |  |  |   ); | 
					
						
							|  |  |  |  |   api.post( | 
					
						
							|  |  |  |  |     '/account/resetprogress', | 
					
						
							|  |  |  |  |     ifNoUser401, | 
					
						
							|  |  |  |  |     postResetProgress | 
					
						
							|  |  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 21:26:17 +07:00
										 |  |  |  |   api.get( | 
					
						
							|  |  |  |  |     '/account/unlink/:social', | 
					
						
							|  |  |  |  |     sendNonUserToMap, | 
					
						
							|  |  |  |  |     getUnlinkSocial | 
					
						
							|  |  |  |  |   ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |   // Ensure these are the last routes!
 | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   api.get( | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |     '/:username/front-end-certification', | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |     showCert.bind(null, certTypes.frontEnd) | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |   ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   api.get( | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |     '/:username/data-visualization-certification', | 
					
						
							|  |  |  |  |     showCert.bind(null, certTypes.dataVis) | 
					
						
							| 
									
										
										
										
											2015-12-09 12:28:19 -08:00
										 |  |  |  |   ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   api.get( | 
					
						
							| 
									
										
										
										
											2015-12-09 12:28:19 -08:00
										 |  |  |  |     '/:username/back-end-certification', | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |     showCert.bind(null, certTypes.backEnd) | 
					
						
							|  |  |  |  |   ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   api.get( | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |     '/:username/full-stack-certification', | 
					
						
							|  |  |  |  |     (req, res) => res.redirect(req.url.replace('full-stack', 'back-end')) | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |   ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  |   router.get('/:username', showUserProfile); | 
					
						
							| 
									
										
										
										
											2016-12-15 02:54:59 +05:30
										 |  |  |  |   router.get( | 
					
						
							|  |  |  |  |     '/:username/report-user/', | 
					
						
							|  |  |  |  |     sendNonUserToMap, | 
					
						
							|  |  |  |  |     ifNotVerifiedRedirectToSettings, | 
					
						
							|  |  |  |  |     getReportUserProfile | 
					
						
							|  |  |  |  |   ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   api.post( | 
					
						
							|  |  |  |  |     '/:username/report-user/', | 
					
						
							|  |  |  |  |     ifNoUser401, | 
					
						
							|  |  |  |  |     postReportUserProfile | 
					
						
							|  |  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |   app.use('/:lang', router); | 
					
						
							| 
									
										
										
										
											2016-07-15 14:32:42 -07:00
										 |  |  |  |   app.use(api); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:31:42 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 23:27:18 -07:00
										 |  |  |  |   function getSignin(req, res) { | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     if (req.user) { | 
					
						
							|  |  |  |  |       return res.redirect('/'); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |     return res.render('account/signin', { | 
					
						
							| 
									
										
										
										
											2017-01-13 21:14:43 -05:00
										 |  |  |  |       title: 'Sign in to freeCodeCamp' | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-01-13 04:34:54 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 23:27:18 -07:00
										 |  |  |  |   function signout(req, res) { | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     req.logout(); | 
					
						
							|  |  |  |  |     res.redirect('/'); | 
					
						
							| 
									
										
										
										
											2015-03-28 11:34:12 +09:00
										 |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-01-07 17:45:42 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-22 02:17:59 +05:30
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 15:43:35 +00:00
										 |  |  |  |   function getDepSignin(req, res) { | 
					
						
							|  |  |  |  |     if (req.user) { | 
					
						
							|  |  |  |  |       return res.redirect('/'); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |     return res.render('account/deprecated-signin', { | 
					
						
							| 
									
										
										
										
											2017-01-13 21:14:43 -05:00
										 |  |  |  |       title: 'Sign in to freeCodeCamp using a Deprecated Login' | 
					
						
							| 
									
										
										
										
											2016-04-18 15:43:35 +00:00
										 |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-22 02:17:59 +05:30
										 |  |  |  |   function getUpdateEmail(req, res) { | 
					
						
							|  |  |  |  |     if (!req.user) { | 
					
						
							|  |  |  |  |       return res.redirect('/'); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-03 10:54:56 +05:30
										 |  |  |  |     return res.render('account/update-email', { | 
					
						
							| 
									
										
										
										
											2016-04-22 02:17:59 +05:30
										 |  |  |  |       title: 'Update your Email' | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 23:27:18 -07:00
										 |  |  |  |   function getEmailSignin(req, res) { | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     if (req.user) { | 
					
						
							|  |  |  |  |       return res.redirect('/'); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |     return res.render('account/email-signin', { | 
					
						
							| 
									
										
										
										
											2017-01-13 21:14:43 -05:00
										 |  |  |  |       title: 'Sign in to freeCodeCamp using your Email Address' | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-05-21 11:07:40 -07:00
										 |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-01-07 17:45:42 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 23:27:18 -07:00
										 |  |  |  |   function getEmailSignup(req, res) { | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     if (req.user) { | 
					
						
							|  |  |  |  |       return res.redirect('/'); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |     return res.render('account/email-signup', { | 
					
						
							| 
									
										
										
										
											2017-01-13 21:14:43 -05:00
										 |  |  |  |       title: 'Sign up for freeCodeCamp using your Email Address' | 
					
						
							| 
									
										
										
										
											2015-03-21 13:42:02 +09:00
										 |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-12-23 08:48:28 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 23:27:18 -07:00
										 |  |  |  |   function getAccount(req, res) { | 
					
						
							| 
									
										
										
										
											2015-10-01 20:55:55 -07:00
										 |  |  |  |     const { username } = req.user; | 
					
						
							|  |  |  |  |     return res.redirect('/' + username); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-01-24 04:14:41 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 21:26:17 +07:00
										 |  |  |  |   function getUnlinkSocial(req, res, next) { | 
					
						
							|  |  |  |  |     const { user } = req; | 
					
						
							|  |  |  |  |     const { username } = user; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     let social = req.params.social; | 
					
						
							|  |  |  |  |     if (!social) { | 
					
						
							|  |  |  |  |       req.flash('errors', { | 
					
						
							|  |  |  |  |         msg: 'No social account found' | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |       return res.redirect('/' + username); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     social = social.toLowerCase(); | 
					
						
							|  |  |  |  |     const validSocialAccounts = ['twitter', 'linkedin']; | 
					
						
							|  |  |  |  |     if (validSocialAccounts.indexOf(social) === -1) { | 
					
						
							|  |  |  |  |       req.flash('errors', { | 
					
						
							|  |  |  |  |         msg: 'Invalid social account' | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |       return res.redirect('/' + username); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (!user[social]) { | 
					
						
							|  |  |  |  |       req.flash('errors', { | 
					
						
							|  |  |  |  |         msg: `No ${social} account associated` | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |       return res.redirect('/' + username); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     const query = { | 
					
						
							|  |  |  |  |       where: { | 
					
						
							|  |  |  |  |         provider: social | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return user.identities(query, function(err, identities) { | 
					
						
							|  |  |  |  |       if (err) { return next(err); } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       // assumed user identity is unique by provider
 | 
					
						
							|  |  |  |  |       let identity = identities.shift(); | 
					
						
							|  |  |  |  |       if (!identity) { | 
					
						
							|  |  |  |  |         req.flash('errors', { | 
					
						
							|  |  |  |  |           msg: 'No social account found' | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  |         return res.redirect('/' + username); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       return identity.destroy(function(err) { | 
					
						
							|  |  |  |  |         if (err) { return next(err); } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         const updateData = { [social]: null }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         return user.update$(updateData) | 
					
						
							|  |  |  |  |           .subscribe(() => { | 
					
						
							|  |  |  |  |             debug(`${social} has been unlinked successfully`); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             req.flash('info', { | 
					
						
							|  |  |  |  |               msg: `You\'ve successfully unlinked your ${social}.` | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |             return res.redirect('/' + username); | 
					
						
							|  |  |  |  |           }, next); | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  |   function showUserProfile(req, res, next) { | 
					
						
							| 
									
										
										
										
											2015-08-05 13:01:19 -07:00
										 |  |  |  |     const username = req.params.username.toLowerCase(); | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |     const { user } = req; | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |     // timezone of signed-in account
 | 
					
						
							|  |  |  |  |     // to show all date related components
 | 
					
						
							|  |  |  |  |     // using signed-in account's timezone
 | 
					
						
							|  |  |  |  |     // not of the profile she is viewing
 | 
					
						
							|  |  |  |  |     const timezone = user && user.timezone ? | 
					
						
							|  |  |  |  |       user.timezone : | 
					
						
							|  |  |  |  |       'UTC'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     const query = { | 
					
						
							|  |  |  |  |       where: { username }, | 
					
						
							|  |  |  |  |       include: 'pledge' | 
					
						
							|  |  |  |  |     }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return User.findOne$(query) | 
					
						
							|  |  |  |  |       .filter(userPortfolio => { | 
					
						
							|  |  |  |  |         if (!userPortfolio) { | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |           next(); | 
					
						
							| 
									
										
										
										
											2015-08-05 13:01:19 -07:00
										 |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |         return !!userPortfolio; | 
					
						
							|  |  |  |  |       }) | 
					
						
							|  |  |  |  |       .flatMap(userPortfolio => { | 
					
						
							|  |  |  |  |         userPortfolio = userPortfolio.toJSON(); | 
					
						
							| 
									
										
										
										
											2016-01-19 21:11:20 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |         const timestamps = userPortfolio | 
					
						
							| 
									
										
										
										
											2015-08-07 13:31:48 -07:00
										 |  |  |  |           .progressTimestamps | 
					
						
							|  |  |  |  |           .map(objOrNum => { | 
					
						
							|  |  |  |  |             return typeof objOrNum === 'number' ? | 
					
						
							|  |  |  |  |               objOrNum : | 
					
						
							|  |  |  |  |               objOrNum.timestamp; | 
					
						
							| 
									
										
										
										
											2016-02-09 09:10:18 -08:00
										 |  |  |  |           }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         const uniqueDays = prepUniqueDays(timestamps, timezone); | 
					
						
							| 
									
										
										
										
											2015-08-05 13:01:19 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |         userPortfolio.currentStreak = calcCurrentStreak(uniqueDays, timezone); | 
					
						
							|  |  |  |  |         userPortfolio.longestStreak = calcLongestStreak(uniqueDays, timezone); | 
					
						
							| 
									
										
										
										
											2015-08-05 13:01:19 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |         const calender = userPortfolio | 
					
						
							| 
									
										
										
										
											2015-08-07 13:31:48 -07:00
										 |  |  |  |           .progressTimestamps | 
					
						
							|  |  |  |  |           .map((objOrNum) => { | 
					
						
							|  |  |  |  |             return typeof objOrNum === 'number' ? | 
					
						
							|  |  |  |  |               objOrNum : | 
					
						
							|  |  |  |  |               objOrNum.timestamp; | 
					
						
							|  |  |  |  |           }) | 
					
						
							| 
									
										
										
										
											2015-08-19 13:05:53 -07:00
										 |  |  |  |           .filter((timestamp) => { | 
					
						
							|  |  |  |  |             return !!timestamp; | 
					
						
							|  |  |  |  |           }) | 
					
						
							| 
									
										
										
										
											2015-08-07 13:31:48 -07:00
										 |  |  |  |           .reduce((data, timeStamp) => { | 
					
						
							|  |  |  |  |             data[(timeStamp / 1000)] = 1; | 
					
						
							|  |  |  |  |             return data; | 
					
						
							|  |  |  |  |           }, {}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 19:40:20 +04:00
										 |  |  |  |         if (userPortfolio.isCheater && !user) { | 
					
						
							| 
									
										
										
										
											2016-05-02 11:09:32 +12:00
										 |  |  |  |           req.flash('errors', { | 
					
						
							|  |  |  |  |             msg: dedent`
 | 
					
						
							|  |  |  |  |               Upon review, this account has been flagged for academic | 
					
						
							|  |  |  |  |               dishonesty. If you’re the owner of this account contact | 
					
						
							|  |  |  |  |               team@freecodecamp.com for details. | 
					
						
							|  |  |  |  |             `
 | 
					
						
							|  |  |  |  |           }); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 18:24:43 +01:00
										 |  |  |  |         if (userPortfolio.bio) { | 
					
						
							|  |  |  |  |           userPortfolio.bio = emoji.emojify(userPortfolio.bio); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 16:54:33 -07:00
										 |  |  |  |         return map$.map(({ entities }) => createNameIdMap(entities)) | 
					
						
							|  |  |  |  |           .flatMap(entities => buildDisplayChallenges( | 
					
						
							|  |  |  |  |             entities, | 
					
						
							|  |  |  |  |             userPortfolio.challengeMap, | 
					
						
							|  |  |  |  |             timezone | 
					
						
							|  |  |  |  |           )) | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |           .map(displayChallenges => ({ | 
					
						
							|  |  |  |  |             ...userPortfolio, | 
					
						
							|  |  |  |  |             ...displayChallenges, | 
					
						
							|  |  |  |  |             title: 'Camper ' + userPortfolio.username + '\'s Code Portfolio', | 
					
						
							|  |  |  |  |             calender, | 
					
						
							|  |  |  |  |             github: userPortfolio.githubURL, | 
					
						
							|  |  |  |  |             moment, | 
					
						
							| 
									
										
										
										
											2016-06-17 12:35:10 -07:00
										 |  |  |  |             encodeFcc, | 
					
						
							|  |  |  |  |             supportedLanguages | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |           })); | 
					
						
							|  |  |  |  |       }) | 
					
						
							|  |  |  |  |       .doOnNext(data => { | 
					
						
							|  |  |  |  |         return res.render('account/show', data); | 
					
						
							|  |  |  |  |       }) | 
					
						
							|  |  |  |  |       .subscribe( | 
					
						
							|  |  |  |  |         () => {}, | 
					
						
							|  |  |  |  |         next | 
					
						
							|  |  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-01-28 17:41:13 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |   function showCert(certType, req, res, next) { | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |     const username = req.params.username.toLowerCase(); | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |     const certId = certIds[certType]; | 
					
						
							| 
									
										
										
										
											2016-02-11 13:46:11 -08:00
										 |  |  |  |     return findUserByUsername$(username, { | 
					
						
							| 
									
										
										
										
											2015-10-08 09:02:35 -07:00
										 |  |  |  |           isGithubCool: true, | 
					
						
							| 
									
										
										
										
											2016-01-31 16:35:15 -08:00
										 |  |  |  |           isCheater: true, | 
					
						
							|  |  |  |  |           isLocked: true, | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |           isFrontEndCert: true, | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |           isDataVisCert: true, | 
					
						
							| 
									
										
										
										
											2015-12-09 12:28:19 -08:00
										 |  |  |  |           isBackEndCert: true, | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |           isFullStackCert: true, | 
					
						
							| 
									
										
										
										
											2015-10-08 09:02:35 -07:00
										 |  |  |  |           isHonest: true, | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |           username: true, | 
					
						
							| 
									
										
										
										
											2016-02-09 14:33:25 -08:00
										 |  |  |  |           name: true, | 
					
						
							| 
									
										
										
										
											2016-02-11 13:46:11 -08:00
										 |  |  |  |           challengeMap: true | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |       }) | 
					
						
							|  |  |  |  |       .subscribe( | 
					
						
							| 
									
										
										
										
											2016-02-11 13:46:11 -08:00
										 |  |  |  |         user => { | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |           if (!user) { | 
					
						
							|  |  |  |  |             req.flash('errors', { | 
					
						
							| 
									
										
										
										
											2016-03-14 23:54:59 -07:00
										 |  |  |  |               msg: `We couldn't find a user with the username ${username}` | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |             }); | 
					
						
							|  |  |  |  |             return res.redirect('/'); | 
					
						
							|  |  |  |  |           } | 
					
						
							| 
									
										
										
										
											2015-10-05 22:42:42 -07:00
										 |  |  |  |           if (!user.isGithubCool) { | 
					
						
							|  |  |  |  |             req.flash('errors', { | 
					
						
							|  |  |  |  |               msg: dedent`
 | 
					
						
							|  |  |  |  |                 This user needs to link GitHub with their account | 
					
						
							| 
									
										
										
										
											2016-01-04 02:01:38 -06:00
										 |  |  |  |                 in order for others to be able to view their certificate. | 
					
						
							| 
									
										
										
										
											2015-10-05 22:42:42 -07:00
										 |  |  |  |               `
 | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |             return res.redirect('back'); | 
					
						
							|  |  |  |  |           } | 
					
						
							| 
									
										
										
										
											2016-01-24 15:28:15 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |           if (user.isCheater) { | 
					
						
							|  |  |  |  |             return res.redirect(`/${user.username}`); | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-05 20:00:25 -07:00
										 |  |  |  |           if (user.isLocked) { | 
					
						
							|  |  |  |  |             req.flash('errors', { | 
					
						
							|  |  |  |  |               msg: dedent`
 | 
					
						
							| 
									
										
										
										
											2016-01-10 19:41:50 -06:00
										 |  |  |  |                 ${username} has chosen to make their profile | 
					
						
							|  |  |  |  |                   private. They will need to make their profile public | 
					
						
							| 
									
										
										
										
											2016-01-04 02:01:38 -06:00
										 |  |  |  |                   in order for others to be able to view their certificate. | 
					
						
							| 
									
										
										
										
											2015-10-05 20:00:25 -07:00
										 |  |  |  |               `
 | 
					
						
							|  |  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2015-10-05 22:42:42 -07:00
										 |  |  |  |             return res.redirect('back'); | 
					
						
							| 
									
										
										
										
											2015-10-05 20:00:25 -07:00
										 |  |  |  |           } | 
					
						
							|  |  |  |  |           if (!user.isHonest) { | 
					
						
							|  |  |  |  |             req.flash('errors', { | 
					
						
							|  |  |  |  |               msg: dedent`
 | 
					
						
							| 
									
										
										
										
											2016-01-04 02:01:38 -06:00
										 |  |  |  |                 ${username} has not yet agreed to our Academic Honesty Pledge. | 
					
						
							| 
									
										
										
										
											2015-10-05 20:00:25 -07:00
										 |  |  |  |               `
 | 
					
						
							|  |  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2015-10-05 22:42:42 -07:00
										 |  |  |  |             return res.redirect('back'); | 
					
						
							| 
									
										
										
										
											2015-10-05 20:00:25 -07:00
										 |  |  |  |           } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |           if (user[certType]) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-11 13:46:11 -08:00
										 |  |  |  |             const { challengeMap = {} } = user; | 
					
						
							|  |  |  |  |             const { completedDate = new Date() } = challengeMap[certId] || {}; | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |             return res.render( | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |               certViews[certType], | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |               { | 
					
						
							|  |  |  |  |                 username: user.username, | 
					
						
							| 
									
										
										
										
											2016-05-30 22:06:58 -04:00
										 |  |  |  |                 date: moment(new Date(completedDate)).format('MMMM D, YYYY'), | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |                 name: user.name | 
					
						
							|  |  |  |  |               } | 
					
						
							|  |  |  |  |             ); | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |           req.flash('errors', { | 
					
						
							| 
									
										
										
										
											2016-01-11 15:58:37 -08:00
										 |  |  |  |             msg: `Looks like user ${username} is not ${certText[certType]}` | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |           return res.redirect('back'); | 
					
						
							| 
									
										
										
										
											2015-10-02 11:47:36 -07:00
										 |  |  |  |         }, | 
					
						
							|  |  |  |  |         next | 
					
						
							|  |  |  |  |       ); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-01 15:33:46 -07:00
										 |  |  |  |   function showDelete(req, res) { | 
					
						
							|  |  |  |  |     return res.render('account/delete', { title: 'Delete My Account!' }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 23:27:18 -07:00
										 |  |  |  |   function postDeleteAccount(req, res, next) { | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     User.destroyById(req.user.id, function(err) { | 
					
						
							| 
									
										
										
										
											2015-03-21 13:42:02 +09:00
										 |  |  |  |       if (err) { return next(err); } | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |       req.logout(); | 
					
						
							| 
									
										
										
										
											2016-03-14 23:54:59 -07:00
										 |  |  |  |       req.flash('info', { msg: 'You\'ve successfully deleted your account.' }); | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |       return res.redirect('/'); | 
					
						
							| 
									
										
										
										
											2013-12-13 00:27:51 -05:00
										 |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-07 14:08:56 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 12:43:34 -05:00
										 |  |  |  |   function showResetProgress(req, res) { | 
					
						
							|  |  |  |  |     return res.render('account/reset-progress', { title: 'Reset My Progress!' | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   function postResetProgress(req, res, next) { | 
					
						
							|  |  |  |  |     User.findById(req.user.id, function(err, user) { | 
					
						
							|  |  |  |  |       if (err) { return next(err); } | 
					
						
							|  |  |  |  |       return user.updateAttributes({ | 
					
						
							|  |  |  |  |         progressTimestamps: [{ | 
					
						
							|  |  |  |  |           timestamp: Date.now() | 
					
						
							|  |  |  |  |         }], | 
					
						
							|  |  |  |  |         currentStreak: 0, | 
					
						
							|  |  |  |  |         longestStreak: 0, | 
					
						
							|  |  |  |  |         currentChallengeId: '', | 
					
						
							|  |  |  |  |         isBackEndCert: false, | 
					
						
							|  |  |  |  |         isFullStackCert: false, | 
					
						
							|  |  |  |  |         isDataVisCert: false, | 
					
						
							|  |  |  |  |         isFrontEndCert: false, | 
					
						
							|  |  |  |  |         challengeMap: {}, | 
					
						
							|  |  |  |  |         challegesCompleted: [] | 
					
						
							|  |  |  |  |       }, function(err) { | 
					
						
							|  |  |  |  |         if (err) { return next(err); } | 
					
						
							|  |  |  |  |         req.flash('info', { msg: 'You\'ve successfully reset your progress.' }); | 
					
						
							|  |  |  |  |         return res.redirect('/'); | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |   function getReset(req, res) { | 
					
						
							|  |  |  |  |     if (!req.accessToken) { | 
					
						
							|  |  |  |  |       req.flash('errors', { msg: 'access token invalid' }); | 
					
						
							|  |  |  |  |       return res.render('account/forgot'); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |     return res.render('account/reset', { | 
					
						
							| 
									
										
										
										
											2015-10-31 02:59:09 -07:00
										 |  |  |  |       title: 'Reset your Password', | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |       accessToken: req.accessToken.id | 
					
						
							|  |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-03-21 13:42:02 +09:00
										 |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-07 14:08:56 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 23:27:18 -07:00
										 |  |  |  |   function postReset(req, res, next) { | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |     const errors = req.validationErrors(); | 
					
						
							|  |  |  |  |     const { password } = req.body; | 
					
						
							| 
									
										
										
										
											2015-03-21 13:42:02 +09:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     if (errors) { | 
					
						
							|  |  |  |  |       req.flash('errors', errors); | 
					
						
							|  |  |  |  |       return res.redirect('back'); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |     return User.findById(req.accessToken.userId, function(err, user) { | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |       if (err) { return next(err); } | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |       return user.updateAttribute('password', password, function(err) { | 
					
						
							|  |  |  |  |         if (err) { return next(err); } | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |         debug('password reset processed successfully'); | 
					
						
							| 
									
										
										
										
											2016-03-14 23:54:59 -07:00
										 |  |  |  |         req.flash('info', { msg: 'You\'ve successfully reset your password.' }); | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |         return res.redirect('/'); | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-07 14:08:56 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-22 23:27:18 -07:00
										 |  |  |  |   function getForgot(req, res) { | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     if (req.isAuthenticated()) { | 
					
						
							|  |  |  |  |       return res.redirect('/'); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |     return res.render('account/forgot', { | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |       title: 'Forgot Password' | 
					
						
							|  |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-03-21 13:42:02 +09:00
										 |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-07 14:08:56 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |   function postForgot(req, res) { | 
					
						
							| 
									
										
										
										
											2016-05-12 15:48:34 -07:00
										 |  |  |  |     req.validate('email', 'Email format is not valid').isEmail(); | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |     const errors = req.validationErrors(); | 
					
						
							|  |  |  |  |     const email = req.body.email.toLowerCase(); | 
					
						
							| 
									
										
										
										
											2015-03-21 13:42:02 +09:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     if (errors) { | 
					
						
							|  |  |  |  |       req.flash('errors', errors); | 
					
						
							|  |  |  |  |       return res.redirect('/forgot'); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-03-21 13:42:02 +09:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |     return User.resetPassword({ | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |       email: email | 
					
						
							|  |  |  |  |     }, function(err) { | 
					
						
							|  |  |  |  |       if (err) { | 
					
						
							| 
									
										
										
										
											2015-12-10 09:21:21 -05:00
										 |  |  |  |         req.flash('errors', err.message); | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  |         return res.redirect('/forgot'); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |       } | 
					
						
							| 
									
										
										
										
											2015-08-16 09:54:34 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       req.flash('info', { | 
					
						
							|  |  |  |  |         msg: 'An e-mail has been sent to ' + | 
					
						
							|  |  |  |  |         email + | 
					
						
							|  |  |  |  |         ' with further instructions.' | 
					
						
							|  |  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-03-02 20:54:14 -08:00
										 |  |  |  |       return res.render('account/forgot'); | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-15 02:54:59 +05:30
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   function getReportUserProfile(req, res) { | 
					
						
							|  |  |  |  |     const username = req.params.username.toLowerCase(); | 
					
						
							|  |  |  |  |     return res.render('account/report-profile', { | 
					
						
							|  |  |  |  |       title: 'Report User', | 
					
						
							|  |  |  |  |       username | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   function postReportUserProfile(req, res, next) { | 
					
						
							|  |  |  |  |     const { user } = req; | 
					
						
							|  |  |  |  |     const { username } = req.params; | 
					
						
							|  |  |  |  |     const report = req.sanitize('reportDescription').trimTags(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (!username || !report || report === '') { | 
					
						
							|  |  |  |  |       req.flash('errors', { | 
					
						
							|  |  |  |  |         msg: 'Oops, something is not right please re-check your submission.' | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |       return next(); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return Email.send$({ | 
					
						
							|  |  |  |  |       type: 'email', | 
					
						
							|  |  |  |  |       to: 'Team@FreeCodeCamp.com', | 
					
						
							|  |  |  |  |       cc: user.email, | 
					
						
							|  |  |  |  |       from: 'Team@FreeCodeCamp.com', | 
					
						
							|  |  |  |  |       subject: 'Abuse Report : Reporting ' + username + '\'s profile.', | 
					
						
							|  |  |  |  |       text: dedent(`
 | 
					
						
							|  |  |  |  |         Hello Team,\n | 
					
						
							|  |  |  |  |         This is to report the profile of ${username}.\n | 
					
						
							|  |  |  |  |         Report Details:\n | 
					
						
							|  |  |  |  |         ${report}\n\n | 
					
						
							|  |  |  |  |         Reported by: | 
					
						
							|  |  |  |  |         Username: ${user.username} | 
					
						
							|  |  |  |  |         Name: ${user.name} | 
					
						
							|  |  |  |  |         Email: ${user.email}\n | 
					
						
							|  |  |  |  |         Thanks and regards, | 
					
						
							|  |  |  |  |         ${user.name} | 
					
						
							|  |  |  |  |       `)
 | 
					
						
							|  |  |  |  |     }, err => { | 
					
						
							|  |  |  |  |       if (err) { | 
					
						
							|  |  |  |  |         err.redirectTo = '/' + username; | 
					
						
							|  |  |  |  |         return next(err); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       req.flash('info', { | 
					
						
							|  |  |  |  |         msg: 'A report was sent to the team with ' + user.email + ' in copy.' | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |       return res.redirect('/'); | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-06-03 16:19:23 -07:00
										 |  |  |  | }; |