diff --git a/app/index.js b/app/index.js
index c37abac8c..1059c2b04 100644
--- a/app/index.js
+++ b/app/index.js
@@ -139,17 +139,17 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({
{
value: 'googleAuth',
name: 'Google',
- checked: false
+ checked: true
},
{
value: 'facebookAuth',
name: 'Facebook',
- checked: false
+ checked: true
},
{
value: 'twitterAuth',
name: 'Twitter',
- checked: false
+ checked: true
}
]
}, {
diff --git a/app/templates/client/app/account(auth)/settings/settings(html).html b/app/templates/client/app/account(auth)/settings/settings(html).html
index bb5d8ded0..94d0ee013 100644
--- a/app/templates/client/app/account(auth)/settings/settings(html).html
+++ b/app/templates/client/app/account(auth)/settings/settings(html).html
@@ -3,16 +3,35 @@
-
Change Password
+ Email
+
+
+
+
<% if (filters.oauth) { %>{{ user.localEnabled ? 'Change' : 'Set' }}<% } else { %>Change<% } %> Password
+
+
+ <% if (filters.oauth) { %>
+
+ <% } %>
\ No newline at end of file
diff --git a/app/templates/client/app/account(auth)/settings/settings(jade).jade b/app/templates/client/app/account(auth)/settings/settings(jade).jade
index 2dc55d402..8565781c2 100644
--- a/app/templates/client/app/account(auth)/settings/settings(jade).jade
+++ b/app/templates/client/app/account(auth)/settings/settings(jade).jade
@@ -2,20 +2,47 @@ div(ng-include='"components/navbar/navbar.html"')
.container
.row
.col-sm-12
- h1 Change Password
+ h1 Email
+
+ .col-sm-12
+ form(role='form', name='email', ng-submit='changeEmail()', novalidate)
+
+ .form-group.has-feedback
+ label Current Email
+ input.form-control(type='email', name='email', ng-model='user.email', placeholder='ex. me@awesome.com')
+ span.glyphicon.glyphicon-ok.form-control-feedback(ng-if='email.confirmed', title='email confirmed')
+ p.help-block(ng-show='!email.email.$valid')
+ | Email not valid
+
+ button.btn.btn-lg.btn-primary(type='submit') Save changes
+
+ .row
.col-sm-12
- form.form(name='form', ng-submit='changePassword(form)', novalidate='')
+ h1 <% if (filters.oauth) { %>{{ user.localEnabled ? 'Change' : 'Set' }}<% } else { %>Change<% } %> Password
+
+ .col-sm-12
+ form(role='form', name='pwd', ng-submit='<% if(filters.oauth) { %>!user.localEnabled ? setPassword() : <% } %>changePassword()', novalidate)
+
.form-group
label Current Password
- input.form-control(type='password', name='password', ng-model='user.oldPassword', mongoose-error='')
- p.help-block(ng-show='form.password.$error.mongoose')
+ input.form-control(type='password', name='old', placeholder='ex. password123', ng-model='user.oldPassword', <% if (filters.oauth) { %>ng-disabled='!user.localEnabled', <% } %>mongoose-error='')
+ p.help-block(ng-show='pwd.old.$error.mongoose')
| {{ errors.other }}
+
.form-group
label New Password
- input.form-control(type='password', name='newPassword', ng-model='user.newPassword', ng-minlength='3', required='')
- p.help-block(ng-show='(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || submitted)')
+ input.form-control(type='password', name='new', placeholder='ex. GoofyM1ckeyDonald&Pluto', ng-model='user.newPassword', ng-minlength='3', required)
+ p.help-block(ng-show='(pwd.new.$error.minlength || pwd.new.$error.required) && (pwd.new.$dirty || pwd.submitted)')
| Password must be at least 3 characters.
- p.help-block {{ message }}
+ p.help-block {{ message }}
button.btn.btn-lg.btn-primary(type='submit') Save changes
+
+<% if (filters.oauth) { %>
+ //- .row
+ //- .col-sm-12
+ //- h1 Social accounts
+
+ //- .col-sm-12
+<% } %>
diff --git a/app/templates/client/app/account(auth)/settings/settings.controller(coffee).coffee b/app/templates/client/app/account(auth)/settings/settings.controller(coffee).coffee
index e058f167e..4cb856146 100644
--- a/app/templates/client/app/account(auth)/settings/settings.controller(coffee).coffee
+++ b/app/templates/client/app/account(auth)/settings/settings.controller(coffee).coffee
@@ -1,17 +1,59 @@
'use strict'
angular.module '<%= scriptAppName %>'
-.controller 'SettingsCtrl', ($scope, User, Auth) ->
+.controller 'SettingsCtrl', ($scope, Auth) ->
$scope.errors = {}
- $scope.changePassword = (form) ->
- $scope.submitted = true
- if form.$valid
+ $scope.user = Auth.getCurrentUser()
+ $scope.email = {}
+
+ getEmail = (user) ->
+ return [null, null] unless $scope.user.credentials.length
+
+ for c in $scope.user.credentials when c.type is 'email'
+ return [c.value, c.confirmed]
+
+ [null, null]
+
+ [initialEmail, $scope.email.confirmed] = getEmail $scope.user
+
+ $scope.user.email = initialEmail
+
+ $scope.changeEmail = ->
+ if $scope.email.$valid
+ Auth.changeEmail initialEmail, $scope.user.email
+ .then ->
+ $scope.message = 'Email successfully changed'
+
+ .catch ->
+ # TODO: handle errors
+ $scope.message = ''
+
+ $scope.changePassword = ->
+ $scope.pwd.submitted = true
+
+ if $scope.pwd.$valid
Auth.changePassword $scope.user.oldPassword, $scope.user.newPassword
.then ->
- $scope.message = 'Password successfully changed.'
+ $scope.message = 'Password successfully changed'
.catch ->
- form.password.$setValidity 'mongoose', false
+ $scope.pwd.old.$setValidity 'mongoose', false
$scope.errors.other = 'Incorrect password'
$scope.message = ''
+<% if (filters.oauth) { %>
+ $scope.setPassword = ->
+ $scope.pwd.submitted = true
+
+ if $scope.pwd.$valid
+ Auth.setPassword $scope.user.newPassword
+ .then ->
+ $scope.message = 'Password successfully set'
+ $scope.user.localEnabled = true
+ $scope.user.newPassword = ''
+
+ .catch ->
+ $scope.pwd.old.$setValidity 'mongoose', false
+ $scope.errors.other = 'Another account with that email already exists'
+ $scope.message = ''
+<% } %>
diff --git a/app/templates/client/app/account(auth)/settings/settings.controller(js).js b/app/templates/client/app/account(auth)/settings/settings.controller(js).js
index 829bd8248..2fcf3cbf7 100644
--- a/app/templates/client/app/account(auth)/settings/settings.controller(js).js
+++ b/app/templates/client/app/account(auth)/settings/settings.controller(js).js
@@ -1,21 +1,71 @@
'use strict';
angular.module('<%= scriptAppName %>')
- .controller('SettingsCtrl', function ($scope, User, Auth) {
+ .controller('SettingsCtrl', function ($scope, Auth) {
$scope.errors = {};
- $scope.changePassword = function(form) {
- $scope.submitted = true;
- if(form.$valid) {
+ $scope.user = Auth.getCurrentUser();
+ $scope.email = {};
+
+ var getEmail = function(user) {
+ if (!$scope.user.credentials.length) {
+ return null;
+ }
+
+ for(var i in $scope.user.credentials) {
+ var c = $scope.user.credentials[i];
+ if(c.type==='email') return [c.value, c.confirmed];
+ }
+ };
+
+ var tmp = getEmail($scope.user);
+
+ var initialEmail = tmp ? tmp[0] : null;
+ $scope.email.confirmed = tmp ? tmp[1] : null;
+
+ $scope.user.email = initialEmail;
+
+ $scope.changeEmail = function () {
+ if($scope.email.$valid) {
+ Auth.changeEmail(initialEmail, $scope.user.email)
+ .then(function() {
+ $scope.message = 'Email successfully changed';
+ })
+ .catch(function() {
+ // TODO: handle errors
+ $scope.message = '';
+ });
+ }
+ }
+
+ $scope.changePassword = function() {
+ $scope.pwd.submitted = true;
+ if($scope.pwd.$valid) {
Auth.changePassword( $scope.user.oldPassword, $scope.user.newPassword )
.then( function() {
- $scope.message = 'Password successfully changed.';
+ $scope.message = 'Password successfully changed';
})
.catch( function() {
- form.password.$setValidity('mongoose', false);
+ $scope.pwd.old.$setValidity('mongoose', false);
$scope.errors.other = 'Incorrect password';
$scope.message = '';
});
}
};
+<% if (filters.oauth) { %>
+ $scope.setPassword = function() {
+ $scope.submitted = true;
+ if($scope.pwd.$valid) {
+ Auth.changePassword( $scope.user.newPassword )
+ .then( function() {
+ $scope.message = 'Password successfully set';
+ })
+ .catch( function() {
+ $scope.pwd.old.$setValidity('mongoose', false);
+ $scope.errors.other = 'Another account with that email already exists';
+ $scope.message = '';
+ });
+ }
+ };
+<% } %>
});
diff --git a/app/templates/client/app/admin(auth)/admin(css).css b/app/templates/client/app/admin(auth)/admin(css).css
index a6f536dc5..f064e4d88 100644
--- a/app/templates/client/app/admin(auth)/admin(css).css
+++ b/app/templates/client/app/admin(auth)/admin(css).css
@@ -1 +1,3 @@
.trash { color:rgb(209, 91, 71); }
+.confirm { color:rgb(240, 173, 78); }
+.confirmed { color:rgb(92, 184, 92); }
diff --git a/app/templates/client/app/admin(auth)/admin(html).html b/app/templates/client/app/admin(auth)/admin(html).html
index 5c27c7af2..8d4833c85 100644
--- a/app/templates/client/app/admin(auth)/admin(html).html
+++ b/app/templates/client/app/admin(auth)/admin(html).html
@@ -6,6 +6,7 @@
{{user.name}}
{{user.email}}
+
diff --git a/app/templates/client/app/admin(auth)/admin(jade).jade b/app/templates/client/app/admin(auth)/admin(jade).jade
index a4672dadd..d5983eccd 100644
--- a/app/templates/client/app/admin(auth)/admin(jade).jade
+++ b/app/templates/client/app/admin(auth)/admin(jade).jade
@@ -6,6 +6,9 @@ div(ng-include='"components/navbar/navbar.html"')
li.list-group-item(ng-repeat='user in users')
strong {{user.name}}
br
- span.text-muted {{user.email}}
- a.trash(ng-click='delete(user)')
+ span.text-muted {{user.credentials[0].value}}
+ a(ng-click='confirm(user)', ng-class="user.credentials[0].confirmed ? 'confirmed' : 'confirm'", title='confirm email')
+ span.glyphicon.glyphicon-ok-circle
+
+ a.trash(ng-click='delete(user)', title='delete user')
span.glyphicon.glyphicon-trash.pull-right
diff --git a/app/templates/client/app/admin(auth)/admin(less).less b/app/templates/client/app/admin(auth)/admin(less).less
index ad8202750..f0a247e2c 100644
--- a/app/templates/client/app/admin(auth)/admin(less).less
+++ b/app/templates/client/app/admin(auth)/admin(less).less
@@ -1 +1,3 @@
-.trash { color:rgb(209, 91, 71); }
\ No newline at end of file
+.trash { color:rgb(209, 91, 71); }
+.confirm { color:rgb(240, 173, 78); }
+.confirmed { color:rgb(92, 184, 92); }
\ No newline at end of file
diff --git a/app/templates/client/app/admin(auth)/admin(sass).scss b/app/templates/client/app/admin(auth)/admin(sass).scss
index a6f536dc5..f064e4d88 100644
--- a/app/templates/client/app/admin(auth)/admin(sass).scss
+++ b/app/templates/client/app/admin(auth)/admin(sass).scss
@@ -1 +1,3 @@
.trash { color:rgb(209, 91, 71); }
+.confirm { color:rgb(240, 173, 78); }
+.confirmed { color:rgb(92, 184, 92); }
diff --git a/app/templates/client/app/admin(auth)/admin(stylus).styl b/app/templates/client/app/admin(auth)/admin(stylus).styl
index d57e50db5..29f31a2d6 100644
--- a/app/templates/client/app/admin(auth)/admin(stylus).styl
+++ b/app/templates/client/app/admin(auth)/admin(stylus).styl
@@ -1,2 +1,8 @@
.trash
- color rgb(209, 91, 71)
\ No newline at end of file
+ color rgb(209, 91, 71)
+
+.confirm
+ color: rgb(240, 173, 78)
+
+.confirmed
+ color: rgb(92, 184, 92)
\ No newline at end of file
diff --git a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee
index 6f5aef8c4..bb4dc4ed4 100644
--- a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee
+++ b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee
@@ -1,7 +1,7 @@
'use strict'
angular.module '<%= scriptAppName %>'
-.controller 'AdminCtrl', ($scope, $http, Auth, User) ->
+.controller 'AdminCtrl', ($scope, $http, User) ->
$http.get '/api/users'
.success (users) ->
@@ -11,3 +11,6 @@ angular.module '<%= scriptAppName %>'
User.remove id: user._id
angular.forEach $scope.users, (u, i) ->
$scope.users.splice i, 1 if u is user
+
+ $scope.confirm = (user) ->
+ User.confirm id: user._id, null
diff --git a/app/templates/client/app/admin(auth)/admin.controller(js).js b/app/templates/client/app/admin(auth)/admin.controller(js).js
index 1c3e56167..a44512167 100644
--- a/app/templates/client/app/admin(auth)/admin.controller(js).js
+++ b/app/templates/client/app/admin(auth)/admin.controller(js).js
@@ -1,7 +1,7 @@
'use strict';
angular.module('<%= scriptAppName %>')
- .controller('AdminCtrl', function ($scope, $http, Auth, User) {
+ .controller('AdminCtrl', function ($scope, $http, User) {
$http.get('/api/users').success(function(users) {
$scope.users = users;
@@ -15,4 +15,8 @@ angular.module('<%= scriptAppName %>')
}
});
};
+
+ $scope.confirm = function(user) {
+ User.confirm({ id:user._id }, null);
+ };
});
diff --git a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee
index ac503ed0b..129d1a325 100644
--- a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee
+++ b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee
@@ -86,6 +86,50 @@ angular.module '<%= scriptAppName %>'
.$promise
+<% if (filters.oauth) { %>
+ ###
+ Set password (vel create LocalStrategy)
+
+ @param {String} newPassword
+ @param {Function} callback - optional
+ @return {Promise}
+ ###
+ setPassword: (newPassword, callback) ->
+ User.setPassword
+ id: currentUser._id
+ ,
+ newPassword: newPassword
+
+ , (user) ->
+ callback? user
+
+ , (err) ->
+ callback? err
+
+ .$promise
+<% } %>
+ ###
+ Change email
+
+ @param {String} email
+ @param {Function} callback - optional
+ @return {Promise}
+ ###
+ changeEmail: (oldEmail, newEmail, callback) ->
+ User.changeEmail
+ id: currentUser._id
+ ,
+ oldEmail: oldEmail
+ newEmail: newEmail
+
+ , (user) ->
+ callback? user
+
+ , (err) ->
+ callback? err
+
+ .$promise
+
###
Gets all available info on authenticated user
diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js
index 9afb12da9..da2b00c1f 100644
--- a/app/templates/client/components/auth(auth)/auth.service(js).js
+++ b/app/templates/client/components/auth(auth)/auth.service(js).js
@@ -91,6 +91,45 @@ angular.module('<%= scriptAppName %>')
return cb(err);
}).$promise;
},
+<% if (filters.oauth) { %>
+ /**
+ * Set password (vel create LocalStrategy)
+ *
+ * @param {String} newPassword
+ * @param {Function} callback - optional
+ * @return {Promise}
+ */
+ setPassword: function(newPassword, callback) {
+ var cb = callback || angular.noop;
+
+ return User.setPassword({ id: currentUser._id }, {
+ newPassword: newPassword
+ }, function(user) {
+ return cb(user);
+ }, function(err) {
+ return cb(err);
+ }).$promise;
+ },
+<% } %>
+ /**
+ * Change email
+ *
+ * @param {String} email
+ * @param {Function} callback - optional
+ * @return {Promise}
+ */
+ changeEmail: function(oldEmail, newEmail, callback) {
+ var cb = callback || angular.noop;
+
+ return User.changeEmail({ id: currentUser._id }, {
+ oldEmail: oldEmail,
+ newEmail: newEmail
+ }, function(user) {
+ return cb(user);
+ }, function(err) {
+ return cb(err);
+ }).$promise;
+ },
/**
* Gets all available info on authenticated user
diff --git a/app/templates/client/components/auth(auth)/user.service(coffee).coffee b/app/templates/client/components/auth(auth)/user.service(coffee).coffee
index e0dc2e839..bdd7e5bf5 100644
--- a/app/templates/client/components/auth(auth)/user.service(coffee).coffee
+++ b/app/templates/client/components/auth(auth)/user.service(coffee).coffee
@@ -9,9 +9,23 @@ angular.module '<%= scriptAppName %>'
method: 'PUT'
params:
controller: 'password'
+<% if (filters.oauth) { %>
+ setPassword:
+ method: 'POST'
+ params:
+ controller: 'password'
+<% } %>
+ changeEmail:
+ method: 'PUT'
+ params:
+ controller: 'email'
get:
method: 'GET'
params:
id: 'me'
+ confirm:
+ method: 'POST'
+ params:
+ controller: 'confirm'
\ No newline at end of file
diff --git a/app/templates/client/components/auth(auth)/user.service(js).js b/app/templates/client/components/auth(auth)/user.service(js).js
index c41fe8312..9cb49ded6 100644
--- a/app/templates/client/components/auth(auth)/user.service(js).js
+++ b/app/templates/client/components/auth(auth)/user.service(js).js
@@ -11,12 +11,30 @@ angular.module('<%= scriptAppName %>')
params: {
controller:'password'
}
+ }<% if (filters.oauth) { %>,
+ setPassword: {
+ method: 'POST',
+ params: {
+ controller: 'password'
+ }
+ }<% } %>,
+ changeEmail: {
+ method: 'PUT',
+ params: {
+ controller: 'email'
+ }
},
get: {
method: 'GET',
params: {
id:'me'
}
+ },
+ confirm: {
+ method: 'POST',
+ params: {
+ controller: 'confirm'
+ }
}
});
});
diff --git a/app/templates/server/api/user(auth)/index.js b/app/templates/server/api/user(auth)/index.js
index 48567e485..006b3d52c 100644
--- a/app/templates/server/api/user(auth)/index.js
+++ b/app/templates/server/api/user(auth)/index.js
@@ -7,11 +7,16 @@ var auth = require('../../auth/auth.service');
var router = express.Router();
-router.get('/', auth.hasRole('admin'), controller.index);
-router.delete('/:id', auth.hasRole('admin'), controller.destroy);
router.get('/me', auth.isAuthenticated(), controller.me);
-router.put('/:id/password', auth.isAuthenticated(), controller.changePassword);
+router.put('/:id/password', auth.isAuthenticated(), controller.changePassword);<% if (filters.oauth) { %>
+router.post('/:id/password', auth.isAuthenticated(), controller.setPassword);<% } %>
+router.put('/:id/email', auth.isAuthenticated(), controller.changeEmail);
router.get('/:id', auth.isAuthenticated(), controller.show);
router.post('/', controller.create);
+// admin roles
+router.get('/', auth.hasRole('admin'), controller.index);
+router.delete('/:id', auth.hasRole('admin'), controller.destroy);
+router.post('/:id/confirm', auth.hasRole('admin'), controller.confirm);
+
module.exports = router;
diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js
index f4cd10c29..dae0c1554 100644
--- a/app/templates/server/api/user(auth)/user.controller.js
+++ b/app/templates/server/api/user(auth)/user.controller.js
@@ -1,101 +1,133 @@
'use strict';
-var User = require('./user.model');
-var passport = require('passport');
-var config = require('../../config/environment');
-var jwt = require('jsonwebtoken');
+var passport = require('passport');
+var jwt = require('jsonwebtoken');
+
+var User = require('./user.model');
+var config = require('../../config/environment');
+
var validationError = function(res, err) {
return res.json(422, err);
};
-/**
- * Get list of users
- * restriction: 'admin'
- */
-exports.index = function(req, res) {
- User.find({}, '-salt -hashedPassword', function (err, users) {
- if(err) return res.send(500, err);
- res.json(200, users);
- });
-};
+var excludedFields = '-salt -hashedPassword';
-/**
- * Creates a new user
- */
-exports.create = function (req, res, next) {
- var newUser = new User(req.body);
- newUser.provider = 'local';
- newUser.role = 'user';
- newUser.save(function(err, user) {
+// Create new LocalStrategy user
+exports.create = function(req, res) {
+ User.create(req.body, function(err, user) {
if (err) return validationError(res, err);
- var token = jwt.sign({_id: user._id }, config.secrets.session, { expiresInMinutes: 60*5 });
+
+ var token = jwt.sign({ _id: user._id }, config.secrets.session, { expiresInMinutes: 30 * 24 * 60 });
res.json({ token: token });
});
};
-/**
- * Get a single user
- */
-exports.show = function (req, res, next) {
- var userId = req.params.id;
-
- User.findById(userId, function (err, user) {
+// Get a single user
+exports.show = function(req, res, next) {
+ User.findById(req.params.id, function(err, user) {
if (err) return next(err);
if (!user) return res.send(401);
- res.json(user.profile);
- });
-};
-/**
- * Deletes a user
- * restriction: 'admin'
- */
-exports.destroy = function(req, res) {
- User.findByIdAndRemove(req.params.id, function(err, user) {
- if(err) return res.send(500, err);
- return res.send(204);
+ return res.json(user.profile);
});
};
-/**
- * Change a users password
- */
-exports.changePassword = function(req, res, next) {
- var userId = req.user._id;
+// Change user's password
+exports.changePassword = function(req, res) {
var oldPass = String(req.body.oldPassword);
var newPass = String(req.body.newPassword);
- User.findById(userId, function (err, user) {
- if(user.authenticate(oldPass)) {
+ User.findById(req.user._id, function(err, user) {
+ if (user.authenticate(oldPass)) {
user.password = newPass;
user.save(function(err) {
if (err) return validationError(res, err);
+
res.send(200);
});
- } else {
- res.send(403);
- }
+
+ } else res.send(403);
});
};
+<% if (filters.oauth) { %>
+// Set password (vel. enable LocalStrategy)
+exports.setPassword = function(req, res) {
+ User.findById(req.user._id, function(err, user) {
+ // TODO: should anything else except jwt be checked here?
+ if (true) {
+ user.password = String(req.body.newPassword);
+ user.save(function(err) {
+ if (err) return validationError(res, err);
-/**
- * Get my info
- */
+ res.send(200);
+ });
+
+ } else res.send(403);
+
+ });
+};
+<% } %>
+// Change email
+exports.changeEmail = function(req, res) {
+ User.findById(req.user._id, function(err, user) {
+ if (err) return res.send(500, err);
+ if (!user) return res.json(401);
+
+ user.changeEmail(req.body.oldEmail, req.body.newEmail, function(err) {
+ if (err) return res.send(500, err);
+
+ res.send(200, user);
+ });
+ });
+};
+
+// Get currently logged in user info
exports.me = function(req, res, next) {
- var userId = req.user._id;
- User.findOne({
- _id: userId
- }, '-salt -hashedPassword', function(err, user) { // don't ever give out the password or salt
+ User.findById(req.user._id, excludedFields, function(err, user) {
if (err) return next(err);
if (!user) return res.json(401);
+
res.json(user);
});
};
+// Authentication callback
+exports.authCallback = function(req, res) {
+ return res.redirect('/');
+};
+
+
/**
- * Authentication callback
- */
-exports.authCallback = function(req, res, next) {
- res.redirect('/');
+ * Admin methods
+ **/
+
+// Get list of users
+exports.index = function(req, res) {
+ User.find({}, excludedFields, function(err, users) {
+ if (err) return res.send(500, err);
+
+ res.json(200, users);
+ });
};
+
+exports.confirm = function(req, res) {
+ User.findById(req.params.id, function(err, user) {
+ if (err) return res.send(500, err);
+
+ user.confirm(user.email, function(err) {
+ if (err) return res.send(500, err);
+
+ res.send(200, user);
+ });
+ });
+};
+
+// Delete a user
+exports.destroy = function(req, res) {
+ User.findByIdAndRemove(req.params.id, function(err, user) {
+ if (err) return res.send(500, err);
+
+ res.send(204);
+ });
+};
\ No newline at end of file
diff --git a/app/templates/server/api/user(auth)/user.model.js b/app/templates/server/api/user(auth)/user.model.js
index cc8d59263..d363b1ed3 100644
--- a/app/templates/server/api/user(auth)/user.model.js
+++ b/app/templates/server/api/user(auth)/user.model.js
@@ -1,149 +1,205 @@
'use strict';
-var mongoose = require('mongoose');
-var Schema = mongoose.Schema;
-var crypto = require('crypto');<% if(filters.oauth) { %>
-var authTypes = ['github', 'twitter', 'facebook', 'google'];<% } %>
+var mongoose = require('mongoose');
+var Schema = mongoose.Schema;
+var crypto = require('crypto');
+
+
+var CredentialSchema = new Schema({
+ type: {
+ type: String,
+ "default": 'email',
+ "enum": ['email', 'phone']
+ },
+ value: {
+ type: String,
+ required: true,
+ lowercase: true,
+ trim: true
+ },
+ confirmed: {
+ type: Boolean,
+ "default": false
+ }
+}, { _id:false });
+
+
var UserSchema = new Schema({
name: String,
- email: { type: String, lowercase: true },
role: {
type: String,
- default: 'user'
+ "default": 'user'
},
+ username: String,
+ salt: String,
hashedPassword: String,
- provider: String,
- salt: String<% if (filters.oauth) { %>,<% if (filters.facebookAuth) { %>
- facebook: {},<% } %><% if (filters.twitterAuth) { %>
- twitter: {},<% } %><% if (filters.googleAuth) { %>
- google: {},<% } %>
- github: {}<% } %>
+
+ credentials: [ CredentialSchema ]<% if (filters.oauth) { %>,
+
+ // NOTE: using `Mixed` is tricky. Should be changed to sth else.
+ strategies: {
+ type: Schema.Types.Mixed,
+ "default": {}
+ },
+ localEnabled: {
+ type: Boolean,
+ "default": false
+ }<% } %>
});
-/**
- * Virtuals
- */
UserSchema
- .virtual('password')
- .set(function(password) {
- this._password = password;
- this.salt = this.makeSalt();
- this.hashedPassword = this.encryptPassword(password);
- })
- .get(function() {
- return this._password;
- });
+.virtual('password')
+.set(function(pwd) {
+ this.salt = this.makeSalt();
+ this.hashedPassword = this.encryptPassword(pwd);
+
+ <% if (filters.oauth) { %>// Setting password implies enabling LocalStrategy
+ this.localEnabled = true;<% } %>
+});
-// Public profile information
UserSchema
- .virtual('profile')
- .get(function() {
- return {
- 'name': this.name,
- 'role': this.role
- };
- });
+.path('hashedPassword')<% if (filters.oauth) { %>
+.validate(function(hashedPwd) {
+ return !!this.emails.length;
+
+}, 'Cannot set password with empty email')<% } %>
+.validate(function(hashedPwd) {<% if (filters.oauth) { %>
+ if (!this.localEnabled) return true;<% } %>
+
+ return !!hashedPwd.length;
+}, 'Password cannot be blank');
-// Non-sensitive info we'll be putting in the token
UserSchema
- .virtual('token')
- .get(function() {
- return {
- '_id': this._id,
- 'role': this.role
- };
+.virtual('email')
+.set(function(email) {
+ this.credentials.push({
+ value: email
});
-/**
- * Validations
- */
+}).get(function() {
+ // returns only first found email
+ // TODO: in case of multiple emails, should prioritize confirmed ones
+ return this.credentials.filter(function(c) {
+ return c.type==='email';
-// Validate empty email
-UserSchema
- .path('email')
- .validate(function(email) {<% if (filters.oauth) { %>
- if (authTypes.indexOf(this.provider) !== -1) return true;<% } %>
- return email.length;
- }, 'Email cannot be blank');
+ })[0].value;
+});
-// Validate empty password
UserSchema
- .path('hashedPassword')
- .validate(function(hashedPassword) {<% if (filters.oauth) { %>
- if (authTypes.indexOf(this.provider) !== -1) return true;<% } %>
- return hashedPassword.length;
- }, 'Password cannot be blank');
+.virtual('emails')
+.get(function() {
+ return this.credentials
+ .filter(function(c) { return c.type==='email'; })
+ .map(function(c) { return c.value; });
+
+});
-// Validate email is not taken
UserSchema
- .path('email')
- .validate(function(value, respond) {
- var self = this;
- this.constructor.findOne({email: value}, function(err, user) {
- if(err) throw err;
- if(user) {
- if(self.id === user.id) return respond(true);
- return respond(false);
+.pre('save', function(next) {<% if (filters.oauth) { %>
+ if(!this.localEnabled) {
+ if (Object.keys(this.strategies).length===0) {
+ return next(new Error('No connected accounts'));
+ }
+ return next();
+ }<% } %>
+
+ mongoose.models['User']<% if (filters.oauth) { %>
+ .find({ localEnabled:true })<% } %>
+ .where('credentials.type').equals('email')
+ .where('credentials.value').equals(this.email)
+ .where('_id').ne(String(this._id))
+ .exec(function(err, users) {
+ if (users.length) {
+ return next(new Error('Account with this email address already exists'));
}
- respond(true);
+ next();
});
-}, 'The specified email address is already in use.');
-
-var validatePresenceOf = function(value) {
- return value && value.length;
-};
-/**
- * Pre-save hook
- */
-UserSchema
- .pre('save', function(next) {
- if (!this.isNew) return next();
-
- if (!validatePresenceOf(this.hashedPassword)<% if (filters.oauth) { %> && authTypes.indexOf(this.provider) === -1<% } %>)
- next(new Error('Invalid password'));
- else
- next();
- });
+});
-/**
- * Methods
- */
UserSchema.methods = {
- /**
- * Authenticate - check if the passwords are the same
- *
- * @param {String} plainText
- * @return {Boolean}
- * @api public
- */
- authenticate: function(plainText) {
- return this.encryptPassword(plainText) === this.hashedPassword;
+ authenticate: function(pwd) {
+ return this.hashedPassword === this.encryptPassword(pwd);
+ },
+ encryptPassword: function(pwd) {
+ var salt;
+ if (!pwd || !this.salt) {
+ return null;
+ }
+ salt = new Buffer(this.salt, 'base64');
+ return crypto.pbkdf2Sync(pwd, salt, 10000, 64).toString('base64');
+ },
+ confirm: function(emailOrPhone, cb) {
+ this.credentials.forEach(function(c) {
+ if (c.value===emailOrPhone) {
+ c.confirmed = true;
+ }
+ });
+ this.save(cb);
+ },
+ changeEmail: function(oldEmail, newEmail, cb) {
+ this.credentials.forEach(function(c) {
+ if (c.value===oldEmail) {
+ c.value = newEmail;
+ c.confirmed = false;
+ }
+ });
+ this.save(cb);
},
-
- /**
- * Make salt
- *
- * @return {String}
- * @api public
- */
makeSalt: function() {
return crypto.randomBytes(16).toString('base64');
- },
+ }<% if (filters.oauth) { %>,
+ absorb: function(name, profile) {
+ if (!this.strategies[name]) {
+ this.strategies[name] = profile;
+ this.markModified('strategies');
+ this.save();
+ } else {
+ // TODO: move current to archive, and save current as current
+ console.log("update profile");
+ }
+ }<% } %>
+};
- /**
- * Encrypt password
- *
- * @param {String} password
- * @return {String}
- * @api public
- */
- encryptPassword: function(password) {
- if (!password || !this.salt) return '';
- var salt = new Buffer(this.salt, 'base64');
- return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64');
- }
+UserSchema.statics = {
+ findOneByEmail: function(email, cb) {
+ this.find({ 'credentials.value': email.toLowerCase() })
+ .where('credentials.type').equals('email')
+ .exec(function(err, user) {
+ if (err) return cb(err);
+ if (user.length === 0) return cb(null, null);
+
+ cb(null, user[0]);
+ });
+ }<% if (filters.oauth) { %>,
+ findDuplicates: function(data, cb) {
+ var dataFormatted;
+ dataFormatted = [];
+
+ if (data.email != null) {
+ dataFormatted.push({
+ 'credentials.type': 'email',
+ 'credentials.value': data.email
+ });
+ }
+
+ if (data.phone != null) {
+ dataFormatted.push({
+ 'credentials.type': 'phone',
+ 'credentials.value': data.phone
+ });
+ }
+
+ this.find({ 'credentials.confirmed':true })
+ .or(dataFormatted)
+ .exec(function(err, users) {
+ if (err) return cb(err);
+ if (users.length===0) return cb(null, null);
+
+ cb(null, users);
+ });
+ }<% } %>
};
-module.exports = mongoose.model('User', UserSchema);
+module.exports = mongoose.model('User', UserSchema);
\ No newline at end of file
diff --git a/app/templates/server/api/user(auth)/user.model.spec.js b/app/templates/server/api/user(auth)/user.model.spec.js
index 2c1b7dfbe..1781521dc 100644
--- a/app/templates/server/api/user(auth)/user.model.spec.js
+++ b/app/templates/server/api/user(auth)/user.model.spec.js
@@ -5,22 +5,22 @@ var app = require('../../app');
var User = require('./user.model');
var user = new User({
- provider: 'local',
name: 'Fake User',
email: 'test@test.com',
password: 'password'
});
describe('User Model', function() {
+
+ // Clear users before testing
before(function(done) {
- // Clear users before testing
- User.remove().exec().then(function() {
+ User.remove().exec().then(function(){
done();
});
});
afterEach(function(done) {
- User.remove().exec().then(function() {
+ User.remove().exec().then(function(){
done();
});
});
diff --git a/app/templates/server/auth(auth)/auth.service.js b/app/templates/server/auth(auth)/auth.service.js
index 38ec34302..56a5233c8 100644
--- a/app/templates/server/auth(auth)/auth.service.js
+++ b/app/templates/server/auth(auth)/auth.service.js
@@ -1,31 +1,32 @@
'use strict';
-var mongoose = require('mongoose');
-var passport = require('passport');
-var config = require('../config/environment');
-var jwt = require('jsonwebtoken');
-var expressJwt = require('express-jwt');
-var compose = require('composable-middleware');
-var User = require('../api/user/user.model');
+var mongoose = require('mongoose');
+var passport = require('passport');
+var jwt = require('jsonwebtoken');
+var expressJwt = require('express-jwt');
+var compose = require('composable-middleware');
+
+var config = require('../config/environment');
+var User = require('../api/user/user.model');
+
var validateJwt = expressJwt({ secret: config.secrets.session });
-/**
- * Attaches the user object to the request if authenticated
- * Otherwise returns 403
- */
-function isAuthenticated() {
+
+// Attaches the user object to the request if authenticated
+// Otherwise returns 403
+var isAuthenticated = function() {
return compose()
// Validate jwt
.use(function(req, res, next) {
// allow access_token to be passed through query parameter as well
- if(req.query && req.query.hasOwnProperty('access_token')) {
+ if (req.query && req.query.hasOwnProperty('access_token')) {
req.headers.authorization = 'Bearer ' + req.query.access_token;
}
validateJwt(req, res, next);
})
// Attach user to request
.use(function(req, res, next) {
- User.findById(req.user._id, function (err, user) {
+ User.findById(req.user._id, function(err, user) {
if (err) return next(err);
if (!user) return res.send(401);
@@ -33,44 +34,42 @@ function isAuthenticated() {
next();
});
});
-}
+};
-/**
- * Checks if the user role meets the minimum requirements of the route
- */
-function hasRole(roleRequired) {
+// Checks if the user role meets the minimum requirements of the route
+var hasRole = function(roleRequired) {
if (!roleRequired) throw new Error('Required role needs to be set');
return compose()
.use(isAuthenticated())
- .use(function meetsRequirements(req, res, next) {
+ .use(function(req, res, next) {
if (config.userRoles.indexOf(req.user.role) >= config.userRoles.indexOf(roleRequired)) {
next();
- }
- else {
- res.send(403);
- }
+
+ } else res.send(403);
});
-}
+};
+
+// Returns a jwt token signed by the app secret
+var signToken = function(id, role) {
+ var payload = { _id: id };
+ if (role !== null) payload.role = role;
+
+ return jwt.sign(payload, config.secrets.session, { expiresInMinutes: 30 * 24 * 60 }); // 30 days
+};
-/**
- * Returns a jwt token signed by the app secret
- */
-function signToken(id) {
- return jwt.sign({ _id: id }, config.secrets.session, { expiresInMinutes: 60*5 });
-}
+// Set token cookie directly for oAuth strategies
+var setTokenCookie = function(req, res) {
+ if (!req.user) return res.json(404, { message: 'Something went wrong, please try again' });
-/**
- * Set token cookie directly for oAuth strategies
- */
-function setTokenCookie(req, res) {
- if (!req.user) return res.json(404, { message: 'Something went wrong, please try again.'});
var token = signToken(req.user._id, req.user.role);
res.cookie('token', JSON.stringify(token));
res.redirect('/');
-}
+};
-exports.isAuthenticated = isAuthenticated;
-exports.hasRole = hasRole;
-exports.signToken = signToken;
-exports.setTokenCookie = setTokenCookie;
\ No newline at end of file
+module.exports = {
+ isAuthenticated: isAuthenticated,
+ hasRole: hasRole,
+ signToken: signToken,
+ setTokenCookie: setTokenCookie
+};
\ No newline at end of file
diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js
index 4a6f87886..d94841e62 100644
--- a/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js
+++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js
@@ -6,9 +6,15 @@ var auth = require('../auth.service');
var router = express.Router();
+
+// available scopes:
+// https://developers.facebook.com/docs/facebook-login/permissions/v2.0#reference
+var SCOPE = ['email', 'user_about_me'];
+
+
router
.get('/', passport.authenticate('facebook', {
- scope: ['email', 'user_about_me'],
+ scope: SCOPE,
failureRedirect: '/signup',
session: false
}))
diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js
index 90ae48939..71a8480b2 100644
--- a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js
+++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js
@@ -1,37 +1,49 @@
-var passport = require('passport');
-var FacebookStrategy = require('passport-facebook').Strategy;
+'use strict';
+
+var passport = require('passport');
+var FacebookStrategy= require('passport-facebook').Strategy;
exports.setup = function (User, config) {
- passport.use(new FacebookStrategy({
- clientID: config.facebook.clientID,
- clientSecret: config.facebook.clientSecret,
- callbackURL: config.facebook.callbackURL
- },
+ passport.use(new FacebookStrategy(config.facebook,
function(accessToken, refreshToken, profile, done) {
- User.findOne({
- 'facebook.id': profile.id
- },
- function(err, user) {
- if (err) {
- return done(err);
- }
- if (!user) {
- user = new User({
+
+ User.findOne({ 'strategies.facebook.id': profile.id }, function(err, user) {
+ if (err) return done(err);
+ if (user) return done(null, user);
+
+ User.findDuplicates({
+
+ // We can treat this email as confirmed because:
+ // Without confirming user's are not able to "log in to apps"
+ // more: http://goo.gl/OKcd6H
+ email: profile.emails[0].value
+
+ }, function (err, users) {
+ if (err) return done(err);
+ if (users) {
+ var user = users[0];
+ user.absorb(profile.provider, profile);
+
+ // we can do that because we have it handled by Facebook
+ user.confirm(profile.emails[0].value);
+ return done(null, user);
+ }
+
+ var user = new User({
name: profile.displayName,
email: profile.emails[0].value,
- role: 'user',
username: profile.username,
- provider: 'facebook',
- facebook: profile._json
+ strategies: { facebook: profile._json }
});
+ user.confirm(profile.emails[0].value);
+
user.save(function(err) {
- if (err) done(err);
- return done(err, user);
+ if(err) return done(err);
+ return done(null, user);
});
- } else {
- return done(err, user);
- }
- })
+
+ });
+ });
}
));
};
\ No newline at end of file
diff --git a/app/templates/server/auth(auth)/google(googleAuth)/index.js b/app/templates/server/auth(auth)/google(googleAuth)/index.js
index 9b1ce39fe..220def868 100644
--- a/app/templates/server/auth(auth)/google(googleAuth)/index.js
+++ b/app/templates/server/auth(auth)/google(googleAuth)/index.js
@@ -6,13 +6,16 @@ var auth = require('../auth.service');
var router = express.Router();
+
+// available scopes:
+// https://developers.google.com/+/api/oauth
+var SCOPE = [ 'profile', 'email' ];
+
+
router
.get('/', passport.authenticate('google', {
+ scope: SCOPE,
failureRedirect: '/signup',
- scope: [
- 'https://www.googleapis.com/auth/userinfo.profile',
- 'https://www.googleapis.com/auth/userinfo.email'
- ],
session: false
}))
diff --git a/app/templates/server/auth(auth)/google(googleAuth)/passport.js b/app/templates/server/auth(auth)/google(googleAuth)/passport.js
index 211fe78d7..953f2b9eb 100644
--- a/app/templates/server/auth(auth)/google(googleAuth)/passport.js
+++ b/app/templates/server/auth(auth)/google(googleAuth)/passport.js
@@ -1,32 +1,48 @@
-var passport = require('passport');
-var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
+'use strict';
+
+var passport = require('passport');
+var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
exports.setup = function (User, config) {
- passport.use(new GoogleStrategy({
- clientID: config.google.clientID,
- clientSecret: config.google.clientSecret,
- callbackURL: config.google.callbackURL
- },
+ passport.use(new GoogleStrategy(config.google,
function(accessToken, refreshToken, profile, done) {
- User.findOne({
- 'google.id': profile.id
- }, function(err, user) {
- if (!user) {
- user = new User({
+
+ User.findOne({ 'strategies.google.id': profile.id }, function(err, user) {
+ if (err) return done(err);
+ if (user) return done(null, user);
+
+ User.findDuplicates({
+
+ // We can treat this email as confirmed because:
+ // It's immpossible to create Google account without Gmail address,
+ // and that one is returned by Google API after user signed in.
+ email: profile.emails[0].value
+
+ }, function (err, users) {
+ if (err) return done(err);
+ if (users) {
+ var user = users[0];
+ user.absorb(profile.provider, profile);
+
+ // we can do that because we have it handled by Google
+ user.confirm(profile.emails[0].value);
+ return done(null, user);
+ }
+
+ var user = new User({
name: profile.displayName,
email: profile.emails[0].value,
- role: 'user',
username: profile.username,
- provider: 'google',
- google: profile._json
+ strategies: { google: profile._json }
});
+ user.confirm(profile.emails[0].value);
+
user.save(function(err) {
- if (err) done(err);
- return done(err, user);
+ if(err) return done(err);
+ return done(null, user);
});
- } else {
- return done(err, user);
- }
+
+ });
});
}
));
diff --git a/app/templates/server/auth(auth)/index.js b/app/templates/server/auth(auth)/index.js
index e3e6c87ad..8c7449242 100644
--- a/app/templates/server/auth(auth)/index.js
+++ b/app/templates/server/auth(auth)/index.js
@@ -7,15 +7,15 @@ var User = require('../api/user/user.model');
// Passport Configuration
require('./local/passport').setup(User, config);<% if (filters.facebookAuth) { %>
-require('./facebook/passport').setup(User, config);<% } %><% if (filters.googleAuth) { %>
-require('./google/passport').setup(User, config);<% } %><% if (filters.twitterAuth) { %>
+require('./facebook/passport').setup(User, config);<% } if (filters.googleAuth) { %>
+require('./google/passport').setup(User, config);<% } if (filters.twitterAuth) { %>
require('./twitter/passport').setup(User, config);<% } %>
var router = express.Router();
router.use('/local', require('./local'));<% if (filters.facebookAuth) { %>
-router.use('/facebook', require('./facebook'));<% } %><% if (filters.twitterAuth) { %>
-router.use('/twitter', require('./twitter'));<% } %><% if (filters.googleAuth) { %>
+router.use('/facebook', require('./facebook'));<% } if (filters.twitterAuth) { %>
+router.use('/twitter', require('./twitter'));<% } if (filters.googleAuth) { %>
router.use('/google', require('./google'));<% } %>
module.exports = router;
\ No newline at end of file
diff --git a/app/templates/server/auth(auth)/local/index.js b/app/templates/server/auth(auth)/local/index.js
index 8bf88a046..0e2e5c137 100644
--- a/app/templates/server/auth(auth)/local/index.js
+++ b/app/templates/server/auth(auth)/local/index.js
@@ -14,6 +14,7 @@ router.post('/', function(req, res, next) {
var token = auth.signToken(user._id, user.role);
res.json({token: token});
+
})(req, res, next)
});
diff --git a/app/templates/server/auth(auth)/local/passport.js b/app/templates/server/auth(auth)/local/passport.js
index ac82b42a2..444847751 100644
--- a/app/templates/server/auth(auth)/local/passport.js
+++ b/app/templates/server/auth(auth)/local/passport.js
@@ -1,25 +1,24 @@
+'use strict';
+
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
exports.setup = function (User, config) {
passport.use(new LocalStrategy({
- usernameField: 'email',
- passwordField: 'password' // this is the virtual field on the model
- },
- function(email, password, done) {
- User.findOne({
- email: email.toLowerCase()
- }, function(err, user) {
- if (err) return done(err);
+ usernameField: 'email',
+ passwordField: 'password' // this is the virtual field on the model
+ },
+ function(email, password, done) {
+ User.findOneByEmail(email, function(err, user) {
+ if (err) return done(err);
- if (!user) {
- return done(null, false, { message: 'This email is not registered.' });
- }
- if (!user.authenticate(password)) {
- return done(null, false, { message: 'This password is not correct.' });
- }
- return done(null, user);
- });
- }
- ));
+ if (!user) {
+ return done(null, false, { message: 'This email is not registered.' });
+ }
+ if (!user.authenticate(password)) {
+ return done(null, false, { message: 'This password is not correct.' });
+ }
+ return done(null, user);
+ });
+ }));
};
\ No newline at end of file
diff --git a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js
index a2eb4a537..c283b6e90 100644
--- a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js
+++ b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js
@@ -1,35 +1,27 @@
+'use strict';
+
+var passport = require('passport');
+var TwitterStrategy = require('passport-twitter').Strategy;
+
exports.setup = function (User, config) {
- var passport = require('passport');
- var TwitterStrategy = require('passport-twitter').Strategy;
+ passport.use(new TwitterStrategy(config.twitter,
+ function(token, tokenSecret, profile, done) {
+
+ User.findOne({ 'strategies.twitter.id_str': profile.id }, function(err, user) {
+ if (err) return done(err);
+ if (user) return done(null, user);
- passport.use(new TwitterStrategy({
- consumerKey: config.twitter.clientID,
- consumerSecret: config.twitter.clientSecret,
- callbackURL: config.twitter.callbackURL
- },
- function(token, tokenSecret, profile, done) {
- User.findOne({
- 'twitter.id_str': profile.id
- }, function(err, user) {
- if (err) {
- return done(err);
- }
- if (!user) {
- user = new User({
+ User.create({
name: profile.displayName,
username: profile.username,
- role: 'user',
- provider: 'twitter',
- twitter: profile._json
- });
- user.save(function(err) {
+ strategies: { twitter: profile._json }
+
+ }, function(err, user) {
if (err) return done(err);
- return done(err, user);
+ return done(null, user);
+
});
- } else {
- return done(err, user);
- }
- });
+ });
}
));
};
\ No newline at end of file
diff --git a/app/templates/server/config/_local.env.js b/app/templates/server/config/_local.env.js
index e95b1c6ad..2576351d3 100644
--- a/app/templates/server/config/_local.env.js
+++ b/app/templates/server/config/_local.env.js
@@ -6,18 +6,18 @@
// This file should not be tracked by git.
module.exports = {
- DOMAIN: 'http://localhost:9000',
- SESSION_SECRET: "<%= _.slugify(appname) + '-secret' %>",<% if (filters.facebookAuth) { %>
+ DOMAIN: 'http://localhost:9000',
+ SESSION_SECRET: "<%= _.slugify(appname) + '-secret' %>",<% if (filters.facebookAuth) { %>
- FACEBOOK_ID: 'app-id',
- FACEBOOK_SECRET: 'secret',<% } if (filters.twitterAuth) { %>
+ FACEBOOK_ID: 'app-id',
+ FACEBOOK_SECRET: 'secret',<% } if (filters.twitterAuth) { %>
- TWITTER_ID: 'app-id',
- TWITTER_SECRET: 'secret',<% } if (filters.googleAuth) { %>
+ TWITTER_ID: 'app-id',
+ TWITTER_SECRET: 'secret',<% } if (filters.googleAuth) { %>
+
+ GOOGLE_ID: 'app-id',
+ GOOGLE_SECRET: 'secret',<% } %>
- GOOGLE_ID: 'app-id',
- GOOGLE_SECRET: 'secret',
-<% } %>
// Control debug level for modules using visionmedia/debug
DEBUG: ''
};
diff --git a/app/templates/server/config/environment/index.js b/app/templates/server/config/environment/index.js
index b6c5ed60a..2f50a92bb 100644
--- a/app/templates/server/config/environment/index.js
+++ b/app/templates/server/config/environment/index.js
@@ -42,21 +42,21 @@ var all = {
},
<% if(filters.facebookAuth) { %>
facebook: {
- clientID: process.env.FACEBOOK_ID || 'id',
- clientSecret: process.env.FACEBOOK_SECRET || 'secret',
- callbackURL: process.env.DOMAIN + '/auth/facebook/callback'
+ clientID: process.env.FACEBOOK_ID || 'id',
+ clientSecret: process.env.FACEBOOK_SECRET || 'secret',
+ callbackURL: process.env.DOMAIN + '/auth/facebook/callback'
},
-<% } %><% if(filters.twitterAuth) { %>
+<% } if(filters.twitterAuth) { %>
twitter: {
- clientID: process.env.TWITTER_ID || 'id',
- clientSecret: process.env.TWITTER_SECRET || 'secret',
- callbackURL: process.env.DOMAIN + '/auth/twitter/callback'
+ consumerKey: process.env.TWITTER_ID || 'id',
+ consumerSecret: process.env.TWITTER_SECRET || 'secret',
+ callbackURL: process.env.DOMAIN + '/auth/twitter/callback'
},
-<% } %><% if(filters.googleAuth) { %>
+<% } if(filters.googleAuth) { %>
google: {
- clientID: process.env.GOOGLE_ID || 'id',
- clientSecret: process.env.GOOGLE_SECRET || 'secret',
- callbackURL: process.env.DOMAIN + '/auth/google/callback'
+ clientID: process.env.GOOGLE_ID || 'id',
+ clientSecret: process.env.GOOGLE_SECRET || 'secret',
+ callbackURL: process.env.DOMAIN + '/auth/google/callback'
}<% } %>
};
diff --git a/app/templates/server/config/seed(mongoose).js b/app/templates/server/config/seed(mongoose).js
index 27ab19417..8eaef4ede 100644
--- a/app/templates/server/config/seed(mongoose).js
+++ b/app/templates/server/config/seed(mongoose).js
@@ -27,23 +27,24 @@ Thing.find({}).remove(function() {
},{
name : 'Deployment Ready',
info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift subgenerators'
+ }, function() {
+ console.log('finished populating things');
});
});<% if (filters.auth) { %>
User.find({}).remove(function() {
User.create({
- provider: 'local',
name: 'Test User',
email: 'test@test.com',
password: 'test'
+
}, {
- provider: 'local',
role: 'admin',
name: 'Admin',
email: 'admin@admin.com',
password: 'admin'
+
}, function() {
- console.log('finished populating users');
- }
- );
+ console.log('finished populating users');
+ });
});<% } %>
\ No newline at end of file