diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json
index 59c10f984c..ab30786d54 100644
--- a/seed/challenges/basic-javascript.json
+++ b/seed/challenges/basic-javascript.json
@@ -277,7 +277,7 @@
"difficulty": "9.98141",
"description": [
"",
- "In JavaScript whole numbers (called integers) can be really easily to preform mathematical functions",
+ "In JavaScript whole numbers (called integers) can be easily used to preform mathematical functions",
"Let's try a few of the most commonly used ones now",
"We use +
for addition",
"Replace the 0
with correct number to achieve the result in the comment."
@@ -301,7 +301,7 @@
"difficulty": "9.98142",
"description": [
"",
- "In JavaScript whole numbers (called integers) can be really easily to preform mathematical functions",
+ "In JavaScript whole numbers (called integers) can be easily used to preform mathematical functions",
"Let's try a few of the most commonly used ones now",
"We use -
for subtraction",
"Replace the 0
with correct number to achieve the result in the comment."
@@ -325,7 +325,7 @@
"difficulty": "9.98143",
"description": [
"",
- "In JavaScript whole numbers (called integers) can be really easily to preform mathematical functions",
+ "In JavaScript whole numbers (called integers) can be easily used to preform mathematical functions",
"Let's try a few of the most commonly used ones now",
"We use *
for multiplication",
"Replace the 0
with correct number to achieve the result in the comment."
@@ -349,7 +349,7 @@
"difficulty": "9.9814",
"description": [
"",
- "In JavaScript whole numbers (called integers) can be really easily to preform mathematical functions",
+ "In JavaScript whole numbers (called integers) can be easily used to preform mathematical functions",
"Let's try a few of the most commonly used ones now",
"We use /
for division",
"Replace the 0
with correct number to achieve the result in the comment."
diff --git a/server/server.js b/server/server.js
index 3c047934e5..f8f6955e97 100755
--- a/server/server.js
+++ b/server/server.js
@@ -3,11 +3,30 @@ var pmx = require('pmx');
pmx.init();
var assign = require('lodash').assign,
- loopback = require('loopback'),
- boot = require('loopback-boot'),
- expressState = require('express-state'),
- path = require('path'),
- passportProviders = require('./passport-providers');
+ loopback = require('loopback'),
+ boot = require('loopback-boot'),
+ accepts = require('accepts'),
+ cookieParser = require('cookie-parser'),
+ compress = require('compression'),
+ session = require('express-session'),
+ expressState = require('express-state'),
+ 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'),
+
+ passportProviders = require('./passport-providers'),
+ rxMiddleware = require('./utils/rx').rxMiddleware,
+ /**
+ * API keys and Passport configuration.
+ */
+ secrets = require('./../config/secrets');
var generateKey =
require('loopback-component-passport/lib/models/utils').generateKey;
@@ -26,9 +45,147 @@ var passportConfigurator = new PassportConfigurator(app);
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
-app.disable('x-powered-by');
+app.use(compress());
+app.use(lessMiddleware(path.join(__dirname, '/public')));
+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);
+ }
+ }
+}));
+app.use(methodOverride());
+app.use(cookieParser(secrets.cookieSecret));
+app.use(session({
+ resave: true,
+ saveUninitialized: true,
+ secret: secrets.sessionSecret,
+ store: new MongoStore({
+ url: secrets.db,
+ 'autoReconnect': true
+ })
+}));
+
+app.use(flash());
+app.disable('x-powered-by');
// adds passport initialization after session middleware phase is complete
+
+app.use(helmet.xssFilter());
+app.use(helmet.noSniff());
+app.use(helmet.frameguard());
+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();
+});
+
+var trusted = [
+ "'self'",
+ 'blob:',
+ '104.236.218.15',
+ '*.freecodecamp.com',
+ 'http://www.freecodecamp.com',
+ 'https://www.freecodecamp.com',
+ 'https://freecodecamp.com',
+ 'https://freecodecamp.org',
+ '*.freecodecamp.org',
+ // NOTE(berks): add the following as the blob above was not covering www
+ 'http://www.freecodecamp.org',
+ 'ws://freecodecamp.com/',
+ 'ws://www.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'",
+ '*.bootstrapcdn.com',
+ '*.cloudflare.com',
+ 'https://*.cloudflare.com',
+ 'localhost:3001',
+ 'ws://localhost:3001/',
+ 'http://localhost:3001',
+ 'localhost:3000',
+ 'ws://localhost:3000/',
+ 'http://localhost:3000',
+ '127.0.0.1',
+ '127.0.0.1:3000',
+ 'ws://127.0.0.1:3000/',
+ 'http://127.0.0.1:3000',
+ '*.ionicframework.com',
+ 'https://syndication.twitter.com',
+ '*.youtube.com',
+ '*.jsdelivr.net',
+ 'https://*.jsdelivr.net',
+ '*.ytimg.com',
+ '*.bitly.com',
+ 'http://cdn.inspectlet.com/',
+ 'https://cdn.inspeclet.com/',
+ 'wss://inspectletws.herokuapp.com/',
+ 'http://hn.inspectlet.com/',
+ '*.googleapis.com',
+ '*.gstatic.com',
+ 'https://hn.inspectlet.com/',
+ 'http://*.github.com'
+];
+
+app.use(helmet.csp({
+ defaultSrc: trusted,
+ scriptSrc: [
+ '*.optimizely.com',
+ '*.aspnetcdn.com',
+ '*.d3js.org',
+ 'https://cdn.inspectlet.com/inspectlet.js',
+ 'http://cdn.inspectlet.com/inspectlet.js',
+ 'http://beta.freecodecamp.com'
+ ].concat(trusted),
+ 'connect-src': [
+ 'vimeo.com'
+ ].concat(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',
+ '*.gstatic.com'
+ ].concat(trusted),
+ mediaSrc: [
+ '*.amazonaws.com',
+ '*.twitter.com'
+ ].concat(trusted),
+ frameSrc: [
+ '*.gitter.im',
+ '*.gitter.im https:',
+ '*.vimeo.com',
+ '*.twitter.com',
+ '*.ghbtns.com'
+ ].concat(trusted),
+ // set to true if you only want to report errors
+ reportOnly: false,
+ // set to true if you want to set all headers
+ setAllHeaders: false,
+ // set to true if you want to force buggy CSP in Safari 5
+ safari5: false
+}));
+
passportConfigurator.init();
boot(app, {