Merge pull request #4621 from HabitRPG/lefnire/change-email
feat(change-email): allow changing email address
This commit is contained in:
@@ -77,33 +77,12 @@ habitrpg.controller('SettingsCtrl',
|
||||
$rootScope.$state.go('tasks');
|
||||
}
|
||||
|
||||
$scope.changeUsername = function(changeUser){
|
||||
if (!changeUser.newUsername || !changeUser.password) {
|
||||
return alert(window.env.t('fillAll'));
|
||||
}
|
||||
$http.post(ApiUrl.get() + '/api/v2/user/change-username', changeUser)
|
||||
$scope.changeUser = function(attr, updates){
|
||||
$http.post(ApiUrl.get() + '/api/v2/user/change-'+attr, updates)
|
||||
.success(function(){
|
||||
alert(window.env.t('usernameSuccess'));
|
||||
$scope.changeUser = {};
|
||||
alert(window.env.t(attr+'Success'));
|
||||
_.each(updates, function(v,k){updates[k]=null;});
|
||||
User.sync();
|
||||
})
|
||||
.error(function(data){
|
||||
alert(data.err);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.changePassword = function(changePass){
|
||||
if (!changePass.oldPassword || !changePass.newPassword || !changePass.confirmNewPassword) {
|
||||
return alert(window.env.t('fillAll'));
|
||||
}
|
||||
$http.post(ApiUrl.get() + '/api/v2/user/change-password', changePass)
|
||||
.success(function(data, status, headers, config){
|
||||
if (data.err) return alert(data.err);
|
||||
alert(window.env.t('passSuccess'));
|
||||
$scope.changePass = {};
|
||||
})
|
||||
.error(function(data, status, headers, config){
|
||||
alert(data.err);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+42
-23
@@ -23,6 +23,10 @@ var accountSuspended = function(uuid){
|
||||
code: 'ACCOUNT_SUSPENDED'
|
||||
};
|
||||
}
|
||||
// escape email for regex, then search case-insensitive. See http://stackoverflow.com/a/3561711/362790
|
||||
var mongoEmailRegex = function(email){
|
||||
return new RegExp('^' + email.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i');
|
||||
}
|
||||
|
||||
api.auth = function(req, res, next) {
|
||||
var uid = req.headers['x-api-user'];
|
||||
@@ -196,9 +200,7 @@ api.resetPassword = function(req, res, next){
|
||||
newPassword = utils.makeSalt(), // use a salt as the new password too (they'll change it later)
|
||||
hashed_password = utils.encryptPassword(newPassword, salt);
|
||||
|
||||
// escape email for regex, then search case-insensitive. See http://stackoverflow.com/a/3561711/362790
|
||||
var emailRegExp = new RegExp('^' + email.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i');
|
||||
User.findOne({'auth.local.email':emailRegExp}, function(err, user){
|
||||
User.findOne({'auth.local.email':mongoEmailRegex(email)}, function(err, user){
|
||||
if (err) return next(err);
|
||||
if (!user) return res.send(500, {err:"Couldn't find a user registered for email " + email});
|
||||
user.auth.local.salt = salt;
|
||||
@@ -215,28 +217,45 @@ api.resetPassword = function(req, res, next){
|
||||
});
|
||||
};
|
||||
|
||||
var invalidPassword = function(user, password){
|
||||
var hashed_password = utils.encryptPassword(password, user.auth.local.salt);
|
||||
if (hashed_password !== user.auth.local.hashed_password)
|
||||
return {code:401, err:"Incorrect password"};
|
||||
return false;
|
||||
}
|
||||
|
||||
api.changeUsername = function(req, res, next) {
|
||||
var user = res.locals.user,
|
||||
password = req.body.password,
|
||||
newUsername = req.body.newUsername;
|
||||
async.waterfall([
|
||||
function(cb){
|
||||
User.findOne({'auth.local.username': req.body.username}, {auth:1}, cb);
|
||||
},
|
||||
function(found, cb){
|
||||
if (found) return cb({code:401, err: "Username already taken"});
|
||||
if (invalidPassword(res.locals.user, req.body.password)) return cb(invalidPassword(res.locals.user, req.body.password));
|
||||
res.locals.user.auth.local.username = req.body.username;
|
||||
res.locals.user.save(cb);
|
||||
}
|
||||
], function(err){
|
||||
if (err) return err.code ? res.json(err.code, err) : next(err);
|
||||
res.send(200);
|
||||
})
|
||||
}
|
||||
|
||||
User.findOne({'auth.local.username': newUsername}, function(err, result) {
|
||||
if (err) next(err);
|
||||
if(result) return res.json(401, {err: "Username already taken"});
|
||||
|
||||
var salt = user.auth.local.salt;
|
||||
var hashed_password = utils.encryptPassword(password, salt);
|
||||
|
||||
if (hashed_password !== user.auth.local.hashed_password)
|
||||
return res.json(401, {err:"Incorrect password"});
|
||||
|
||||
user.auth.local.username = newUsername;
|
||||
user.save(function(err, saved){
|
||||
if (err) next(err);
|
||||
res.send(200);
|
||||
user = password = newUsername = null;
|
||||
})
|
||||
});
|
||||
api.changeEmail = function(req, res, next){
|
||||
async.waterfall([
|
||||
function(cb){
|
||||
User.findOne({'auth.local.email': mongoEmailRegex(req.body.email)}, {auth:1}, cb);
|
||||
},
|
||||
function(found, cb){
|
||||
if(found) return cb({code:401, err: "Email already taken"});
|
||||
if (invalidPassword(res.locals.user, req.body.password)) return cb(invalidPassword(res.locals.user, req.body.password));
|
||||
res.locals.user.auth.local.email = req.body.email;
|
||||
res.locals.user.save(cb);
|
||||
}
|
||||
], function(err){
|
||||
if (err) return err.code ? res.json(err.code,err) : next(err);
|
||||
res.send(200);
|
||||
})
|
||||
}
|
||||
|
||||
api.changePassword = function(req, res, next) {
|
||||
|
||||
@@ -11,6 +11,7 @@ router.post('/api/v2/user/auth/social', i18n.getUserLanguage, auth.loginSocial);
|
||||
router.post('/api/v2/user/reset-password', i18n.getUserLanguage, auth.resetPassword);
|
||||
router.post('/api/v2/user/change-password', i18n.getUserLanguage, auth.auth, auth.changePassword);
|
||||
router.post('/api/v2/user/change-username', i18n.getUserLanguage, auth.auth, auth.changeUsername);
|
||||
router.post('/api/v2/user/change-email', i18n.getUserLanguage, auth.auth, auth.changeEmail);
|
||||
|
||||
router.post('/api/v1/register', i18n.getUserLanguage, auth.registerUser);
|
||||
router.post('/api/v1/user/auth/local', i18n.getUserLanguage, auth.loginLocal);
|
||||
|
||||
+21
-10
@@ -103,7 +103,7 @@ script(type='text/ng-template', id='partials/options.settings.settings.html')
|
||||
|
|
||||
=env.t('loginNameDescription3')
|
||||
p=env.t('email')
|
||||
|: {{::user.auth.local.email}}
|
||||
|: {{user.auth.local.email}}
|
||||
p
|
||||
small.muted
|
||||
=env.t('emailChange1')
|
||||
@@ -112,22 +112,33 @@ script(type='text/ng-template', id='partials/options.settings.settings.html')
|
||||
|
|
||||
=env.t('emailChange3')
|
||||
hr
|
||||
|
||||
h5=env.t('changeUsername')
|
||||
form(ng-submit='changeUsername(changeUser)', ng-show='user.auth.local')
|
||||
form(ng-submit='changeUser("username", usernameUpdates)', ng-init='usernameUpdates={}', ng-show='user.auth.local', name='changeUsername', novalidate)
|
||||
//-.alert.alert-danger(ng-messages='changeUsername.$error && changeUsername.submitted')=env.t('fillAll')
|
||||
.form-group
|
||||
input.form-control(type='text', placeholder=env.t('newUsername'), ng-model='changeUser.newUsername', required)
|
||||
input.form-control(type='text', placeholder=env.t('newUsername'), ng-model='usernameUpdates.username', required)
|
||||
.form-group
|
||||
input.form-control(type='password', placeholder=env.t('password'), ng-model='changeUser.password', required)
|
||||
input.btn.btn-default(type='submit', value=env.t('submit'))
|
||||
input.form-control(type='password', placeholder=env.t('password'), ng-model='usernameUpdates.password', required)
|
||||
input.btn.btn-default(type='submit', ng-disabled='changeUsername.$invalid', value=env.t('submit'))
|
||||
|
||||
h5=env.t('changeEmail')
|
||||
form(ng-submit='changeUser("email", emailUpdates)', ng-show='user.auth.local', name='changeEmail', novalidate)
|
||||
.form-group
|
||||
input.form-control(type='text', placeholder=env.t('newEmail'), ng-model='emailUpdates.email', required)
|
||||
.form-group
|
||||
input.form-control(type='password', placeholder=env.t('password'), ng-model='emailUpdates.password', required)
|
||||
input.btn.btn-default(type='submit', ng-disabled='changeEmail.$invalid', value=env.t('submit'))
|
||||
|
||||
h5=env.t('changePass')
|
||||
form(ng-submit='changePassword(changePass)', ng-show='user.auth.local')
|
||||
form(ng-submit='changeUser("password", passwordUpdates)', ng-show='user.auth.local', name='changePassword', novalidate)
|
||||
.form-group
|
||||
input.form-control(type='password', placeholder=env.t('oldPass'), ng-model='changePass.oldPassword', required)
|
||||
input.form-control(type='password', placeholder=env.t('oldPass'), ng-model='passwordUpdates.oldPassword', required)
|
||||
.form-group
|
||||
input.form-control(type='password', placeholder=env.t('newPass'), ng-model='changePass.newPassword', required)
|
||||
input.form-control(type='password', placeholder=env.t('newPass'), ng-model='passwordUpdates.newPassword', required)
|
||||
.form-group
|
||||
input.form-control(type='password', placeholder=env.t('confirmPass'), ng-model='changePass.confirmNewPassword', required)
|
||||
input.btn.btn-default(type='submit', value=env.t('submit'))
|
||||
input.form-control(type='password', placeholder=env.t('confirmPass'), ng-model='passwordUpdates.confirmNewPassword', required)
|
||||
input.btn.btn-default(type='submit', ng-disabled='changePassword.$invalid', value=env.t('submit'))
|
||||
|
||||
|
||||
.panel.panel-default
|
||||
|
||||
Reference in New Issue
Block a user