From f246ef618cd2ed17f97cb475a0a9de0aa7fce002 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sun, 22 Mar 2015 16:57:10 -0700 Subject: [PATCH 1/9] Close web worker after completion closes #257 --- public/js/lib/bonfire/plugin_v0.1.4.js | 1 + 1 file changed, 1 insertion(+) diff --git a/public/js/lib/bonfire/plugin_v0.1.4.js b/public/js/lib/bonfire/plugin_v0.1.4.js index 9aa5978c06..f71c0d34f1 100644 --- a/public/js/lib/bonfire/plugin_v0.1.4.js +++ b/public/js/lib/bonfire/plugin_v0.1.4.js @@ -17,6 +17,7 @@ var run = function(code) { } application.remote.output(result); + self.close(); }; From 940dbea6227b30627f9b224594e17845e7291434 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sun, 22 Mar 2015 22:07:58 -0700 Subject: [PATCH 2/9] Handle err in config/passport --- config/passport.js | 254 +++++++++++++++++++++++++-------------------- 1 file changed, 141 insertions(+), 113 deletions(-) diff --git a/config/passport.js b/config/passport.js index af46f12713..9c3beb04b0 100644 --- a/config/passport.js +++ b/config/passport.js @@ -27,8 +27,10 @@ passport.deserializeUser(function(id, done) { passport.use(new LocalStrategy({ usernameField: 'email' }, function(email, password, done) { User.findOne({ email: email }, function(err, user) { + if (err) { return done(err); } if (!user) return done(null, false, { message: 'Email ' + email + ' not found'}); user.comparePassword(password, function(err, isMatch) { + if (err) { return done(err); } if (isMatch) { return done(null, user); } else { @@ -58,30 +60,35 @@ passport.use(new LocalStrategy({ usernameField: 'email' }, function(email, passw passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, refreshToken, profile, done) { if (req.user) { User.findOne({ facebook: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) { req.flash('errors', { msg: 'There is already a Facebook account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); + done(); } else { User.findById(req.user.id, function(err, user) { + if (err) { return done(err); } user.facebook = profile.id; user.tokens.push({ kind: 'facebook', accessToken: accessToken }); user.profile.name = user.profile.name || profile.displayName; user.profile.gender = user.profile.gender || profile._json.gender; user.profile.picture = user.profile.picture || 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png'; user.save(function(err) { + if (err) { return done(err); } req.flash('info', { msg: 'Facebook account has been linked.' }); - done(err, user); + done(null, user); }); }); } }); } else { User.findOne({ facebook: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) return done(null, existingUser); User.findOne({ email: profile._json.email }, function(err, existingEmailUser) { + if (err) { return done(err); } if (existingEmailUser) { req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Facebook manually from Account Settings.' }); - done(err); + done(); } else { var user = new User(); user.email = profile._json.email; @@ -92,30 +99,31 @@ passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, r user.profile.picture = 'https://graph.facebook.com/' + profile.id + '/picture?type=large'; user.profile.location = (profile._json.location) ? profile._json.location.name : ''; user.save(function(err) { - done(err, user); - }); - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } - }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Welcome to Free Code Camp!', - text: [ - 'Greetings from San Francisco!\n\n', - 'Thank you for joining our community.\n', - 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', - "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", - 'Good luck with the challenges!\n\n', - '- the Volunteer Camp Counselor Team' - ].join('') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return err; } + if (err) { return done(err); } + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Welcome to Free Code Camp!', + text: [ + 'Greetings from San Francisco!\n\n', + 'Thank you for joining our community.\n', + 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', + "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", + 'Good luck with the challenges!\n\n', + '- the Volunteer Camp Counselor Team' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return done(err); } + done(null, user); + }); }); } }); @@ -128,9 +136,10 @@ passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, r passport.use(new GitHubStrategy(secrets.github, function(req, accessToken, refreshToken, profile, done) { if (req.user) { User.findOne({ github: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) { req.flash('errors', { msg: 'There is already a GitHub account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); + done(); } else { User.findById(req.user.id, function(err, user) { user.github = profile.id; @@ -140,19 +149,22 @@ passport.use(new GitHubStrategy(secrets.github, function(req, accessToken, refre user.profile.location = user.profile.location || profile._json.location; user.profile.website = user.profile.website || profile._json.blog; user.save(function(err) { + if (err) { return done(err); } req.flash('info', { msg: 'GitHub account has been linked.' }); - done(err, user); + done(null, user); }); }); } }); } else { User.findOne({ github: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) return done(null, existingUser); User.findOne({ email: profile._json.email }, function(err, existingEmailUser) { + if (err) { return done(err); } if (existingEmailUser) { req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with GitHub manually from Account Settings.' }); - done(err); + done(null); } else { var user = new User(); user.email = profile._json.email; @@ -163,30 +175,31 @@ passport.use(new GitHubStrategy(secrets.github, function(req, accessToken, refre user.profile.location = profile._json.location; user.profile.website = profile._json.blog; user.save(function(err) { - done(err, user); - }); - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } - }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Welcome to Free Code Camp!', - text: [ - 'Greetings from San Francisco!\n\n', - 'Thank you for joining our community.\n', - 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', - "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", - 'Good luck with the challenges!\n\n', - '- the Volunteer Camp Counselor Team' - ].join('') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return err; } + if (err) { return done(err); } + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Welcome to Free Code Camp!', + text: [ + 'Greetings from San Francisco!\n\n', + 'Thank you for joining our community.\n', + 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', + "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", + 'Good luck with the challenges!\n\n', + '- the Volunteer Camp Counselor Team' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return done(err); } + done(null, user); + }); }); } }); @@ -199,9 +212,10 @@ passport.use(new GitHubStrategy(secrets.github, function(req, accessToken, refre passport.use(new TwitterStrategy(secrets.twitter, function(req, accessToken, tokenSecret, profile, done) { if (req.user) { User.findOne({ twitter: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) { req.flash('errors', { msg: 'There is already a Twitter account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); + done(); } else { User.findById(req.user.id, function(err, user) { user.twitter = profile.id; @@ -212,8 +226,9 @@ passport.use(new TwitterStrategy(secrets.twitter, function(req, accessToken, tok user.profile.picture = user.profile.picture || profile._json.profile_image_url_https.replace('_normal', ''); user.profile.twitterHandle = user.profile.twitterHandle || profile.username.toLowerCase(); user.save(function(err) { + if (err) { return done(err); } req.flash('info', { msg: 'Twitter account has been linked.' }); - done(err, user); + done(null, user); }); }); } @@ -221,6 +236,7 @@ passport.use(new TwitterStrategy(secrets.twitter, function(req, accessToken, tok } else { User.findOne({ twitter: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) return done(null, existingUser); var user = new User(); user.profile.username = profile.username.toLowerCase(); @@ -231,7 +247,8 @@ passport.use(new TwitterStrategy(secrets.twitter, function(req, accessToken, tok user.profile.picture = profile._json.profile_image_url_https.replace('_normal', ''); user.profile.twitterHandle = user.profile.twitterHandle || profile.username.toLowerCase(); user.save(function(err) { - done(err, user); + if (err) { return done(err); } + done(null, user); }); }); } @@ -242,30 +259,35 @@ passport.use(new TwitterStrategy(secrets.twitter, function(req, accessToken, tok passport.use(new GoogleStrategy(secrets.google, function(req, accessToken, refreshToken, profile, done) { if (req.user) { User.findOne({ google: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) { req.flash('errors', { msg: 'There is already a Google account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); + done(); } else { User.findById(req.user.id, function(err, user) { + if (err) { return done(err); } user.google = profile.id; user.tokens.push({ kind: 'google', accessToken: accessToken }); user.profile.name = user.profile.name || profile.displayName; user.profile.gender = user.profile.gender || profile._json.gender; user.profile.picture = user.profile.picture || profile._json.picture; user.save(function(err) { + if (err) { return done(err); } req.flash('info', { msg: 'Google account has been linked.' }); - done(err, user); + done(null, user); }); }); } }); } else { User.findOne({ google: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) return done(null, existingUser); User.findOne({ email: profile._json.email }, function(err, existingEmailUser) { + if (err) { return done(err); } if (existingEmailUser) { req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Google manually from Account Settings.' }); - done(err); + done(); } else { var user = new User(); user.email = profile._json.email; @@ -275,30 +297,31 @@ passport.use(new GoogleStrategy(secrets.google, function(req, accessToken, refre user.profile.gender = profile._json.gender; user.profile.picture = profile._json.picture; user.save(function(err) { - done(err, user); - }); - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } - }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Welcome to Free Code Camp!', - text: [ - 'Greetings from San Francisco!\n\n', - 'Thank you for joining our community.\n', - 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', - "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", - 'Good luck with the challenges!\n\n', - '- the Volunteer Camp Counselor Team' - ].join('') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return err; } + if (err) { return done(err); } + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Welcome to Free Code Camp!', + text: [ + 'Greetings from San Francisco!\n\n', + 'Thank you for joining our community.\n', + 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', + "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", + 'Good luck with the challenges!\n\n', + '- the Volunteer Camp Counselor Team' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return err; } + done(null, user); + }); }); } }); @@ -311,11 +334,13 @@ passport.use(new GoogleStrategy(secrets.google, function(req, accessToken, refre passport.use(new LinkedInStrategy(secrets.linkedin, function(req, accessToken, refreshToken, profile, done) { if (req.user) { User.findOne({ linkedin: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) { req.flash('errors', { msg: 'There is already a LinkedIn account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); + done(); } else { User.findById(req.user.id, function(err, user) { + if (err) { return done(err); } user.linkedin = profile.id; user.tokens.push({ kind: 'linkedin', accessToken: accessToken }); user.profile.name = user.profile.name || profile.displayName; @@ -323,8 +348,9 @@ passport.use(new LinkedInStrategy(secrets.linkedin, function(req, accessToken, r user.profile.picture = user.profile.picture || profile._json.pictureUrl; user.profile.website = user.profile.website || profile._json.publicProfileUrl; user.save(function(err) { + if (err) { return done(err); } req.flash('info', { msg: 'LinkedIn account has been linked.' }); - done(err, user); + done(null, user); }); }); } @@ -333,9 +359,10 @@ passport.use(new LinkedInStrategy(secrets.linkedin, function(req, accessToken, r User.findOne({ linkedin: profile.id }, function(err, existingUser) { if (existingUser) return done(null, existingUser); User.findOne({ email: profile._json.emailAddress }, function(err, existingEmailUser) { + if (err) { return done(err); } if (existingEmailUser) { req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with LinkedIn manually from Account Settings.' }); - done(err); + done(); } else { var user = new User(); user.linkedin = profile.id; @@ -346,30 +373,31 @@ passport.use(new LinkedInStrategy(secrets.linkedin, function(req, accessToken, r user.profile.picture = profile._json.pictureUrl; user.profile.website = profile._json.publicProfileUrl; user.save(function(err) { - done(err, user); - }); - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } - }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Welcome to Free Code Camp!', - text: [ - 'Greetings from San Francisco!\n\n', - 'Thank you for joining our community.\n', - 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', - "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", - 'Good luck with the challenges!\n\n', - '- the Volunteer Camp Counselor Team' - ].join('') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return err; } + if (err) { return done(err); } + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Welcome to Free Code Camp!', + text: [ + 'Greetings from San Francisco!\n\n', + 'Thank you for joining our community.\n', + 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', + "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", + 'Good luck with the challenges!\n\n', + '- the Volunteer Camp Counselor Team' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return err; } + done(null, user); + }); }); } }); @@ -380,7 +408,7 @@ passport.use(new LinkedInStrategy(secrets.linkedin, function(req, accessToken, r // Login Required middleware. exports.isAuthenticated = function(req, res, next) { - if (req.isAuthenticated()) return next(); + if (req.isAuthenticated()) { return next(); } res.redirect('/login'); }; @@ -394,4 +422,4 @@ exports.isAuthorized = function(req, res, next) { } else { res.redirect('/auth/' + provider); } -}; \ No newline at end of file +}; From d8bf99708d4288ca994f53c68a64affcbffafb2e Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sun, 22 Mar 2015 22:18:01 -0700 Subject: [PATCH 3/9] Add uncaught exception handler closes #258 --- app.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index fc2a8e81ed..5c5b748823 100644 --- a/app.js +++ b/app.js @@ -2,9 +2,17 @@ if (process.env.NODE_ENV !== 'development') { require('newrelic'); } require('dotenv').load(); -/** - * Module dependencies. - */ +// 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); + /* eslint-disable no-process-exit */ + process.exit(1); + /* eslint-enable no-process-exit */ +}); var express = require('express'), cookieParser = require('cookie-parser'), From 89ee552a12e42a072bc125cec2ec77e7099dc353 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sun, 22 Mar 2015 22:22:52 -0700 Subject: [PATCH 4/9] start adding error handling to passport --- config/passport.js | 53 +++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/config/passport.js b/config/passport.js index af46f12713..1961f88cca 100644 --- a/config/passport.js +++ b/config/passport.js @@ -29,6 +29,7 @@ passport.use(new LocalStrategy({ usernameField: 'email' }, function(email, passw User.findOne({ email: email }, function(err, user) { if (!user) return done(null, false, { message: 'Email ' + email + ' not found'}); user.comparePassword(password, function(err, isMatch) { + if (err) { return done(err); } if (isMatch) { return done(null, user); } else { @@ -58,6 +59,7 @@ passport.use(new LocalStrategy({ usernameField: 'email' }, function(email, passw passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, refreshToken, profile, done) { if (req.user) { User.findOne({ facebook: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) { req.flash('errors', { msg: 'There is already a Facebook account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); done(err); @@ -77,8 +79,10 @@ passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, r }); } else { User.findOne({ facebook: profile.id }, function(err, existingUser) { + if (err) { return done(err); } if (existingUser) return done(null, existingUser); User.findOne({ email: profile._json.email }, function(err, existingEmailUser) { + if (err) { return done(err); } if (existingEmailUser) { req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Facebook manually from Account Settings.' }); done(err); @@ -92,30 +96,31 @@ passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, r user.profile.picture = 'https://graph.facebook.com/' + profile.id + '/picture?type=large'; user.profile.location = (profile._json.location) ? profile._json.location.name : ''; user.save(function(err) { - done(err, user); - }); - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } - }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Welcome to Free Code Camp!', - text: [ - 'Greetings from San Francisco!\n\n', - 'Thank you for joining our community.\n', - 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', - "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", - 'Good luck with the challenges!\n\n', - '- the Volunteer Camp Counselor Team' - ].join('') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return err; } + if (err) { return done(err); } + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Welcome to Free Code Camp!', + text: [ + 'Greetings from San Francisco!\n\n', + 'Thank you for joining our community.\n', + 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', + "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", + 'Good luck with the challenges!\n\n', + '- the Volunteer Camp Counselor Team' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return done(err); } + done(null, user); + }); }); } }); From 6c929b83757ebc2f13e0360ff20bb51693b5ffb6 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sun, 22 Mar 2015 22:23:46 -0700 Subject: [PATCH 5/9] Revert "start adding error handling to passport" This reverts commit 89ee552a12e42a072bc125cec2ec77e7099dc353. --- config/passport.js | 53 +++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/config/passport.js b/config/passport.js index 9c3beb04b0..970753ce21 100644 --- a/config/passport.js +++ b/config/passport.js @@ -30,7 +30,6 @@ passport.use(new LocalStrategy({ usernameField: 'email' }, function(email, passw if (err) { return done(err); } if (!user) return done(null, false, { message: 'Email ' + email + ' not found'}); user.comparePassword(password, function(err, isMatch) { - if (err) { return done(err); } if (isMatch) { return done(null, user); } else { @@ -60,7 +59,6 @@ passport.use(new LocalStrategy({ usernameField: 'email' }, function(email, passw passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, refreshToken, profile, done) { if (req.user) { User.findOne({ facebook: profile.id }, function(err, existingUser) { - if (err) { return done(err); } if (existingUser) { req.flash('errors', { msg: 'There is already a Facebook account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); done(); @@ -82,10 +80,8 @@ passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, r }); } else { User.findOne({ facebook: profile.id }, function(err, existingUser) { - if (err) { return done(err); } if (existingUser) return done(null, existingUser); User.findOne({ email: profile._json.email }, function(err, existingEmailUser) { - if (err) { return done(err); } if (existingEmailUser) { req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Facebook manually from Account Settings.' }); done(); @@ -99,31 +95,30 @@ passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, r user.profile.picture = 'https://graph.facebook.com/' + profile.id + '/picture?type=large'; user.profile.location = (profile._json.location) ? profile._json.location.name : ''; user.save(function(err) { - if (err) { return done(err); } - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } - }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Welcome to Free Code Camp!', - text: [ - 'Greetings from San Francisco!\n\n', - 'Thank you for joining our community.\n', - 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', - "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", - 'Good luck with the challenges!\n\n', - '- the Volunteer Camp Counselor Team' - ].join('') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return done(err); } - done(null, user); - }); + done(err, user); + }); + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Welcome to Free Code Camp!', + text: [ + 'Greetings from San Francisco!\n\n', + 'Thank you for joining our community.\n', + 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', + "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", + 'Good luck with the challenges!\n\n', + '- the Volunteer Camp Counselor Team' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return err; } }); } }); From 5bfd8a8d5485c7bf5cdbf2e7b74584e624e6054d Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Mon, 23 Mar 2015 17:17:39 -0700 Subject: [PATCH 6/9] Handle user save err and respond to end route handler closes #260 --- app.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 5c5b748823..55850d9ab7 100644 --- a/app.js +++ b/app.js @@ -446,7 +446,7 @@ app.get('/sitemap.xml', resourcesController.sitemap); * and updates user.challengesHash & user.challengesCompleted * */ -app.post('/completed-challenge', function (req, res) { +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; @@ -457,7 +457,10 @@ app.post('/completed-challenge', function (req, res) { } } req.user.points = points; - req.user.save(); + req.user.save(function(err) { + if (err) { return done(err); } + res.status(200).send({ msg: 'progress saved' }); + }); }); /** From a6ce7008317d06e032339db3b0dc5254115a10d4 Mon Sep 17 00:00:00 2001 From: Julie Myers Date: Tue, 24 Mar 2015 04:26:39 -0600 Subject: [PATCH 7/9] Add chai-jquery to package.json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 732eb86787..dadcd03961 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "async": "^0.9.0", "bcrypt-nodejs": "^0.0.3", "body-parser": "^1.9.3", + "chai-jquery": "^2.0.0", "cheerio": "^0.18.0", "clockwork": "^0.1.1", "compression": "^1.2.1", From 2b0cc9175496ff90b94ef2dfd5e082720efce344 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Tue, 24 Mar 2015 08:03:59 -0700 Subject: [PATCH 8/9] Add production error handler --- app.js | 44 +++++++++++++++++++++++++++++++++++++++++--- package.json | 1 + 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 55850d9ab7..ecbdc18fd5 100644 --- a/app.js +++ b/app.js @@ -15,6 +15,7 @@ process.on('uncaughtException', function (err) { }); var express = require('express'), + accepts = require('accepts'), cookieParser = require('cookie-parser'), compress = require('compression'), session = require('express-session'), @@ -524,17 +525,54 @@ app.get( } ); -//put this route last +app.get('/induce-vomiting', function(req, res, next) { + next(new Error('vomiting induced')); +}); + +// put this route last app.get( '/:username', userController.returnUser ); - /** * 500 Error Handler. */ -app.use(errorHandler()); +if (process.env.NODE_ENV === 'development') { + app.use(errorHandler({ log: true })); +} else { + // error handling in production + app.use(function(err, req, res, next) { + + // respect err.status + if (err.status) { + res.statusCode = err.status; + } + + // default status code to 500 + if (res.statusCode < 400) { + res.statusCode = 500; + } + + // parse res type + var accept = accepts(req); + var type = accept.type('html', 'json', 'text'); + + var message = 'opps! Something went wrong. Please try again later'; + if (type === 'html') { + req.flash('errors', { msg: message }); + return res.redirect('/'); + // json + } else if (type === 'json') { + res.setHeader('Content-Type', 'application/json'); + return res.send({ message: message }); + // plain text + } else { + res.setHeader('Content-Type', 'text/plain'); + return res.send(message); + } + }); +} /** * Start Express server. diff --git a/package.json b/package.json index dadcd03961..ffe8c6281b 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "postinstall": "node seed_data/seed.js" }, "dependencies": { + "accepts": "^1.2.5", "async": "^0.9.0", "bcrypt-nodejs": "^0.0.3", "body-parser": "^1.9.3", From 482cc3fa7b477800353448f4f54c9edcd3ee0027 Mon Sep 17 00:00:00 2001 From: Geoff Storbeck Date: Tue, 24 Mar 2015 15:58:17 -0400 Subject: [PATCH 9/9] fixed typo for issue #266 --- seed_data/bonfires.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed_data/bonfires.json b/seed_data/bonfires.json index c298c97db7..a686f7e7f7 100644 --- a/seed_data/bonfires.json +++ b/seed_data/bonfires.json @@ -176,7 +176,7 @@ "tests": [ "assert.deepEqual(chunk(['a', 'b', 'c', 'd'], 2), [['a', 'b'], ['c', 'd']], 'should return chunked arrays');", "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'should return chunked arrays');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'should return cthe last chunk as remaining elements');" + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'should return the last chunk as remaining elements');" ] }, {