diff --git a/app.js b/app.js index ed06fe116d..6b3df71c96 100644 --- a/app.js +++ b/app.js @@ -15,45 +15,47 @@ process.on('uncaughtException', function (err) { }); var express = require('express'), - accepts = require('accepts'), - cookieParser = require('cookie-parser'), - compress = require('compression'), - session = require('express-session'), - logger = require('morgan'), - errorHandler = require('errorhandler'), - methodOverride = require('method-override'), - bodyParser = require('body-parser'), - helmet = require('helmet'), - MongoStore = require('connect-mongo')(session), - flash = require('express-flash'), - path = require('path'), - mongoose = require('mongoose'), - passport = require('passport'), - expressValidator = require('express-validator'), - connectAssets = require('connect-assets'), - request = require('request'), + accepts = require('accepts'), + cookieParser = require('cookie-parser'), + compress = require('compression'), + session = require('express-session'), + logger = require('morgan'), + errorHandler = require('errorhandler'), + methodOverride = require('method-override'), + bodyParser = require('body-parser'), + helmet = require('helmet'), + MongoStore = require('connect-mongo')(session), + flash = require('express-flash'), + path = require('path'), + mongoose = require('mongoose'), + passport = require('passport'), + expressValidator = require('express-validator'), + connectAssets = require('connect-assets'), + request = require('request'), + debug = require('debug')('freecc:app'); - /** - * Controllers (route handlers). - */ - homeController = require('./controllers/home'), - challengesController = require('./controllers/challenges'), - resourcesController = require('./controllers/resources'), - userController = require('./controllers/user'), - contactController = require('./controllers/contact'), - bonfireController = require('./controllers/bonfire'), - coursewareController = require('./controllers/courseware'), - /** - * Stories - */ - storyController = require('./controllers/story'), + /** + * Controllers (route handlers). + */ + homeController = require('./controllers/home'), + challengesController = require('./controllers/challenges'), + resourcesController = require('./controllers/resources'), + userController = require('./controllers/user'), + contactController = require('./controllers/contact'), + bonfireController = require('./controllers/bonfire'), + coursewareController = require('./controllers/courseware'), - /** - * API keys and Passport configuration. - */ - secrets = require('./config/secrets'), - passportConf = require('./config/passport'); + /** + * Stories + */ + storyController = require('./controllers/story'), + + /** + * API keys and Passport configuration. + */ + secrets = require('./config/secrets'), + passportConf = require('./config/passport'); /** * Create Express server. @@ -65,9 +67,9 @@ var app = express(); */ mongoose.connect(secrets.db); mongoose.connection.on('error', function () { - console.error( - 'MongoDB Connection Error. Please make sure that MongoDB is running.' - ); + console.error( + 'MongoDB Connection Error. Please make sure that MongoDB is running.' + ); }); /** @@ -82,32 +84,32 @@ app.use(compress()); var oneYear = 31557600000; app.use(express.static(__dirname + '/public', {maxAge: oneYear})); app.use(connectAssets({ - paths: [ - path.join(__dirname, 'public/css'), - path.join(__dirname, 'public/js') - ], - helperContext: app.locals + paths: [ + path.join(__dirname, 'public/css'), + path.join(__dirname, 'public/js') + ], + helperContext: app.locals })); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.use(expressValidator({ - customValidators: { - matchRegex: function (param, regex) { - return regex.test(param); - } + customValidators: { + matchRegex: function (param, regex) { + return regex.test(param); } + } })); app.use(methodOverride()); app.use(cookieParser()); app.use(session({ - resave: true, - saveUninitialized: true, - secret: secrets.sessionSecret, - store: new MongoStore({ - url: secrets.db, - 'auto_reconnect': true - }) + resave: true, + saveUninitialized: true, + secret: secrets.sessionSecret, + store: new MongoStore({ + url: secrets.db, + 'auto_reconnect': true + }) })); app.use(passport.initialize()); app.use(passport.session()); @@ -118,107 +120,107 @@ app.use(helmet.xssFilter()); app.use(helmet.noSniff()); app.use(helmet.xframe()); app.use(function(req, res, next) { - res.header("Access-Control-Allow-Origin", "*"); - res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); - next(); + res.header("Access-Control-Allow-Origin", "*"); + res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); + next(); }); var trusted = [ - "'self'", - '*.freecodecamp.com', - '*.gstatic.com', - '*.google-analytics.com', - '*.googleapis.com', - '*.google.com', - '*.gstatic.com', - '*.doubleclick.net', - '*.twitter.com', - '*.twitch.tv', - '*.twimg.com', - "'unsafe-eval'", - "'unsafe-inline'", - '*.rafflecopter.com', - '*.bootstrapcdn.com', - '*.cloudflare.com', - 'https://*.cloudflare.com', - 'localhost:3001', - 'ws://localhost:3001/', - 'http://localhost:3001', - 'localhost:3000', - 'ws://localhost:3000/', - 'http://localhost:3000', - '*.ionicframework.com', - 'https://syndication.twitter.com', - '*.youtube.com', - '*.jsdelivr.net', - 'https://*.jsdelivr.net', - '*.togetherjs.com', - 'https://*.togetherjs.com', - 'wss://hub.togetherjs.com', - '*.ytimg.com', - 'wss://fcctogether.herokuapp.com', - '*.bitly.com' + "'self'", + '*.freecodecamp.com', + '*.gstatic.com', + '*.google-analytics.com', + '*.googleapis.com', + '*.google.com', + '*.gstatic.com', + '*.doubleclick.net', + '*.twitter.com', + '*.twitch.tv', + '*.twimg.com', + "'unsafe-eval'", + "'unsafe-inline'", + '*.rafflecopter.com', + '*.bootstrapcdn.com', + '*.cloudflare.com', + 'https://*.cloudflare.com', + 'localhost:3001', + 'ws://localhost:3001/', + 'http://localhost:3001', + 'localhost:3000', + 'ws://localhost:3000/', + 'http://localhost:3000', + '*.ionicframework.com', + 'https://syndication.twitter.com', + '*.youtube.com', + '*.jsdelivr.net', + 'https://*.jsdelivr.net', + '*.togetherjs.com', + 'https://*.togetherjs.com', + 'wss://hub.togetherjs.com', + '*.ytimg.com', + 'wss://fcctogether.herokuapp.com', + '*.bitly.com' ]; app.use(helmet.contentSecurityPolicy({ - defaultSrc: trusted, - scriptSrc: ['*.optimizely.com', '*.aspnetcdn.com'].concat(trusted), - 'connect-src': [ - 'ws://*.rafflecopter.com', - 'wss://*.rafflecopter.com', - 'https://*.rafflecopter.com', - 'ws://www.freecodecamp.com', - 'http://www.freecodecamp.com' - ].concat(trusted), - styleSrc: trusted, - imgSrc: [ - '*.evernote.com', - '*.amazonaws.com', - 'data:', - '*.licdn.com', - '*.gravatar.com', - '*.akamaihd.net', - 'graph.facebook.com', - '*.githubusercontent.com', - '*.googleusercontent.com', - '*' /* allow all input since we have user submitted images for public profile*/ - ].concat(trusted), - fontSrc: ['*.googleapis.com'].concat(trusted), - mediaSrc: [ - '*.amazonaws.com', - '*.twitter.com' - ].concat(trusted), - frameSrc: [ - '*.gitter.im', - '*.gitter.im https:', - '*.vimeo.com', - '*.twitter.com', - '*.rafflecopter.com', - '*.ghbtns.com' - ].concat(trusted), - reportOnly: false, // set to true if you only want to report errors - setAllHeaders: false, // set to true if you want to set all headers - safari5: false // set to true if you want to force buggy CSP in Safari 5 + defaultSrc: trusted, + scriptSrc: ['*.optimizely.com', '*.aspnetcdn.com'].concat(trusted), + 'connect-src': [ + 'ws://*.rafflecopter.com', + 'wss://*.rafflecopter.com', + 'https://*.rafflecopter.com', + 'ws://www.freecodecamp.com', + 'http://www.freecodecamp.com' + ].concat(trusted), + styleSrc: trusted, + imgSrc: [ + '*.evernote.com', + '*.amazonaws.com', + 'data:', + '*.licdn.com', + '*.gravatar.com', + '*.akamaihd.net', + 'graph.facebook.com', + '*.githubusercontent.com', + '*.googleusercontent.com', + '*' /* allow all input since we have user submitted images for public profile*/ + ].concat(trusted), + fontSrc: ['*.googleapis.com'].concat(trusted), + mediaSrc: [ + '*.amazonaws.com', + '*.twitter.com' + ].concat(trusted), + frameSrc: [ + '*.gitter.im', + '*.gitter.im https:', + '*.vimeo.com', + '*.twitter.com', + '*.rafflecopter.com', + '*.ghbtns.com' + ].concat(trusted), + reportOnly: false, // set to true if you only want to report errors + setAllHeaders: false, // set to true if you want to set all headers + safari5: false // set to true if you want to force buggy CSP in Safari 5 })); app.use(function (req, res, next) { - // Make user object available in templates. - res.locals.user = req.user; - next(); + // Make user object available in templates. + res.locals.user = req.user; + next(); }); app.use(function (req, res, next) { - // Remember original destination before login. - var path = req.path.split('/')[1]; - if (/auth|login|logout|signup|fonts|favicon/i.test(path)) { - return next(); - } - req.session.returnTo = req.path; - next(); + // Remember original destination before login. + var path = req.path.split('/')[1]; + if (/auth|login|logout|signup|fonts|favicon/i.test(path)) { + return next(); + } + req.session.returnTo = req.path; + next(); }); app.use( - express.static(path.join(__dirname, 'public'), {maxAge: 31557600000}) + express.static(path.join(__dirname, 'public'), {maxAge: 31557600000}) ); app.use(express.static(__dirname + '/public', { maxAge: 86400000 })); @@ -243,23 +245,23 @@ app.get('/control-shortcuts', resourcesController.controlShortcuts); app.get('/control-shortcuts', resourcesController.deployAWebsite); app.get('/nodeschool-challenges', resourcesController.nodeSchoolChallenges); app.get('/stats', function(req, res) { - res.redirect(301, '/learn-to-code'); + res.redirect(301, '/learn-to-code'); }); app.get('/news', function(req, res) { - res.redirect(301, '/stories/hot'); + res.redirect(301, '/stories/hot'); }); app.get('/learn-to-code', resourcesController.about); app.get('/about', function(req, res) { - res.redirect(301, '/learn-to-code'); + res.redirect(301, '/learn-to-code'); }); app.get('/signin', userController.getSignin); app.get('/login', function(req, res) { - res.redirect(301, '/signin'); + res.redirect(301, '/signin'); }); app.post('/signin', userController.postSignin); app.get('/signout', userController.signout); app.get('/logout', function(req, res) { - res.redirect(301, '/signout'); + res.redirect(301, '/signout'); }); app.get('/forgot', userController.getForgot); app.post('/forgot', userController.postForgot); @@ -283,14 +285,14 @@ app.post( contactController.postDoneWithFirst100Hours ); app.get( - '/nonprofit-project-instructions', - passportConf.isAuthenticated, - resourcesController.nonprofitProjectInstructions + '/nonprofit-project-instructions', + passportConf.isAuthenticated, + resourcesController.nonprofitProjectInstructions ); app.post( - '/update-progress', - passportConf.isAuthenticated, - userController.updateProgress + '/update-progress', + passportConf.isAuthenticated, + userController.updateProgress ); app.get('/api/slack', function(req, res) { @@ -351,98 +353,98 @@ app.get('/api/slack', function(req, res) { * Main routes. */ app.get( - '/stories/hotStories', - storyController.hotJSON + '/stories/hotStories', + storyController.hotJSON ); app.get( - '/stories/recentStories', - storyController.recentJSON + '/stories/recentStories', + storyController.recentJSON ); app.get( - '/stories/', - function(req, res) { - res.redirect(302, '/stories/hot'); - } + '/stories/', + function(req, res) { + res.redirect(302, '/stories/hot'); + } ); app.get( - '/stories/comments/:id', - storyController.comments + '/stories/comments/:id', + storyController.comments ); app.post( - '/stories/comment/', - storyController.commentSubmit + '/stories/comment/', + storyController.commentSubmit ); app.post( - '/stories/comment/:id/comment', - storyController.commentOnCommentSubmit + '/stories/comment/:id/comment', + storyController.commentOnCommentSubmit ); app.get( - '/stories/submit', - storyController.submitNew + '/stories/submit', + storyController.submitNew ); app.get( - '/stories/submit/new-story', - storyController.preSubmit + '/stories/submit/new-story', + storyController.preSubmit ); app.post( - '/stories/preliminary', - storyController.newStory + '/stories/preliminary', + storyController.newStory ); app.post( - '/stories/', - storyController.storySubmission + '/stories/', + storyController.storySubmission ); app.get( - '/stories/hot', - storyController.hot + '/stories/hot', + storyController.hot ); app.get( - '/stories/recent', - storyController.recent + '/stories/recent', + storyController.recent ); app.get( - '/stories/search', - storyController.search + '/stories/search', + storyController.search ); app.post( - '/stories/search', - storyController.getStories + '/stories/search', + storyController.getStories ); app.get( - '/stories/:storyName', - storyController.returnIndividualStory + '/stories/:storyName', + storyController.returnIndividualStory ); app.post( - '/stories/upvote/', - storyController.upvote + '/stories/upvote/', + storyController.upvote ); /** * Challenge related routes */ app.get( - '/challenges/', - challengesController.returnNextChallenge + '/challenges/', + challengesController.returnNextChallenge ); app.get( - '/challenges/:challengeNumber', - challengesController.returnChallenge + '/challenges/:challengeNumber', + challengesController.returnChallenge ); app.all('/account', passportConf.isAuthenticated); @@ -466,11 +468,11 @@ app.post('/bonfire-json-generator', bonfireController.generateChallenge); app.get('/bonfire-challenge-generator', bonfireController.publicGenerator); app.post('/bonfire-challenge-generator', bonfireController.testBonfire) app.get( - '/bonfires/:bonfireName', - bonfireController.returnIndividualBonfire + '/bonfires/:bonfireName', + bonfireController.returnIndividualBonfire ); app.get('/bonfire', function(req, res) { - res.redirect(301, '/playground'); + res.redirect(301, '/playground'); }); app.post('/completed-bonfire/', bonfireController.completedBonfire); @@ -481,8 +483,8 @@ app.post('/completed-bonfire/', bonfireController.completedBonfire); app.get('/coursewares/', coursewareController.returnNextCourseware); app.get( - '/coursewares/:coursewareName', - coursewareController.returnIndividualCourseware + '/coursewares/:coursewareName', + coursewareController.returnIndividualCourseware ); app.post('/completed-courseware/', coursewareController.completedCourseware); @@ -504,20 +506,20 @@ app.get('/sitemap.xml', resourcesController.sitemap); * */ app.post('/completed-challenge', function (req, res, done) { - req.user.challengesHash[parseInt(req.body.challengeNumber)] = - Math.round(+new Date() / 1000); - var timestamp = req.user.challengesHash; - var points = 0; - for (var key in timestamp) { - if (timestamp[key] > 0 && req.body.challengeNumber < 54) { - points += 1; - } + req.user.challengesHash[parseInt(req.body.challengeNumber)] = + Math.round(+new Date() / 1000); + var timestamp = req.user.challengesHash; + var points = 0; + for (var key in timestamp) { + if (timestamp[key] > 0 && req.body.challengeNumber < 54) { + points += 1; } - req.user.points = points; - req.user.save(function(err) { - if (err) { return done(err); } - res.status(200).send({ msg: 'progress saved' }); - }); + } + req.user.points = points; + req.user.save(function(err) { + if (err) { return done(err); } + res.status(200).send({ msg: 'progress saved' }); + }); }); /** @@ -525,60 +527,60 @@ app.post('/completed-challenge', function (req, res, done) { */ var passportOptions = { - successRedirect: '/', - failureRedirect: '/login' + successRedirect: '/', + failureRedirect: '/login' }; app.get('/auth/twitter', passport.authenticate('twitter')); app.get( - '/auth/twitter/callback', - passport.authenticate('twitter', { - successRedirect: '/', - failureRedirect: '/login' - }) + '/auth/twitter/callback', + passport.authenticate('twitter', { + successRedirect: '/', + failureRedirect: '/login' + }) ); app.get( - '/auth/linkedin', - passport.authenticate('linkedin', { - state: 'SOME STATE' - }) + '/auth/linkedin', + passport.authenticate('linkedin', { + state: 'SOME STATE' + }) ); app.get( - '/auth/linkedin/callback', - passport.authenticate('linkedin', passportOptions) + '/auth/linkedin/callback', + passport.authenticate('linkedin', passportOptions) ); app.get( - '/auth/facebook', - passport.authenticate('facebook', {scope: ['email', 'user_location']}) + '/auth/facebook', + passport.authenticate('facebook', {scope: ['email', 'user_location']}) ); app.get( - '/auth/facebook/callback', - passport.authenticate('facebook', passportOptions), function (req, res) { - res.redirect(req.session.returnTo || '/'); - } + '/auth/facebook/callback', + passport.authenticate('facebook', passportOptions), function (req, res) { + res.redirect(req.session.returnTo || '/'); + } ); app.get('/auth/github', passport.authenticate('github')); app.get( - '/auth/github/callback', - passport.authenticate('github', passportOptions), function (req, res) { - res.redirect(req.session.returnTo || '/'); - } + '/auth/github/callback', + passport.authenticate('github', passportOptions), function (req, res) { + res.redirect(req.session.returnTo || '/'); + } ); app.get( - '/auth/google', - passport.authenticate('google', {scope: 'profile email'}) + '/auth/google', + passport.authenticate('google', {scope: 'profile email'}) ); app.get( - '/auth/google/callback', - passport.authenticate('google', passportOptions), function (req, res) { - res.redirect(req.session.returnTo || '/'); - } + '/auth/google/callback', + passport.authenticate('google', passportOptions), function (req, res) { + res.redirect(req.session.returnTo || '/'); + } ); app.get('/induce-vomiting', function(req, res, next) { @@ -587,8 +589,8 @@ app.get('/induce-vomiting', function(req, res, next) { // put this route last app.get( - '/:username', - userController.returnUser + '/:username', + userController.returnUser ); /** @@ -614,15 +616,16 @@ if (process.env.NODE_ENV === 'development') { var accept = accepts(req); var type = accept.type('html', 'json', 'text'); - var message = 'opps! Something went wrong. Please try again later'; + var message = 'oops! Something went wrong. Please try again later.'; + debug('ERROR!!', err); if (type === 'html') { req.flash('errors', { msg: message }); return res.redirect('/'); - // json + // json } else if (type === 'json') { res.setHeader('Content-Type', 'application/json'); return res.send({ message: message }); - // plain text + // plain text } else { res.setHeader('Content-Type', 'text/plain'); return res.send(message); @@ -634,11 +637,11 @@ if (process.env.NODE_ENV === 'development') { * Start Express server. */ app.listen(app.get('port'), function () { - console.log( - 'FreeCodeCamp server listening on port %d in %s mode', - app.get('port'), - app.get('env') - ); + console.log( + 'FreeCodeCamp server listening on port %d in %s mode', + app.get('port'), + app.get('env') + ); }); module.exports = app;