| 
									
										
										
										
											2018-09-14 13:18:31 +01:00
										 |  |  | import debug from 'debug'; | 
					
						
							| 
									
										
										
										
											2018-01-22 17:08:33 -08:00
										 |  |  | import { check } from 'express-validator/check'; | 
					
						
							| 
									
										
										
										
											2018-09-14 13:18:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-25 00:17:40 +01:00
										 |  |  | import { ifNoUser401, createValidatorErrorHandler } from '../utils/middleware'; | 
					
						
							| 
									
										
										
										
											2018-01-29 11:26:24 -08:00
										 |  |  | import { themes } from '../../common/utils/themes.js'; | 
					
						
							| 
									
										
										
										
											2018-01-29 11:34:44 -08:00
										 |  |  | import { alertTypes } from '../../common/utils/flash.js'; | 
					
						
							| 
									
										
										
										
											2016-07-16 10:38:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 13:18:31 +01:00
										 |  |  | const log = debug('fcc:boot:settings'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-16 10:38:06 -07:00
										 |  |  | export default function settingsController(app) { | 
					
						
							|  |  |  |   const api = app.loopback.Router(); | 
					
						
							| 
									
										
										
										
											2018-02-16 23:18:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  |   const updateMyUsername = createUpdateMyUsername(app); | 
					
						
							| 
									
										
										
										
											2018-05-27 17:29:04 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-25 00:17:40 +01:00
										 |  |  |   api.put('/update-privacy-terms', ifNoUser401, updatePrivacyTerms); | 
					
						
							| 
									
										
										
										
											2018-05-27 17:29:04 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:26:24 -08:00
										 |  |  |   api.post( | 
					
						
							| 
									
										
										
										
											2018-05-15 14:56:26 +01:00
										 |  |  |     '/refetch-user-completed-challenges', | 
					
						
							| 
									
										
										
										
											2018-01-29 11:26:24 -08:00
										 |  |  |     ifNoUser401, | 
					
						
							| 
									
										
										
										
											2018-05-15 14:56:26 +01:00
										 |  |  |     refetchCompletedChallenges | 
					
						
							| 
									
										
										
										
											2018-02-16 23:18:53 +00:00
										 |  |  |   ); | 
					
						
							| 
									
										
										
										
											2017-06-17 18:09:43 -04:00
										 |  |  |   api.post( | 
					
						
							| 
									
										
										
										
											2018-02-16 23:18:53 +00:00
										 |  |  |     '/update-my-current-challenge', | 
					
						
							| 
									
										
										
										
											2017-06-17 18:09:43 -04:00
										 |  |  |     ifNoUser401, | 
					
						
							| 
									
										
										
										
											2018-02-16 23:18:53 +00:00
										 |  |  |     updateMyCurrentChallengeValidators, | 
					
						
							|  |  |  |     createValidatorErrorHandler(alertTypes.danger), | 
					
						
							|  |  |  |     updateMyCurrentChallenge | 
					
						
							| 
									
										
										
										
											2017-06-17 18:09:43 -04:00
										 |  |  |   ); | 
					
						
							| 
									
										
										
										
											2018-08-25 00:17:40 +01:00
										 |  |  |   api.post('/update-my-portfolio', ifNoUser401, updateMyPortfolio); | 
					
						
							|  |  |  |   api.post('/update-my-projects', ifNoUser401, updateMyProjects); | 
					
						
							| 
									
										
										
										
											2016-07-16 10:38:06 -07:00
										 |  |  |   api.post( | 
					
						
							| 
									
										
										
										
											2018-02-16 23:18:53 +00:00
										 |  |  |     '/update-my-theme', | 
					
						
							| 
									
										
										
										
											2016-07-16 10:38:06 -07:00
										 |  |  |     ifNoUser401, | 
					
						
							| 
									
										
										
										
											2018-02-16 23:18:53 +00:00
										 |  |  |     updateMyThemeValidators, | 
					
						
							|  |  |  |     createValidatorErrorHandler(alertTypes.danger), | 
					
						
							|  |  |  |     updateMyTheme | 
					
						
							| 
									
										
										
										
											2016-07-16 10:38:06 -07:00
										 |  |  |   ); | 
					
						
							| 
									
										
										
										
											2018-09-18 09:36:20 +01:00
										 |  |  |   api.put('/update-my-about', ifNoUser401, updateMyAbout); | 
					
						
							| 
									
										
										
										
											2018-09-14 14:00:43 +01:00
										 |  |  |   api.put( | 
					
						
							|  |  |  |     '/update-my-email', | 
					
						
							|  |  |  |     ifNoUser401, | 
					
						
							|  |  |  |     updateMyEmailValidators, | 
					
						
							|  |  |  |     createValidatorErrorHandler(alertTypes.danger), | 
					
						
							|  |  |  |     updateMyEmail | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2018-09-18 09:36:20 +01:00
										 |  |  |   api.put('/update-my-profileui', ifNoUser401, updateMyProfileUI); | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  |   api.put('/update-my-username', ifNoUser401, updateMyUsername); | 
					
						
							| 
									
										
										
										
											2018-09-14 14:00:43 +01:00
										 |  |  |   api.put('/update-user-flag', ifNoUser401, updateUserFlag); | 
					
						
							| 
									
										
										
										
											2016-08-05 14:05:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-29 20:52:41 +01:00
										 |  |  |   app.use('/internal', api); | 
					
						
							| 
									
										
										
										
											2016-07-16 10:38:06 -07:00
										 |  |  |   app.use(api); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | const standardErrorMessage = { | 
					
						
							|  |  |  |   type: 'danger', | 
					
						
							|  |  |  |   message: | 
					
						
							|  |  |  |     'Something went wrong updating your account. Please check and try again' | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 13:18:31 +01:00
										 |  |  | const standardSuccessMessage = { | 
					
						
							|  |  |  |   type: 'success', | 
					
						
							|  |  |  |   message: 'We have updated your preferences' | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-18 09:36:20 +01:00
										 |  |  | const createStandardHandler = (req, res, next) => err => { | 
					
						
							|  |  |  |   if (err) { | 
					
						
							|  |  |  |     res.status(500).json(standardErrorMessage); | 
					
						
							|  |  |  |     return next(err); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return res.status(200).json(standardSuccessMessage); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  | function refetchCompletedChallenges(req, res, next) { | 
					
						
							|  |  |  |   const { user } = req; | 
					
						
							|  |  |  |   return user | 
					
						
							|  |  |  |     .requestCompletedChallenges() | 
					
						
							|  |  |  |     .subscribe(completedChallenges => res.json({ completedChallenges }), next); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const updateMyEmailValidators = [ | 
					
						
							|  |  |  |   check('email') | 
					
						
							|  |  |  |     .isEmail() | 
					
						
							|  |  |  |     .withMessage('Email format is invalid.') | 
					
						
							|  |  |  | ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function updateMyEmail(req, res, next) { | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     user, | 
					
						
							|  |  |  |     body: { email } | 
					
						
							|  |  |  |   } = req; | 
					
						
							|  |  |  |   return user | 
					
						
							|  |  |  |     .requestUpdateEmail(email) | 
					
						
							|  |  |  |     .subscribe(message => res.json({ message }), next); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const updateMyCurrentChallengeValidators = [ | 
					
						
							|  |  |  |   check('currentChallengeId') | 
					
						
							|  |  |  |     .isMongoId() | 
					
						
							|  |  |  |     .withMessage('currentChallengeId is not a valid challenge ID') | 
					
						
							|  |  |  | ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function updateMyCurrentChallenge(req, res, next) { | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     user, | 
					
						
							|  |  |  |     body: { currentChallengeId } | 
					
						
							|  |  |  |   } = req; | 
					
						
							| 
									
										
										
										
											2018-11-08 13:43:09 +00:00
										 |  |  |   return user.updateAttribute( | 
					
						
							|  |  |  |     'currentChallengeId', | 
					
						
							|  |  |  |     currentChallengeId, | 
					
						
							|  |  |  |     (err, updatedUser) => { | 
					
						
							|  |  |  |       if (err) { | 
					
						
							|  |  |  |         return next(err); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       const { currentChallengeId } = updatedUser; | 
					
						
							|  |  |  |       return res.status(200).json(currentChallengeId); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const updateMyThemeValidators = [ | 
					
						
							|  |  |  |   check('theme') | 
					
						
							|  |  |  |     .isIn(Object.keys(themes)) | 
					
						
							|  |  |  |     .withMessage('Theme is invalid.') | 
					
						
							|  |  |  | ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function updateMyTheme(req, res, next) { | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     body: { theme } | 
					
						
							|  |  |  |   } = req; | 
					
						
							|  |  |  |   if (req.user.theme === theme) { | 
					
						
							|  |  |  |     return res.sendFlash(alertTypes.info, 'Theme already set'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return req.user | 
					
						
							|  |  |  |     .updateTheme(theme) | 
					
						
							|  |  |  |     .then( | 
					
						
							|  |  |  |       () => res.sendFlash(alertTypes.info, 'Your theme has been updated'), | 
					
						
							|  |  |  |       next | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function updateMyPortfolio(req, res, next) { | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     user, | 
					
						
							|  |  |  |     body: { portfolio } | 
					
						
							|  |  |  |   } = req; | 
					
						
							|  |  |  |   // if we only have one key, it should be the id
 | 
					
						
							|  |  |  |   // user cannot send only one key to this route
 | 
					
						
							|  |  |  |   // other than to remove a portfolio item
 | 
					
						
							|  |  |  |   const requestDelete = Object.keys(portfolio).length === 1; | 
					
						
							|  |  |  |   return user | 
					
						
							|  |  |  |     .updateMyPortfolio(portfolio, requestDelete) | 
					
						
							|  |  |  |     .subscribe(message => res.json({ message }), next); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function updateMyProfileUI(req, res, next) { | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     user, | 
					
						
							|  |  |  |     body: { profileUI } | 
					
						
							|  |  |  |   } = req; | 
					
						
							| 
									
										
										
										
											2018-09-18 09:36:20 +01:00
										 |  |  |   user.updateAttribute( | 
					
						
							|  |  |  |     'profileUI', | 
					
						
							|  |  |  |     profileUI, | 
					
						
							|  |  |  |     createStandardHandler(req, res, next) | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function updateMyProjects(req, res, next) { | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     user, | 
					
						
							|  |  |  |     body: { projects: project } | 
					
						
							|  |  |  |   } = req; | 
					
						
							|  |  |  |   return user | 
					
						
							|  |  |  |     .updateMyProjects(project) | 
					
						
							|  |  |  |     .subscribe(message => res.json({ message }), next); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 13:18:31 +01:00
										 |  |  | function updateMyAbout(req, res, next) { | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     user, | 
					
						
							|  |  |  |     body: { name, location, about, picture } | 
					
						
							|  |  |  |   } = req; | 
					
						
							| 
									
										
										
										
											2018-09-14 14:00:43 +01:00
										 |  |  |   log(name, location, picture, about); | 
					
						
							| 
									
										
										
										
											2018-09-18 09:36:20 +01:00
										 |  |  |   return user.updateAttributes( | 
					
						
							|  |  |  |     { name, location, about, picture }, | 
					
						
							|  |  |  |     createStandardHandler(req, res, next) | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2018-09-14 13:18:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  | function createUpdateMyUsername(app) { | 
					
						
							|  |  |  |   const { User } = app.models; | 
					
						
							|  |  |  |   return async function updateMyUsername(req, res, next) { | 
					
						
							|  |  |  |     const { | 
					
						
							|  |  |  |       user, | 
					
						
							|  |  |  |       body: { username } | 
					
						
							|  |  |  |     } = req; | 
					
						
							|  |  |  |     if (username === user.username) { | 
					
						
							|  |  |  |       return res.json({ | 
					
						
							|  |  |  |         type: 'info', | 
					
						
							|  |  |  |         message: 'Username is already associated with this account' | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const exists = await User.doesExist(username); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (exists) { | 
					
						
							|  |  |  |       return res.json({ | 
					
						
							|  |  |  |         type: 'info', | 
					
						
							|  |  |  |         message: 'Username is already associated with a different account' | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return user.updateAttribute('username', username, err => { | 
					
						
							|  |  |  |       if (err) { | 
					
						
							|  |  |  |         res.status(500).json(standardErrorMessage); | 
					
						
							|  |  |  |         return next(err); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return res.status(200).json({ | 
					
						
							|  |  |  |         type: 'success', | 
					
						
							|  |  |  |         message: `We have updated your username to ${username}` | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 14:00:43 +01:00
										 |  |  | const updatePrivacyTerms = (req, res, next) => { | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  |   const { | 
					
						
							|  |  |  |     user, | 
					
						
							|  |  |  |     body: { quincyEmails } | 
					
						
							|  |  |  |   } = req; | 
					
						
							|  |  |  |   const update = { | 
					
						
							|  |  |  |     acceptedPrivacyTerms: true, | 
					
						
							|  |  |  |     sendQuincyEmail: !!quincyEmails | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   return user.updateAttributes(update, err => { | 
					
						
							|  |  |  |     if (err) { | 
					
						
							| 
									
										
										
										
											2018-09-14 14:00:43 +01:00
										 |  |  |       res.status(500).json(standardErrorMessage); | 
					
						
							|  |  |  |       return next(err); | 
					
						
							| 
									
										
										
										
											2018-09-13 18:28:23 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return res.status(200).json({ | 
					
						
							|  |  |  |       type: 'success', | 
					
						
							|  |  |  |       message: | 
					
						
							|  |  |  |         'We have updated your preferences. ' + | 
					
						
							|  |  |  |         'You can now continue using freeCodeCamp.' | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-09-14 14:00:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | function updateUserFlag(req, res, next) { | 
					
						
							|  |  |  |   const { user, body: update } = req; | 
					
						
							| 
									
										
										
										
											2018-09-18 09:36:20 +01:00
										 |  |  |   user.updateAttributes(update, createStandardHandler(req, res, next)); | 
					
						
							| 
									
										
										
										
											2018-09-14 14:00:43 +01:00
										 |  |  | } |