From 996c3e7816b934f13a1a876fa236d89bba4b4110 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 10 Jun 2015 15:12:48 -0700 Subject: [PATCH 1/7] fix make email optional --- package.json | 2 +- server/boot/a-extendUser.js | 5 +++++ server/boot/user.js | 6 ------ server/server.js | 9 +++++++-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index d9fd32ff7e..acbc84c80d 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "lodash": "^3.9.3", "loopback": "^2.18.0", "loopback-boot": "^2.8.0", - "loopback-component-passport": "^1.3.1", + "loopback-component-passport": "git://github.com/FreeCodeCamp/loopback-component-passport.git#feature/emailOptional", "loopback-connector-mongodb": "^1.10.0", "lusca": "~1.0.2", "method-override": "~2.3.0", diff --git a/server/boot/a-extendUser.js b/server/boot/a-extendUser.js index a719949eda..f5cb84cd52 100644 --- a/server/boot/a-extendUser.js +++ b/server/boot/a-extendUser.js @@ -2,6 +2,11 @@ var debug = require('debug')('freecc:extendUser'); module.exports = function(app) { var User = app.models.User; + // NOTE(berks): user email validation currently not needed but build in. This + // work around should let us sneak by + // see: + // https://github.com/strongloop/loopback/issues/1137#issuecomment-109200135 + delete User.validations.email; debug('setting up user hooks'); // send verification email to new camper User.afterRemote('create', function(ctx, user, next) { diff --git a/server/boot/user.js b/server/boot/user.js index 1f7c74a7c5..5f57748f36 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -9,12 +9,6 @@ var _ = require('lodash'), secrets = require('../../config/secrets'); module.exports = function(app) { - // NOTE(berks): user email validation currently not needed but build in. This - // work around should let us sneak by - // see: - // https://github.com/strongloop/loopback/issues/1137#issuecomment-109200135 - delete app.models.User.validations.email; - var router = app.loopback.Router(); var User = app.models.User; var Story = app.models.Story; diff --git a/server/server.js b/server/server.js index 714e5940cc..bc252012af 100755 --- a/server/server.js +++ b/server/server.js @@ -10,6 +10,7 @@ process.on('uncaughtException', function (err) { }); var R = require('ramda'), + assign = require('lodash').assign, loopback = require('loopback'), boot = require('loopback-boot'), accepts = require('accepts'), @@ -202,6 +203,7 @@ passportConfigurator.setupModels({ }); var passportOptions = { + emailOptional: true, profileToUser: function(provider, profile) { var emails = profile.emails; // NOTE(berks): get email or set to null. @@ -210,7 +212,7 @@ var passportOptions = { emails[0].value : null; - var username = provider + '.' + (profile.username || profile.id); + var username = profile.username || profile.id; var password = generateKey('password'); var userObj = { username: username, @@ -227,7 +229,10 @@ var passportOptions = { R.keys(passportProviders).map(function(strategy) { var config = passportProviders[strategy]; config.session = config.session !== false; - passportConfigurator.configureProvider(strategy, config, passportOptions); + passportConfigurator.configureProvider( + strategy, + assign(config, passportOptions) + ); }); /** From bdb7d40548c58558ad03e176d9944f6929632f92 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 10 Jun 2015 15:22:57 -0700 Subject: [PATCH 2/7] fix usernames should be saved lowercased --- common/models/user.json | 1 - server/boot/user.js | 9 +++------ server/server.js | 3 ++- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/common/models/user.json b/common/models/user.json index 6733437349..076a74dd1e 100644 --- a/common/models/user.json +++ b/common/models/user.json @@ -29,7 +29,6 @@ }, "username": { "type": "string", - "sparse": true, "lowercase": true, "trim": true }, diff --git a/server/boot/user.js b/server/boot/user.js index 5f57748f36..9597fa8ac6 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -21,7 +21,6 @@ module.exports = function(app) { res.redirect(301, '/signout'); }); router.get('/signin', getSignin); - // router.post('/signin', postSignin); router.get('/signout', signout); router.get('/forgot', getForgot); router.post('/forgot', postForgot); @@ -29,7 +28,6 @@ module.exports = function(app) { router.post('/reset/:token', postReset); router.get('/email-signup', getEmailSignup); router.get('/email-signin', getEmailSignin); - // router.post('/email-signup', postEmailSignup); router.get('/account/api', getAccountAngular); router.post('/account/profile', postUpdateProfile); router.post('/account/password', postUpdatePassword); @@ -121,15 +119,14 @@ module.exports = function(app) { */ function returnUser (req, res, next) { - User.find( - {where: { 'username': req.params.username.toLowerCase() }}, + User.findOne( + { where: { username: req.params.username.toLowerCase() } }, function(err, user) { if (err) { debug('Username err: ', err); return next(err); } - if (user[0]) { - user = user[0]; + if (user) { user.progressTimestamps = user.progressTimestamps.sort(function(a, b) { return a - b; diff --git a/server/server.js b/server/server.js index bc252012af..cce2ead0ac 100755 --- a/server/server.js +++ b/server/server.js @@ -212,7 +212,8 @@ var passportOptions = { emails[0].value : null; - var username = profile.username || profile.id; + var username = (profile.username || profile.id); + username = typeof username === 'string' ? username.toLowerCase() : username; var password = generateKey('password'); var userObj = { username: username, From 9f5ace03dcca41395025667cf430c9fee1a57b64 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 10 Jun 2015 17:11:32 -0700 Subject: [PATCH 3/7] fix acls access for user exists remote method --- common/models/user.json | 8 +++++++- public/js/main_0.0.2.js | 6 ++++-- server/boot/a-extendUser.js | 20 +++++++++++++++----- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/common/models/user.json b/common/models/user.json index 076a74dd1e..84ee2a1ba6 100644 --- a/common/models/user.json +++ b/common/models/user.json @@ -174,6 +174,12 @@ }, "validations": [], "relations": {}, - "acls": [], + "acls": [{ + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW", + "property": "doesExist" + }], "methods": [] } diff --git a/public/js/main_0.0.2.js b/public/js/main_0.0.2.js index c8e67d6aaf..3b87d243a1 100644 --- a/public/js/main_0.0.2.js +++ b/public/js/main_0.0.2.js @@ -475,14 +475,16 @@ profileValidation.directive('uniqueEmail', ['$http', function($http) { element.bind("keyup", function (event) { ngModel.$setValidity('unique', true); var email = element.val(); - if (element.val()) { + if (email) { var config = { params: { email: email } }; $http .get('/api/users/exists', config) .success(function (exists) { if (email === scope.storedEmail) { ngModel.$setValidity('unique', true); - } else if (exists) { + console.log('scoped.storedEmail', scoped.storedEmail); + } else if (exists.exists) { + console.log('setValid to false'); ngModel.$setValidity('unique', false); } }); diff --git a/server/boot/a-extendUser.js b/server/boot/a-extendUser.js index f5cb84cd52..ebb7b4724a 100644 --- a/server/boot/a-extendUser.js +++ b/server/boot/a-extendUser.js @@ -64,17 +64,26 @@ module.exports = function(app) { }); User.doesExist = function doesExist(username, email, cb) { + if (!username && !email) { + return process.nextTick(function() { + cb(null, false); + }); + } debug('checking existence'); var where = {}; if (username) { - where.username = username; + where.username = username.toLowerCase(); } else { - where.email = email; + where.email = email ? email.toLowerCase() : email; } + debug('where', where); User.count( - { where: where }, + where, function (err, count) { - if (err) { return cb(err); } + if (err) { + debug('err checking existance: ', err); + return cb(err); + } if (count > 0) { return cb(null, true); } @@ -104,7 +113,8 @@ module.exports = function(app) { } ], http: { - path: '/exists' + path: '/exists', + verb: 'get' } } ); From d01a48a8c32b8eed7ef0e3e9620bfd7d286e0c7a Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 10 Jun 2015 17:11:56 -0700 Subject: [PATCH 4/7] Allow debug to be set at runtime for gulp --- gulpfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index 1a3177de62..4cb0341a96 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -29,7 +29,7 @@ gulp.task('serve', function(cb) { ignore: paths.serverIgnore, env: { 'NODE_ENV': 'development', - 'DEBUG': 'freecc:*' + 'DEBUG': process.env.DEBUG || 'freecc:*' } }) .on('start', function() { From 84f2168769f85fac2def4ea52a27278894fe5223 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 10 Jun 2015 17:12:21 -0700 Subject: [PATCH 5/7] fix remove stray profile reference fix findOne queries should have where filter --- server/boot/user.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/server/boot/user.js b/server/boot/user.js index 9597fa8ac6..e2e4ec0494 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -261,7 +261,9 @@ module.exports = function(app) { return res.redirect('/account'); } - User.findOne({ email: req.body.email }, function(err, existingEmail) { + User.findOne({ + where: { email: req.body.email } + }, function(err, existingEmail) { if (err) { return next(err); } @@ -273,7 +275,7 @@ module.exports = function(app) { return res.redirect('/account'); } User.findOne( - { 'profile.username': req.body.username }, + { where: { username: req.body.username } }, function(err, existingUsername) { if (err) { return next(err); @@ -281,7 +283,7 @@ module.exports = function(app) { var user = req.user; if ( existingUsername && - existingUsername.profile.username !== user.username + existingUsername.username !== user.username ) { req.flash('errors', { msg: 'An account with that username already exists.' @@ -558,7 +560,7 @@ module.exports = function(app) { }, function(token, done) { User.findOne({ - email: req.body.email.toLowerCase() + where: { email: req.body.email.toLowerCase() } }, function(err, user) { if (err) { return done(err); } if (!user) { From f3b1b5ca0de01653d51ecad5dbf4f3578e7ad1df Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 10 Jun 2015 17:14:48 -0700 Subject: [PATCH 6/7] remove misc console.logs --- public/js/main_0.0.2.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/public/js/main_0.0.2.js b/public/js/main_0.0.2.js index 3b87d243a1..8b8bd285a8 100644 --- a/public/js/main_0.0.2.js +++ b/public/js/main_0.0.2.js @@ -482,9 +482,7 @@ profileValidation.directive('uniqueEmail', ['$http', function($http) { .success(function (exists) { if (email === scope.storedEmail) { ngModel.$setValidity('unique', true); - console.log('scoped.storedEmail', scoped.storedEmail); } else if (exists.exists) { - console.log('setValid to false'); ngModel.$setValidity('unique', false); } }); From 147f1d1d3795a2ae8dbd1a66a0ebb0ea0560d396 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 10 Jun 2015 17:21:57 -0700 Subject: [PATCH 7/7] fix user.exists returns an object with property exists --- public/js/main_0.0.2.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/js/main_0.0.2.js b/public/js/main_0.0.2.js index 8b8bd285a8..65ec9f170c 100644 --- a/public/js/main_0.0.2.js +++ b/public/js/main_0.0.2.js @@ -427,10 +427,10 @@ profileValidation.directive('uniqueUsername', ['$http', function($http) { var config = { params: { username: username } }; $http .get('/api/users/exists', config) - .success(function (exists) { + .success(function (result) { if (username === scope.storedUsername) { ngModel.$setValidity('unique', true); - } else if (exists) { + } else if (result.exists) { ngModel.$setValidity('unique', false); } }); @@ -458,8 +458,8 @@ profileValidation.directive('existingUsername', var config = { params: { username: username } }; $http .get('/api/users/exists', config) - .success(function(exists) { - ngModel.$setValidity('exists', exists); + .success(function(result) { + ngModel.$setValidity('exists', result.exists); }); } }); @@ -479,10 +479,10 @@ profileValidation.directive('uniqueEmail', ['$http', function($http) { var config = { params: { email: email } }; $http .get('/api/users/exists', config) - .success(function (exists) { + .success(function(result) { if (email === scope.storedEmail) { ngModel.$setValidity('unique', true); - } else if (exists.exists) { + } else if (result.exists) { ngModel.$setValidity('unique', false); } });