diff --git a/package.json b/package.json index 6f0af36b39..97277d8279 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "passport-local": "^1.0.0", "passport-oauth": "^1.0.0", "passport-twitter": "^1.0.3", + "pmx": "^0.3.16", "ramda": "~0.10.0", "request": "~2.53.0", "rx": "^2.5.3", diff --git a/public/js/lib/jailed/_frame.js b/public/js/lib/jailed/_frame.js index 34046b89de..fa310643fd 100644 --- a/public/js/lib/jailed/_frame.js +++ b/public/js/lib/jailed/_frame.js @@ -12,7 +12,7 @@ var __jailed__path__ = scripts[scripts.length-1].src .split('?')[0] .split('/') .slice(0, -1) - .join('/')+'/'; + .join('/') + '/'; // creating worker as a blob enables import of local files var blobCode = [ diff --git a/server/server.js b/server/server.js index 015d6c5e55..cc69e11ae3 100755 --- a/server/server.js +++ b/server/server.js @@ -1,39 +1,34 @@ require('dotenv').load(); +require('pmx').init(); // handle uncaught exceptions. Forever will restart process on shutdown -process.on('uncaughtException', function (err) { - console.error( - (new Date()).toUTCString() + ' uncaughtException:', - err.message - ); - console.error(err.stack); - process.exit(1); // eslint-disable-line -}); -var R = require('ramda'), - assign = require('lodash').assign, - loopback = require('loopback'), - boot = require('loopback-boot'), - 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'), - expressValidator = require('express-validator'), - forceDomain = require('forcedomain'), - lessMiddleware = require('less-middleware'), +var https = require('https'), + sslConfig = require('./ssl-config'), + R = require('ramda'), + assign = require('lodash').assign, + loopback = require('loopback'), + boot = require('loopback-boot'), + 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'), + expressValidator = require('express-validator'), + lessMiddleware = require('less-middleware'), + pmx = require('pmx'), - passportProviders = require('./passport-providers'), - /** - * API keys and Passport configuration. - */ - secrets = require('./../config/secrets'); + passportProviders = require('./passport-providers'), + /** + * API keys and Passport configuration. + */ + secrets = require('./../config/secrets'); var generateKey = require('loopback-component-passport/lib/models/utils').generateKey; @@ -99,6 +94,10 @@ var trusted = [ '104.236.218.15', '*.freecodecamp.com', 'http://www.freecodecamp.com', + 'https://www.freecodecamp.com', + 'https://freecodecamp.com', + 'https://freecodecamp.org', + '*.freecodecamp.org', 'ws://freecodecamp.com/', 'ws://www.freecodecamp.com/', '*.gstatic.com', @@ -129,8 +128,12 @@ var trusted = [ '*.ytimg.com', '*.bitly.com', 'http://cdn.inspectlet.com/', + 'https://cdn.inspeclet.com/', 'wss://inspectletws.herokuapp.com/', - 'http://hn.inspectlet.com/' + 'http://hn.inspectlet.com/', + '*.googleapis.com', + '*.gstatic.com', + 'https://hn.inspectlet.com/' ]; app.use(helmet.csp({ @@ -138,22 +141,29 @@ app.use(helmet.csp({ scriptSrc: [ '*.optimizely.com', '*.aspnetcdn.com', - '*.d3js.org' + '*.d3js.org', + 'https://cdn.inspectlet.com/inspectlet.js', + 'http://cdn.inspectlet.com/inspectlet.js' ].concat(trusted), 'connect-src': [ ].concat(trusted), - styleSrc: trusted, + styleSrc: [ + '*.googleapis.com', + '*.gstatic.com' + ].concat(trusted), imgSrc: [ /* allow all input since we have user submitted images for public profile*/ '*' ].concat(trusted), - fontSrc: ['*.googleapis.com'].concat(trusted), + fontSrc: [ + '*.googleapis.com', + '*.gstatic.com' + ].concat(trusted), mediaSrc: [ '*.amazonaws.com', '*.twitter.com' ].concat(trusted), frameSrc: [ - '*.gitter.im', '*.gitter.im https:', '*.vimeo.com', @@ -210,8 +220,8 @@ var passportOptions = { // NOTE(berks): get email or set to null. // MongoDB indexs email but can be sparse(blank) var email = emails && emails[0] && emails[0].value ? - emails[0].value : - null; + emails[0].value : + null; var username = (profile.username || profile.id); username = typeof username === 'string' ? username.toLowerCase() : username; @@ -244,9 +254,11 @@ R.keys(passportProviders).map(function(strategy) { /** * 500 Error Handler. */ + if (process.env.NODE_ENV === 'development') { app.use(errorHandler({ log: true })); } else { + app.use(pmx.expressErrorHandler()); // error handling in production disabling eslint due to express parity rules // for error handlers app.use(function(err, req, res, next) { // eslint-disable-line @@ -285,7 +297,23 @@ if (process.env.NODE_ENV === 'development') { * Start Express server. */ -app.start = function() { +var options = { + key: sslConfig.privateKey, + cert: sslConfig.certificate +}; + +if (process.env.NODE_ENV === 'production') { + var server = https.createServer(options, app); + console.log('https://' + process.env.HOST + ':' + process.env.PORT); + server.listen(app.get('port'), function () { + console.log( + 'FreeCodeCamp server listening on port %d in %s mode', + app.get('port'), + app.get('env') + ); + app.emit('started', 'https://' + process.env.HOST + ':' + app.get('port')); + }); +} else { app.listen(app.get('port'), function () { console.log( 'FreeCodeCamp server listening on port %d in %s mode', @@ -293,11 +321,9 @@ app.start = function() { app.get('env') ); }); -}; - -// start the server if `$ node server.js` -if (require.main === module) { - app.start(); } +// start the server if `$ node server.js` + + module.exports = app; diff --git a/server/ssl-config.js b/server/ssl-config.js new file mode 100644 index 0000000000..6cbf418971 --- /dev/null +++ b/server/ssl-config.js @@ -0,0 +1,16 @@ +/** + * Created by nathanleniz on 6/16/15. + */ + +var path = require('path'); +var fs = require('fs'); + +if (process.env.NODE_ENV === 'production') { + exports.privateKey = + fs.readFileSync(path.join(__dirname, + '../../private/privatekey.pem')); + exports.certificate = + fs.readFileSync(path.join(__dirname, + '../../private/certificate.pem')); + +} diff --git a/server/views/coursewares/showBonfire.jade b/server/views/coursewares/showBonfire.jade index 005ed1f1b7..d18abe290e 100644 --- a/server/views/coursewares/showBonfire.jade +++ b/server/views/coursewares/showBonfire.jade @@ -11,7 +11,7 @@ block content link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') - link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") + link(rel="stylesheet", href="//fonts.googleapis.com/css?family=Ubuntu+Mono") script(type='text/javascript', src='/js/lib/codemirror/mode/javascript/javascript.js') script(type='text/javascript', src='/js/lib/jailed/jailed.js') script(type='text/javascript', src='/js/lib/coursewares/sandbox.js') diff --git a/server/views/coursewares/showJS.jade b/server/views/coursewares/showJS.jade index 25bb25cd3f..58737351ac 100644 --- a/server/views/coursewares/showJS.jade +++ b/server/views/coursewares/showJS.jade @@ -10,7 +10,7 @@ block content link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') - link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") + link(rel="stylesheet", href="//fonts.googleapis.com/css?family=Ubuntu+Mono") script(src='/js/lib/codemirror/mode/javascript/javascript.js') script(src='/js/lib/jailed/jailed.js') script(src='/js/lib/coursewares/sandbox.js') diff --git a/server/views/partials/universal-head.jade b/server/views/partials/universal-head.jade index 205a27e0ce..47bc657df6 100644 --- a/server/views/partials/universal-head.jade +++ b/server/views/partials/universal-head.jade @@ -38,7 +38,7 @@ script(src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js") script(src="/bower_components/ramda/dist/ramda.min.js") -link(rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Lato:400|Inconsolata") +link(rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Lato:400|Inconsolata") link(rel="stylesheet" type="text/css" href="/bower_components/cal-heatmap/cal-heatmap.css") @@ -70,7 +70,7 @@ script#inspectletjs(type='text/javascript'). insp.type = 'text/javascript'; insp.async = true; insp.id = "inspsync"; - insp.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://cdn.inspectlet.com/inspectlet.js'; + insp.src = '//cdn.inspectlet.com/inspectlet.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(insp, x); }