diff --git a/package.json b/package.json index 8213e9ac72..4863f4d47a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "express-session": "~1.9.2", "express-validator": "~2.8.0", "font-awesome": "~4.3.0", - "forcedomain": "~0.4.0", "forever": "~0.14.1", "frameguard": "^0.2.2", "github-api": "~0.7.0", diff --git a/pm2Start.js b/pm2Start.js new file mode 100644 index 0000000000..052f3bdbfa --- /dev/null +++ b/pm2Start.js @@ -0,0 +1,12 @@ +var pm2 = require('pm2'); +pm2.connect(function() { + pm2.start({ + name: 'server', + script: 'server/server.js', + exec_mode: 'cluster', + instances: '2', + max_memory_restart: '900M' + }, function(err, apps) { + pm2.disconnect(); + }); +}); diff --git a/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js b/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js index f11f202086..53204220f6 100644 --- a/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js +++ b/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js @@ -18,7 +18,7 @@ editor.setSize("100%", "auto"); // Hijack tab key to enter two spaces intead editor.setOption("extraKeys", { Tab: function(cm) { - if (cm.somethingSelected()){ + if (cm.somethingSelected()) { cm.indentSelection("add"); } else { var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); @@ -26,7 +26,7 @@ editor.setOption("extraKeys", { } }, "Shift-Tab": function(cm) { - if (cm.somethingSelected()){ + if (cm.somethingSelected()) { cm.indentSelection("subtract"); } else { var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); @@ -121,7 +121,10 @@ codeOutput.setValue('/**\n' + ' */'); codeOutput.setSize("100%", "100%"); var info = editor.getScrollInfo(); -var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top; +var after = editor.charCoords({ + line: editor.getCursor().line + 1, + ch: 0 +}, "local").top; if (info.top + info.clientHeight < after) editor.scrollTo(null, after - info.clientHeight + 3); @@ -143,8 +146,8 @@ editorValue = (localBonfire.isAlive())? localBonfire.getEditorValue() : allSeeds myCodeMirror.setValue(editorValue); -function doLinting () { - editor.operation(function () { +function doLinting() { + editor.operation(function() { for (var i = 0; i < widgets.length; ++i) editor.removeLineWidget(widgets[i]); widgets.length = 0; @@ -166,14 +169,14 @@ function doLinting () { }); }; -$('#submitButton').on('click', function () { +$('#submitButton').on('click', function() { bonfireExecute(); }); function bonfireExecute() { attempts++; - ga('send', 'event', 'Challenge', 'ran-code', challenge_Name); - userTests= null; + ga('send', 'event', 'Challenge', 'ran-code', challenge_Name); + userTests = null; $('#codeOutput').empty(); var userJavaScript = myCodeMirror.getValue(); userJavaScript = removeComments(userJavaScript); @@ -205,16 +208,23 @@ var scrapeTests = function(userJavaScript) { } var counter = 0; - var regex = new RegExp(/(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/); + var regex = new RegExp( + /(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/ + ); var match = regex.exec(userJavaScript); while (match != null) { var replacement = '//' + counter + testSalt; - userJavaScript = userJavaScript.substring(0, match.index) + replacement + userJavaScript.substring(match.index + match[0].length); + userJavaScript = userJavaScript.substring(0, match.index) + replacement + + userJavaScript.substring(match.index + match[0].length); if (!userTests) { - userTests= []; + userTests = []; } - userTests.push({"text": match[0], "line": counter, "err": null}); + userTests.push({ + "text": match[0], + "line": counter, + "err": null + }); counter++; match = regex.exec(userJavaScript); } @@ -236,17 +246,22 @@ var createTestDisplay = function() { if (pushed) { userTests.pop(); } - for (var i = 0; i < userTests.length;i++) { + for (var i = 0; i < userTests.length; i++) { var test = userTests[i]; var testDoc = document.createElement("div"); if (test.err != null) { console.log('Should be displaying bad tests'); $(testDoc) - .html("
a
element should have the anchor text of \"cat photos\"')",
- "assert($('a').filter(function(index) { return /com/gi.test($('a').attr('href')); }).length > 0, 'You need an a
element that links to http://catphotoapp.com.')",
+ "assert(/http:\\/\\/catphotoapp\\.com/gi.test($('a').attr('href')), 'You need an a
element that links to http://catphotoapp.com.')",
"assert(editor.match(/<\\/a>/g) && editor.match(/<\\/a>/g).length === editor.match(/a
element has a closing tag.')"
],
"challengeSeed": [
diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json
index eeac669f73..9f2b704153 100644
--- a/seed/challenges/bootstrap.json
+++ b/seed/challenges/bootstrap.json
@@ -626,7 +626,7 @@
"The \"row\" class is applied to a div
, and the buttons themselves can be wrapped within it."
],
"tests": [
- "assert($('div.row:has(button)'), 'Your buttons should all be wrapped within the same div
element with the class \"row\".')",
+ "assert($('div.row:has(button)').length > 0, 'Your buttons should all be wrapped within the same div
element with the class \"row\".')",
"assert($('div.col-xs-4:has(button)').length > 2, 'Each of your Bootstrap buttons should be wrapped within its own a div
element with the class \"col-xs-4\".')",
"assert(editor.match(/<\\/button>/g) && editor.match(/
elements has a closing tag.')",
"assert(editor.match(/<\\/div>/g) && editor.match(//g).length === editor.match(/div elements has a closing tag.')"
diff --git a/seed/challenges/ziplines.json b/seed/challenges/ziplines.json
index 3779c06ff7..11b1b15f9f 100644
--- a/seed/challenges/ziplines.json
+++ b/seed/challenges/ziplines.json
@@ -56,7 +56,7 @@
"Hint: Here's an example call to Twitch.tv's JSON API: https://api.twitch.tv/kraken/streams/freecodecamp
.",
"Hint: The relevant documentation about this API call is here: https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel.",
"Hint: Here's an array of the Twitch.tv usernames of people who regularly stream coding: [\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"comster404\",\"brunofin\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]
",
- "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
+ "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
@@ -87,7 +87,7 @@
"Here are the user stories you must enable, and optional bonus user stories:",
"User Story: As a user, I can click a button to show me a new random quote.",
"Bonus User Story: As a user, I can press a button to tweet out a quote.",
- "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
+ "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
@@ -120,7 +120,7 @@
"Bonus User Story: As a user, I can see an icon depending on the temperature..",
"Bonus User Story: As a user, I see a different background image depending on the temperature (e.g. snowy mountain, hot desert).",
"Bonus User Story: As a user, I can push a button to toggle between Fahrenheit and Celsius.",
- "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
+ "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
@@ -154,7 +154,7 @@
"User Story: As a user, I can click a link to go directly to the post's discussion page.",
"Bonus User Story: As a user, I can see how many upvotes each story has.",
"Hint: Here's the Camper News Hot Stories API endpoint: http://www.freecodecamp.com/stories/hotStories
.",
- "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
+ "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
@@ -187,7 +187,7 @@
"Bonus User Story:As a user, I can click a button to see a random Wikipedia entry.",
"Bonus User Story:As a user, when I type in the search box, I can see a dropdown menu with autocomplete options for matching Wikipedia entries.",
"Hint: Here's an entry on using Wikipedia's API: http://www.mediawiki.org/wiki/API:Main_page
.",
- "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
+ "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
],
diff --git a/server/boot/challenge.js b/server/boot/challenge.js
index dfa2f98ef2..bddf9118c4 100644
--- a/server/boot/challenge.js
+++ b/server/boot/challenge.js
@@ -32,50 +32,30 @@
var R = require('ramda'),
utils = require('../utils'),
- userMigration = require('../utils/middleware').userMigration,
- MDNlinks = require('../../seed/bonfireMDNlinks');
+ userMigration = require('../utils/middleware').userMigration;
var challengeMapWithNames = utils.getChallengeMapWithNames();
var challengeMapWithIds = utils.getChallengeMapWithIds();
var challengeMapWithDashedNames = utils.getChallengeMapWithDashedNames();
-
-function getMDNlinks(links) {
- // takes in an array of links, which are strings
- var populatedLinks = [];
-
- // for each key value, push the corresponding link
- // from the MDNlinks object into a new array
- if (links) {
- links.forEach(function (value) {
- populatedLinks.push(MDNlinks[value]);
- });
- }
- return populatedLinks;
-}
+var getMDNLinks = utils.getMDNLinks;
module.exports = function(app) {
var router = app.loopback.Router();
var Challenge = app.models.Challenge;
var User = app.models.User;
- router.get(
- '/challenges/next-challenge',
- userMigration,
- returnNextChallenge
- );
-
- router.get(
- '/challenges/:challengeName',
- userMigration,
- returnIndividualChallenge
- );
-
- router.get('/challenges/', userMigration, returnCurrentChallenge);
router.post('/completed-challenge/', completedChallenge);
router.post('/completed-zipline-or-basejump', completedZiplineOrBasejump);
router.post('/completed-bonfire', completedBonfire);
+ // the follow routes are covered by userMigration
+ router.use(userMigration);
+ router.get('/challenges/next-challenge', returnNextChallenge);
+ router.get('/challenges/:challengeName', returnIndividualChallenge);
+ router.get('/challenges/', returnCurrentChallenge);
+ router.get('/map', challengeMap);
+
app.use(router);
function returnNextChallenge(req, res, next) {
@@ -295,7 +275,7 @@ module.exports = function(app) {
bonfires: challenge,
challengeId: challenge.id,
MDNkeys: challenge.MDNlinks,
- MDNlinks: getMDNlinks(challenge.MDNlinks),
+ MDNlinks: getMDNLinks(challenge.MDNlinks),
challengeType: challenge.challengeType
});
}
@@ -547,4 +527,51 @@ module.exports = function(app) {
});
}
}
+
+ function challengeMap(req, res, next) {
+ var completedList = [];
+
+ if (req.user) {
+ completedList = req.user.completedChallenges;
+ }
+
+ var noDuplicatedChallenges = R.uniq(completedList);
+
+ var completedChallengeList = noDuplicatedChallenges
+ .map(function(challenge) {
+ // backwards compatibility
+ return (challenge.id || challenge._id);
+ });
+ var challengeList = utils.
+ getChallengeMapForDisplay(completedChallengeList);
+
+ Object.keys(challengeList).forEach(function(key) {
+ challengeList[key].completed = challengeList[key]
+ .challenges.filter(function(elem) {
+ // backwards compatibility hack
+ return completedChallengeList.indexOf(elem.id || elem._id) > -1;
+ });
+ });
+
+ function numberWithCommas(x) {
+ return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+ }
+
+ var date1 = new Date('10/15/2014');
+ var date2 = new Date();
+ var timeDiff = Math.abs(date2.getTime() - date1.getTime());
+ var daysRunning = Math.ceil(timeDiff / (1000 * 3600 * 24));
+
+ User.count(function(err, camperCount) {
+ if (err) { return next(err); }
+
+ res.render('challengeMap/show', {
+ daysRunning: daysRunning,
+ camperCount: numberWithCommas(camperCount),
+ title: "A map of all Free Code Camp's Challenges",
+ challengeList: challengeList,
+ completedChallengeList: completedChallengeList
+ });
+ });
+ }
};
diff --git a/server/boot/challengeMap.js b/server/boot/challengeMap.js
deleted file mode 100644
index 3b7adf2489..0000000000
--- a/server/boot/challengeMap.js
+++ /dev/null
@@ -1,66 +0,0 @@
-var R = require('ramda'),
- // debug = require('debug')('freecc:cntr:challengeMap'),
- utils = require('./../utils'),
- middleware = require('../utils/middleware');
-
-
-module.exports = function(app) {
- var User = app.models.User;
- var router = app.loopback.Router();
-
- router.get('/map', middleware.userMigration, challengeMap);
- router.get('/learn-to-code', function(req, res) {
- res.redirect(301, '/map');
- });
- router.get('/about', function(req, res) {
- res.redirect(301, '/map');
- });
-
- app.use(router);
-
- function challengeMap(req, res, next) {
- var completedList = [];
-
- if (req.user) {
- completedList = req.user.completedChallenges;
- }
-
- var noDuplicatedChallenges = R.uniq(completedList);
-
- var completedChallengeList = noDuplicatedChallenges
- .map(function(challenge) {
- return (challenge.id || challenge._id); // backwards compatibility
- });
- var challengeList = utils.
- getChallengeMapForDisplay(completedChallengeList);
-
- Object.keys(challengeList).forEach(function(key) {
- challengeList[key].completed = challengeList[key]
- .challenges.filter(function(elem) {
- return completedChallengeList.indexOf(elem.id || elem._id) > -1;
- //backwards compatibility hack
- });
- });
-
- function numberWithCommas(x) {
- return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
- }
-
- var date1 = new Date('10/15/2014');
- var date2 = new Date();
- var timeDiff = Math.abs(date2.getTime() - date1.getTime());
- var daysRunning = Math.ceil(timeDiff / (1000 * 3600 * 24));
-
- User.count(function(err, camperCount) {
- if (err) { return next(err); }
-
- res.render('challengeMap/show', {
- daysRunning: daysRunning,
- camperCount: numberWithCommas(camperCount),
- title: "A map of all Free Code Camp's Challenges",
- challengeList: challengeList,
- completedChallengeList: completedChallengeList
- });
- });
- }
-};
diff --git a/server/boot/redirects.js b/server/boot/redirects.js
index 8c622cb501..b07ac3b13e 100644
--- a/server/boot/redirects.js
+++ b/server/boot/redirects.js
@@ -18,5 +18,13 @@ module.exports = function(app) {
);
});
+ router.get('/learn-to-code', function(req, res) {
+ res.redirect(301, '/map');
+ });
+
+ router.get('/about', function(req, res) {
+ res.redirect(301, '/map');
+ });
+
app.use(router);
};
diff --git a/server/datasources.local.js b/server/datasources.local.js
index 03a6648e94..276a4e8dee 100644
--- a/server/datasources.local.js
+++ b/server/datasources.local.js
@@ -3,6 +3,7 @@ var secrets = require('../config/secrets');
module.exports = {
db: {
connector: 'mongodb',
+ connectionTimeout: 15000,
url: process.env.MONGOHQ_URL
},
mail: {
diff --git a/server/passport-providers.js b/server/passport-providers.js
index a17d59a068..b60ad8f51e 100644
--- a/server/passport-providers.js
+++ b/server/passport-providers.js
@@ -41,7 +41,7 @@ module.exports = {
},
'google-login': {
provider: 'google',
- authScheme: 'oauth2',
+ authScheme: 'oauth',
module: 'passport-google-oauth2',
clientID: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
@@ -55,7 +55,7 @@ module.exports = {
},
'google-link': {
provider: 'google',
- authScheme: 'oauth2',
+ authScheme: 'oauth',
module: 'passport-google-oauth2',
clientID: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
diff --git a/server/server.js b/server/server.js
index 27ec95b289..4d59ccbe7f 100755
--- a/server/server.js
+++ b/server/server.js
@@ -1,5 +1,6 @@
require('dotenv').load();
-require('pmx').init();
+var pmx = require('pmx');
+pmx.init();
// handle uncaught exceptions. Forever will restart process on shutdown
var R = require('ramda'),
@@ -20,7 +21,6 @@ var R = require('ramda'),
path = require('path'),
expressValidator = require('express-validator'),
lessMiddleware = require('less-middleware'),
- pmx = require('pmx'),
passportProviders = require('./passport-providers'),
/**
@@ -42,12 +42,6 @@ app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
-//if (process.env.NODE_ENV === 'production') {
-// app.use(forceDomain({
-// hostname: 'www.freecodecamp.com'
-// }));
-//}
-
app.use(compress());
app.use(lessMiddleware(path.join(__dirname, '/public')));
app.use(logger('dev'));
@@ -98,6 +92,8 @@ var trusted = [
'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',
@@ -143,7 +139,8 @@ app.use(helmet.csp({
'*.aspnetcdn.com',
'*.d3js.org',
'https://cdn.inspectlet.com/inspectlet.js',
- 'http://cdn.inspectlet.com/inspectlet.js'
+ 'http://cdn.inspectlet.com/inspectlet.js',
+ 'http://www.freecodecamp.org'
].concat(trusted),
'connect-src': [].concat(trusted),
styleSrc: [
@@ -259,6 +256,8 @@ R.keys(passportProviders).map(function(strategy) {
// if (process.env.NODE_ENV === 'development') {
if (true) { // eslint-disable-line
+ // NOTE(berks): adding pmx here for Beta test. Remove for production
+ app.use(pmx.expressErrorHandler());
app.use(errorHandler({
log: true
}));
diff --git a/server/utils/index.js b/server/utils/index.js
index 6b7b342e56..bff016241c 100644
--- a/server/utils/index.js
+++ b/server/utils/index.js
@@ -7,6 +7,7 @@ var path = require('path'),
fs = require('fs'),
+ MDNlinks = require('../../seed/bonfireMDNlinks'),
resources = require('./resources.json'),
nonprofits = require('../../seed/nonprofits.json'),
fieldGuides = require('../../seed/field-guides.json');
@@ -16,7 +17,7 @@ var path = require('path'),
*/
var allFieldGuideIds, allFieldGuideNames, allNonprofitNames,
challengeMap, challengeMapForDisplay, challengeMapWithIds,
- challengeMapWithNames, allChallengeIds, allChallenges,
+ challengeMapWithNames, allChallengeIds,
challengeMapWithDashedNames;
/**
@@ -216,5 +217,18 @@ module.exports = {
}
});
})();
+ },
+
+ getMDNLinks: function(links) {
+ if (!links) {
+ return [];
+ }
+ // takes in an array of links, which are strings
+
+ // for each key value, push the corresponding link
+ // from the MDNlinks object into a new array
+ return links.map(function(value) {
+ return MDNlinks[value];
+ });
}
};
diff --git a/setup.js b/setup.js
deleted file mode 100644
index 652e4ce228..0000000000
--- a/setup.js
+++ /dev/null
@@ -1,749 +0,0 @@
-var fs = require('fs');
-var os = require('os');
-var blessed = require('blessed');
-var multiline = require('multiline');
-
-if (os.platform() === 'win32') {
- console.log('**************************************************************');
- console.log('Hackathon Starter Generator has been disabled on Windows until');
- console.log('https://github.com/chjj/blessed is fixed or until I find a');
- console.log('better CLI module.');
- console.log('**************************************************************');
- process.exit();
-}
-var screen = blessed.screen({
- autoPadding: true
-});
-
-screen.key('q', function() {
- process.exit(0);
-});
-
-var home = blessed.list({
- parent: screen,
- padding: { top: 2 },
- mouse: true,
- keys: true,
- fg: 'white',
- bg: 'blue',
- selectedFg: 'blue',
- selectedBg: 'white',
- items: [
- '» REMOVE AUTHENTICATION PROVIDER',
- '» CHANGE EMAIL SERVICE',
- '» ADD NODE.JS CLUSTER SUPPORT',
- '» EXIT'
- ]
-});
-
-var homeTitle = blessed.text({
- parent: screen,
- align: 'center',
- fg: 'blue',
- bg: 'white',
- content: 'Hackathon Starter (c) 2014'
-});
-
-var footer = blessed.text({
- parent: screen,
- bottom: 0,
- fg: 'white',
- bg: 'blue',
- tags: true,
- content: ' {cyan-fg}{/cyan-fg} moves |' +
- ' {cyan-fg}{/cyan-fg} selects | {cyan-fg}{/cyan-fg} exits'
-});
-
-var inner = blessed.form({
- top: 'center',
- left: 'center',
- mouse: true,
- keys: true,
- width: 33,
- height: 10,
- border: {
- type: 'line',
- fg: 'white',
- bg: 'red'
- },
- fg: 'white',
- bg: 'red'
-});
-
-var success = blessed.box({
- top: 'center',
- left: 'center',
- mouse: true,
- keys: true,
- tags: true,
- width: '50%',
- height: '40%',
- border: {
- type: 'line',
- fg: 'white',
- bg: 'green'
- },
- fg: 'white',
- bg: 'green',
- padding: 1
-});
-
-success.on('keypress', function() {
- home.focus();
- home.remove(success);
-});
-
-var clusterText = blessed.text({
- top: 'top',
- bg: 'red',
- fg: 'white',
- tags: true,
- content: 'Take advantage of multi-core systems' +
- ' using built-in {underline}cluster{/underline} module.'
-});
-
-
-var enable = blessed.button({
- parent: inner,
- bottom: 0,
- mouse: true,
- shrink: true,
- name: 'enable',
- content: ' ENABLE ',
- border: {
- type: 'line',
- fg: 'white',
- bg: 'red'
- },
- style: {
- fg: 'white',
- bg: 'red',
- focus: {
- fg: 'red',
- bg: 'white'
- }
- }
-});
-
-
-var disable = blessed.button({
- parent: inner,
- bottom: 0,
- left: 10,
- mouse: true,
- shrink: true,
- name: 'disable',
- content: ' DISABLE ',
- border: {
- type: 'line',
- fg: 'white',
- bg: 'red'
- },
- style: {
- fg: 'white',
- bg: 'red',
- focus: {
- fg: 'red',
- bg: 'white'
- }
- }
-});
-
-var cancel = blessed.button({
- parent: inner,
- bottom: 0,
- left: 21,
- mouse: true,
- shrink: true,
- name: 'cancel',
- content: ' CANCEL ',
- border: {
- type: 'line',
- fg: 'white',
- bg: 'red'
- },
- style: {
- fg: 'white',
- bg: 'red',
- focus: {
- fg: 'red',
- bg: 'white'
- }
- }
-});
-
-cancel.on('press', function() {
- home.focus();
- home.remove(inner);
- screen.render();
-
-});
-
-var authForm = blessed.form({
- mouse: true,
- keys: true,
- fg: 'white',
- bg: 'blue',
- padding: { left: 1, right: 1 }
-});
-
-authForm.on('submit', function() {
- var passportConfig = fs.readFileSync('config/passport.js')
- .toString().split(os.EOL);
- var loginTemplate = fs.readFileSync('views/account/login.jade')
- .toString().split(os.EOL);
- var profileTemplate = fs.readFileSync('views/account/profile.jade')
- .toString().split(os.EOL);
- var userModel = fs.readFileSync('models/User.js').toString().split(os.EOL);
- var app = fs.readFileSync('app.js').toString().split(os.EOL);
- var secrets = fs.readFileSync('config/secrets.js').toString().split(os.EOL);
-
- var index = passportConfig
- .indexOf('var FacebookStrategy = require("passport-facebook").Strategy;');
- if (facebookCheckbox.checked && index !== -1) {
- passportConfig.splice(index, 1);
- index = passportConfig.indexOf('// Sign in with Facebook.');
- passportConfig.splice(index, 47);
- fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
-
- index = loginTemplate.indexOf(
- ' a.btn.btn-block.btn-facebook.btn-social(href="/auth/facebook")'
- );
- loginTemplate.splice(index, 3);
- fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
-
- index = profileTemplate.indexOf(' if user.facebook');
- profileTemplate.splice(index - 1, 5);
- fs.writeFileSync(
- 'views/account/profile.jade',
- profileTemplate.join(os.EOL)
- );
-
- index = userModel.indexOf(' facebook: String,');
- userModel.splice(index, 1);
- fs.writeFileSync('models/User.js', userModel.join(os.EOL));
-
- index = app.indexOf([
- 'app.get("/auth/facebook"',
- 'passport.authenticate("facebook",',
- ' { scope: ["email", "user_location"] }));'
- ].join(' '));
-
- app.splice(index, 4);
- fs.writeFileSync('app.js', app.join(os.EOL));
- }
-
- index = passportConfig.indexOf(
- "var GitHubStrategy = require('passport-github').Strategy;"
- );
- if (githubCheckbox.checked && index !== -1) {
- console.log(index);
- passportConfig.splice(index, 1);
- index = passportConfig.indexOf('// Sign in with GitHub.');
- passportConfig.splice(index, 48);
- fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
-
- index = loginTemplate.indexOf(
- " a.btn.btn-block.btn-github.btn-social(href='/auth/github')"
- );
- loginTemplate.splice(index, 3);
- fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
-
- index = profileTemplate.indexOf(' if user.github');
- profileTemplate.splice(index - 1, 5);
- fs.writeFileSync(
- 'views/account/profile.jade',
- profileTemplate.join(os.EOL)
- );
-
- index = userModel.indexOf(' github: String,');
- userModel.splice(index, 1);
- fs.writeFileSync('models/User.js', userModel.join(os.EOL));
-
- index = app.indexOf(
- 'app.get("/auth/github", passport.authenticate("github"));'
- );
- app.splice(index, 4);
- fs.writeFileSync('app.js', app.join(os.EOL));
- }
-
- index = passportConfig.indexOf(
- 'var GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;'
- );
- if (googleCheckbox.checked && index !== -1) {
- passportConfig.splice(index, 1);
- index = passportConfig.indexOf('// Sign in with Google.');
- passportConfig.splice(index, 46);
- fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
-
- index = loginTemplate.indexOf(
- " a.btn.btn-block.btn-google-plus.btn-social(href='/auth/google')"
- );
- loginTemplate.splice(index, 3);
- fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
-
- index = profileTemplate.indexOf(' if user.google');
- profileTemplate.splice(index - 1, 5);
- fs.writeFileSync(
- 'views/account/profile.jade',
- profileTemplate.join(os.EOL)
- );
-
- index = userModel.indexOf(' google: String,');
- userModel.splice(index, 1);
- fs.writeFileSync('models/User.js', userModel.join(os.EOL));
-
- index = app.indexOf(
- 'app.get("/auth/google",' +
- ' passport.authenticate("google", { scope: "profile email" }));'
- );
- app.splice(index, 4);
- fs.writeFileSync('app.js', app.join(os.EOL));
- }
-
- index = passportConfig.indexOf(
- 'var TwitterStrategy = require("passport-twitter").Strategy;'
- );
- if (twitterCheckbox.checked && index !== -1) {
- passportConfig.splice(index, 1);
- index = passportConfig.indexOf('// Sign in with Twitter.');
- passportConfig.splice(index, 43);
- fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
-
- index = loginTemplate.indexOf(
- ' a.btn.btn-block.btn-twitter.btn-social(href="/auth/twitter")'
- );
- loginTemplate.splice(index, 3);
- fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
-
- index = profileTemplate.indexOf(' if user.twitter');
- profileTemplate.splice(index - 1, 5);
- fs.writeFileSync(
- 'views/account/profile.jade', profileTemplate.join(os.EOL)
- );
-
- index = userModel.indexOf(' twitter: String,');
- userModel.splice(index, 1);
- fs.writeFileSync('models/User.js', userModel.join(os.EOL));
-
- index = app.indexOf(
- "app.get('/auth/twitter', passport.authenticate('twitter'));"
- );
- app.splice(index, 4);
- fs.writeFileSync('app.js', app.join(os.EOL));
- }
-
- index = passportConfig.indexOf(
- 'var LinkedInStrategy = require("passport-linkedin-oauth2").Strategy;'
- );
- if (linkedinCheckbox.checked && index !== -1) {
- passportConfig.splice(index, 1);
- index = passportConfig.indexOf('// Sign in with LinkedIn.');
- passportConfig.splice(index, 47);
- fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
-
- index = loginTemplate.indexOf(
- ' a.btn.btn-block.btn-linkedin.btn-social(href="/auth/linkedin")'
- );
- loginTemplate.splice(index, 3);
- fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
-
- index = profileTemplate.indexOf(' if user.linkedin');
- profileTemplate.splice(index - 1, 5);
- fs.writeFileSync(
- 'views/account/profile.jade',
- profileTemplate.join(os.EOL)
- );
-
- index = userModel.indexOf(' linkedin: String,');
- userModel.splice(index, 1);
- fs.writeFileSync('models/User.js', userModel.join(os.EOL));
-
- index = app.indexOf(
- 'app.get("/auth/linkedin",',
- ' passport.authenticate("linkedin", { state: "SOME STATE" }));'
- );
- app.splice(index, 4);
- fs.writeFileSync('app.js', app.join(os.EOL));
- }
-
- index = passportConfig.indexOf(
- 'var InstagramStrategy = require("passport-instagram").Strategy;'
- );
- if (instagramCheckbox.checked && index !== -1) {
- passportConfig.splice(index, 1);
- index = passportConfig.indexOf('// Sign in with Instagram.');
- passportConfig.splice(index, 43);
- fs.writeFileSync(
- 'config/passport.js',
- passportConfig.join(os.EOL)
- );
-
- index = loginTemplate.indexOf(
- ' a.btn.btn-block.btn-instagram.btn-social(href="/auth/instagram")'
- );
- loginTemplate.splice(index, 3);
-
- fs.writeFileSync(
- 'views/account/login.jade',
- loginTemplate.join(os.EOL)
- );
-
- index = profileTemplate.indexOf(' if user.instagram');
- profileTemplate.splice(index - 1, 5);
- fs.writeFileSync(
- 'views/account/profile.jade',
- profileTemplate.join(os.EOL)
- );
-
- index = app.indexOf(
- 'app.get("/auth/instagram", passport.authenticate("instagram"));'
- );
- app.splice(index, 4);
- fs.writeFileSync('app.js', app.join(os.EOL));
-
- userModel.splice(index, 1);
- fs.writeFileSync('models/User.js', userModel.join(os.EOL));
- }
-
- home.remove(authForm);
- home.append(success);
- success.setContent(
- 'Selected authentication providers have been removed' +
- 'from passportConfig.js, User.js, server.js, login.jade and profile.jade!'
- );
- success.focus();
- screen.render();
-});
-
-var authText = blessed.text({
- parent: authForm,
- content: 'Selecting a checkbox removes an authentication provider.' +
- ' If authentication provider is already removed, no action will be taken.',
- padding: 1,
- bg: 'magenta',
- fg: 'white'
-});
-
-var facebookCheckbox = blessed.checkbox({
- parent: authForm,
- top: 6,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'Facebook'
-});
-
-var githubCheckbox = blessed.checkbox({
- parent: authForm,
- top: 7,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'GitHub'
-});
-
-var googleCheckbox = blessed.checkbox({
- parent: authForm,
- top: 8,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'Google'
-});
-
-var twitterCheckbox = blessed.checkbox({
- parent: authForm,
- top: 9,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'Twitter'
-});
-
-var linkedinCheckbox = blessed.checkbox({
- parent: authForm,
- top: 10,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'LinkedIn'
-});
-
-var instagramCheckbox = blessed.checkbox({
- parent: authForm,
- top: 11,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'Instagram'
-});
-
-var authSubmit = blessed.button({
- parent: authForm,
- top: 13,
- mouse: true,
- shrink: true,
- name: 'submit',
- content: ' SUBMIT ',
- style: {
- fg: 'blue',
- bg: 'white',
- focus: {
- fg: 'white',
- bg: 'red'
- }
- }
-});
-
-authSubmit.on('press', function() {
- authForm.submit();
-});
-
-var authCancel = blessed.button({
- parent: authForm,
- top: 13,
- left: 9,
- mouse: true,
- shrink: true,
- name: 'cancel',
- content: ' CANCEL ',
- style: {
- fg: 'blue',
- bg: 'white',
- focus: {
- fg: 'white',
- bg: 'red'
- }
- }
-});
-
-authCancel.on('press', function() {
- home.focus();
- home.remove(authForm);
- screen.render();
-});
-
-var emailForm = blessed.form({
- mouse: true,
- keys: true,
- fg: 'white',
- bg: 'blue',
- padding: { left: 1, right: 1 }
-});
-
-emailForm.on('submit', function() {
- var contactCtrl = fs.readFileSync('controllers/contact.js')
- .toString().split(os.EOL);
- var userCtrl = fs.readFileSync('controllers/user.js')
- .toString().split(os.EOL);
- var choice = null;
-
- if (sendgridRadio.checked) {
- choice = 'SendGrid';
- } else if (mailgunRadio.checked) {
- choice = 'Mailgun';
- } else if (mandrillRadio.checked) {
- choice = 'Mandrill';
- }
-
- var index = contactCtrl.indexOf(
- 'var transporter = nodemailer.createTransport({'
- );
- contactCtrl.splice(index + 1, 1, " service: '" + choice + "',");
- contactCtrl.splice(
- index + 3,
- 1,
- ' user: secrets.' + choice.toLowerCase() + '.user,'
- );
- contactCtrl.splice(
- index + 4,
- 1,
- ' pass: secrets.' + choice.toLowerCase() + '.password'
- );
- fs.writeFileSync('controllers/contact.js', contactCtrl.join(os.EOL));
-
- index = userCtrl.indexOf(
- ' var transporter = nodemailer.createTransport({'
- );
- userCtrl.splice(index + 1, 1, " service: '" + choice + "',");
- userCtrl.splice(
- index + 3,
- 1,
- ' user: secrets.' + choice.toLowerCase() + '.user,'
- );
- userCtrl.splice(
- index + 4,
- 1,
- ' pass: secrets.' + choice.toLowerCase() + '.password'
- );
-
- index = userCtrl.indexOf(
- ' var transporter = nodemailer.createTransport({',
- (index + 1)
- );
- userCtrl.splice(
- index + 1,
- 1,
- ' service: "' + choice + '",'
- );
-
- userCtrl.splice(
- index + 3,
- 1,
- ' user: secrets.' + choice.toLowerCase() + '.user,'
- );
- userCtrl.splice(
- index + 4,
- 1,
- ' pass: secrets.' + choice.toLowerCase() + '.password'
- );
- fs.writeFileSync('controllers/user.js', userCtrl.join(os.EOL));
-
- home.remove(emailForm);
- home.append(success);
- success.setContent('Email Service has been switched to ' + choice);
- success.focus();
- screen.render();
-});
-
-var emailText = blessed.text({
- parent: emailForm,
- content: 'Select one of the following email service providers ' +
- 'for {underline}contact form{/underline}' +
- ' and {underline}password reset{/underline}.',
- padding: 1,
- bg: 'red',
- fg: 'white',
- tags: true
-});
-
-var sendgridRadio = blessed.radiobutton({
- parent: emailForm,
- top: 5,
- checked: true,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'SendGrid'
-});
-
-var mailgunRadio = blessed.radiobutton({
- parent: emailForm,
- top: 6,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'Mailgun'
-});
-
-var mandrillRadio = blessed.radiobutton({
- parent: emailForm,
- top: 7,
- mouse: true,
- fg: 'white',
- bg: 'blue',
- content: 'Mandrill'
-});
-
-var emailSubmit = blessed.button({
- parent: emailForm,
- top: 9,
- mouse: true,
- shrink: true,
- name: 'submit',
- content: ' SUBMIT ',
- style: {
- fg: 'blue',
- bg: 'white',
- focus: {
- fg: 'white',
- bg: 'red'
- }
- }
-});
-
-emailSubmit.on('press', function() {
- emailForm.submit();
-});
-
-var emailCancel = blessed.button({
- parent: emailForm,
- top: 9,
- left: 9,
- mouse: true,
- shrink: true,
- name: 'cancel',
- content: ' CANCEL ',
- style: {
- fg: 'blue',
- bg: 'white',
- focus: {
- fg: 'white',
- bg: 'red'
- }
- }
-});
-
-emailCancel.on('press', function() {
- home.focus();
- home.remove(emailForm);
- screen.render();
-
-});
-
-home.on('select', function(child, index) {
- switch (index) {
- case 0:
- home.append(authForm);
- authForm.focus();
- screen.render();
- break;
- case 1:
- home.append(emailForm);
- emailForm.focus();
- break;
- case 2:
- addClusterSupport();
- home.append(success);
- success.setContent([
- 'New file {underline}cluster_app.js{/underline} has been created.',
- 'Your app is now able to use more than 1 CPU by running',
- '{underline}node cluster_app.js{/underline}, which in turn',
- 'spawns multiple instances of {underline}server.js{/underline}'
- ].join(' '));
- success.focus();
- screen.render();
- break;
- default:
- process.exit(0);
- }
-});
-
-screen.render();
-
-
-function addClusterSupport() {
-
- var fileContents = multiline(function() {
-/*
-var os = require('os');
-var cluster = require('cluster');
-
-cluster.setupMaster({
- exec: 'server.js'
-});
-
-cluster.on('exit', function(worker) {
- console.log('worker ' + worker.id + ' died');
- cluster.fork();
-});
-
-for (var i = 0; i < os.cpus().length; i++) {
- cluster.fork();
-}
-*/
- });
-
- fs.writeFileSync('cluster_app.js', fileContents);
-}