v1.18.x
barisusakli 9 years ago
parent 36bfe30425
commit 7854e67b7b

@ -29,6 +29,9 @@
"chat": "Chatting with %1",
"account/edit": "Editing \"%1\"",
"account/edit/password": "Editing password of \"%1\"",
"account/edit/username": "Editing username of \"%1\"",
"account/edit/email": "Editing email of \"%1\"",
"account/following": "People %1 follows",
"account/followers": "People who follow %1",
"account/posts": "Posts made by %1",

@ -39,6 +39,8 @@
"profile_update_success": "Profile has been updated successfully!",
"change_picture": "Change Picture",
"change_username": "Change Username",
"change_email": "Change Email",
"edit": "Edit",
"uploaded_picture": "Uploaded Picture",
"upload_new_picture": "Upload New Picture",

@ -1,13 +1,12 @@
'use strict';
/* globals define, ajaxify, socket, app, config, utils, bootbox */
/* globals define, ajaxify, socket, app, config, templates, bootbox */
define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'], function(header, uploader, translator) {
var AccountEdit = {},
gravatarPicture = '',
uploadedPicture = '',
selectedImageType = '',
currentEmail;
selectedImageType = '';
AccountEdit.init = function() {
gravatarPicture = ajaxify.data.gravatarpicture;
@ -25,12 +24,9 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
});
});
currentEmail = $('#inputEmail').val();
handleImageChange();
handleAccountDelete();
handleEmailConfirm();
handlePasswordChange();
updateSignature();
updateAboutMe();
};
@ -38,8 +34,6 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
function updateProfile() {
var userData = {
uid: $('#inputUID').val(),
username: $('#inputUsername').val(),
email: $('#inputEmail').val(),
fullname: $('#inputFullname').val(),
website: $('#inputWebsite').val(),
birthday: $('#inputBirthday').val(),
@ -64,27 +58,13 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
gravatarPicture = data.gravatarpicture;
}
if (data.userslug) {
var oldslug = $('.account-username-box').attr('data-userslug');
$('.account-username-box a').each(function() {
$(this).attr('href', $(this).attr('href').replace(oldslug, data.userslug));
});
$('.account-username-box').attr('data-userslug', data.userslug);
}
if (currentEmail !== data.email) {
currentEmail = data.email;
$('#confirm-email').removeClass('hide');
}
updateHeader(data.picture, userData.username, data.userslug);
updateHeader(data.picture);
});
return false;
}
function updateHeader(picture, username, userslug) {
function updateHeader(picture) {
require(['components'], function(components) {
if (parseInt(ajaxify.data.theirid, 10) !== parseInt(ajaxify.data.yourid, 10)) {
return;
@ -93,11 +73,6 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
if (picture) {
components.get('header/userpicture').attr('src', picture);
}
if (username && userslug) {
components.get('header/profilelink').attr('href', config.relative_path + '/user/' + userslug);
components.get('header/username').text(username);
}
});
}
@ -282,88 +257,6 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
});
}
function handlePasswordChange() {
var currentPassword = $('#inputCurrentPassword');
var password_notify = $('#password-notify');
var password_confirm_notify = $('#password-confirm-notify');
var password = $('#inputNewPassword');
var password_confirm = $('#inputNewPasswordAgain');
var passwordvalid = false;
var passwordsmatch = false;
function onPasswordChanged() {
if (password.val().length < config.minimumPasswordLength) {
showError(password_notify, '[[user:change_password_error_length]]');
passwordvalid = false;
} else if (!utils.isPasswordValid(password.val())) {
showError(password_notify, '[[user:change_password_error]]');
passwordvalid = false;
} else {
showSuccess(password_notify);
passwordvalid = true;
}
}
function onPasswordConfirmChanged() {
if (password.val() !== password_confirm.val()) {
showError(password_confirm_notify, '[[user:change_password_error_match]]');
passwordsmatch = false;
} else {
if (password.val()) {
showSuccess(password_confirm_notify);
} else {
password_confirm_notify.parent().removeClass('alert-success alert-danger');
password_confirm_notify.children().show();
password_confirm_notify.find('.msg').html('');
}
passwordsmatch = true;
}
}
password.on('blur', onPasswordChanged);
password_confirm.on('blur', onPasswordConfirmChanged);
$('#changePasswordBtn').on('click', function() {
onPasswordChanged();
onPasswordConfirmChanged();
var btn = $(this);
if ((passwordvalid && passwordsmatch) || app.user.isAdmin) {
btn.addClass('disabled').find('i').removeClass('hide');
socket.emit('user.changePassword', {
'currentPassword': currentPassword.val(),
'newPassword': password.val(),
'uid': ajaxify.data.theirid
}, function(err) {
btn.removeClass('disabled').find('i').addClass('hide');
currentPassword.val('');
password.val('');
password_confirm.val('');
passwordsmatch = false;
passwordvalid = false;
if (err) {
onPasswordChanged();
onPasswordConfirmChanged();
return app.alertError(err.message);
}
app.alertSuccess('[[user:change_password_success]]');
});
} else {
if (!passwordsmatch) {
app.alertError('[[user:change_password_error_match]]');
}
if (!passwordvalid) {
app.alertError('[[user:change_password_error]]');
}
}
return false;
});
}
function changeUserPicture(type, callback) {
socket.emit('user.changePicture', {
type: type,
@ -393,24 +286,6 @@ define('forum/account/edit', ['forum/account/header', 'uploader', 'translator'],
});
}
function showError(element, msg) {
translator.translate(msg, function(msg) {
element.find('.error').html(msg).removeClass('hide').siblings().addClass('hide');
element.parent()
.removeClass('alert-success')
.addClass('alert-danger');
element.show();
});
}
function showSuccess(element) {
element.find('.success').removeClass('hide').siblings().addClass('hide');
element.parent()
.removeClass('alert-danger')
.addClass('alert-success');
element.show();
}
return AccountEdit;
});

@ -0,0 +1,39 @@
'use strict';
/* globals define, ajaxify, socket, app */
define('forum/account/edit/email', ['forum/account/header'], function(header) {
var AccountEditEmail = {};
AccountEditEmail.init = function() {
header.init();
$('#submitBtn').on('click', function () {
var userData = {
uid: $('#inputUID').val(),
email: $('#inputNewEmail').val(),
password: $('#inputCurrentPassword').val()
};
if (!userData.email) {
return;
}
var btn = $(this);
btn.addClass('disabled').find('i').removeClass('hide');
socket.emit('user.changeUsernameEmail', userData, function(err) {
btn.removeClass('disabled').find('i').addClass('hide');
if (err) {
return app.alertError(err.message);
}
ajaxify.go('user/' + ajaxify.data.userslug);
});
return false;
});
};
return AccountEditEmail;
});

@ -0,0 +1,116 @@
'use strict';
/* globals define, ajaxify, socket, app, config, utils */
define('forum/account/edit/password', ['forum/account/header', 'translator'], function(header, translator) {
var AccountEditPassword = {};
AccountEditPassword.init = function() {
header.init();
handlePasswordChange();
};
function handlePasswordChange() {
var currentPassword = $('#inputCurrentPassword');
var password_notify = $('#password-notify');
var password_confirm_notify = $('#password-confirm-notify');
var password = $('#inputNewPassword');
var password_confirm = $('#inputNewPasswordAgain');
var passwordvalid = false;
var passwordsmatch = false;
function onPasswordChanged() {
if (password.val().length < config.minimumPasswordLength) {
showError(password_notify, '[[user:change_password_error_length]]');
passwordvalid = false;
} else if (!utils.isPasswordValid(password.val())) {
showError(password_notify, '[[user:change_password_error]]');
passwordvalid = false;
} else {
showSuccess(password_notify);
passwordvalid = true;
}
}
function onPasswordConfirmChanged() {
if (password.val() !== password_confirm.val()) {
showError(password_confirm_notify, '[[user:change_password_error_match]]');
passwordsmatch = false;
} else {
if (password.val()) {
showSuccess(password_confirm_notify);
} else {
password_confirm_notify.parent().removeClass('alert-success alert-danger');
password_confirm_notify.children().show();
password_confirm_notify.find('.msg').html('');
}
passwordsmatch = true;
}
}
password.on('blur', onPasswordChanged);
password_confirm.on('blur', onPasswordConfirmChanged);
$('#changePasswordBtn').on('click', function() {
onPasswordChanged();
onPasswordConfirmChanged();
var btn = $(this);
if ((passwordvalid && passwordsmatch) || app.user.isAdmin) {
btn.addClass('disabled').find('i').removeClass('hide');
socket.emit('user.changePassword', {
'currentPassword': currentPassword.val(),
'newPassword': password.val(),
'uid': ajaxify.data.theirid
}, function(err) {
btn.removeClass('disabled').find('i').addClass('hide');
currentPassword.val('');
password.val('');
password_confirm.val('');
passwordsmatch = false;
passwordvalid = false;
if (err) {
onPasswordChanged();
onPasswordConfirmChanged();
return app.alertError(err.message);
}
ajaxify.go('user/' + ajaxify.data.userslug);
app.alertSuccess('[[user:change_password_success]]');
});
} else {
if (!passwordsmatch) {
app.alertError('[[user:change_password_error_match]]');
}
if (!passwordvalid) {
app.alertError('[[user:change_password_error]]');
}
}
return false;
});
}
function showError(element, msg) {
translator.translate(msg, function(msg) {
element.find('.error').html(msg).removeClass('hide').siblings().addClass('hide');
element.parent()
.removeClass('alert-success')
.addClass('alert-danger');
element.show();
});
}
function showSuccess(element) {
element.find('.success').removeClass('hide').siblings().addClass('hide');
element.parent()
.removeClass('alert-danger')
.addClass('alert-success');
element.show();
}
return AccountEditPassword;
});

@ -0,0 +1,43 @@
'use strict';
/* globals define, ajaxify, socket, app, utils, config */
define('forum/account/edit/username', ['forum/account/header'], function(header) {
var AccountEditUsername = {};
AccountEditUsername.init = function() {
header.init();
$('#submitBtn').on('click', function updateUsername() {
var userData = {
uid: $('#inputUID').val(),
username: $('#inputNewUsername').val(),
password: $('#inputCurrentPassword').val()
};
if (!userData.username) {
return;
}
var btn = $(this);
btn.addClass('disabled').find('i').removeClass('hide');
socket.emit('user.changeUsernameEmail', userData, function(err) {
btn.removeClass('disabled').find('i').addClass('hide');
if (err) {
return app.alertError(err.message);
}
var userslug = utils.slugify(userData.username);
if (userData.username && userslug && parseInt(userData.uid, 10) === parseInt(app.user.uid, 10)) {
$('[component="header/profilelink"]').attr('href', config.relative_path + '/user/' + userslug);
$('[component="header/username"]').text(userData.username);
}
ajaxify.go('user/' + userslug);
});
return false;
});
};
return AccountEditUsername;
});

@ -14,6 +14,48 @@ var async = require('async'),
var editController = {};
editController.get = function(req, res, callback) {
accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, function(err, userData) {
if (err || !userData) {
return callback(err);
}
userData.title = '[[pages:account/edit, ' + userData.username + ']]';
userData.breadcrumbs = helpers.buildBreadcrumbs([{text: userData.username, url: '/user/' + userData.userslug}, {text: '[[user:edit]]'}]);
res.render('account/edit', userData);
});
};
editController.password = function(req, res, next) {
renderRoute('password', req, res, next);
};
editController.username = function(req, res, next) {
renderRoute('username', req, res, next);
};
editController.email = function(req, res, next) {
renderRoute('email', req, res, next);
};
function renderRoute(name, req, res, next) {
getUserData(req, next, function(err, userData) {
if (err) {
return next(err);
}
userData.title = '[[pages:account/edit/' + name + ', ' + userData.username + ']]';
userData.breadcrumbs = helpers.buildBreadcrumbs([
{text: userData.username, url: '/user/' + userData.userslug},
{text: '[[user:edit]]', url: '/user/' + userData.userslug + '/edit'},
{text: '[[user:' + name + ']]'}
]);
res.render('account/edit/' + name, userData);
});
}
function getUserData(req, next, callback) {
var userData;
async.waterfall([
function(next) {
@ -22,7 +64,7 @@ editController.get = function(req, res, callback) {
function(data, next) {
userData = data;
if (!userData) {
return callback();
return next();
}
db.getObjectField('user:' + userData.uid, 'password', next);
}
@ -33,13 +75,9 @@ editController.get = function(req, res, callback) {
userData['username:disableEdit'] = parseInt(meta.config['username:disableEdit'], 10) === 1;
userData.hasPassword = !!password;
userData.title = '[[pages:account/edit, ' + userData.username + ']]';
userData.breadcrumbs = helpers.buildBreadcrumbs([{text: userData.username, url: '/user/' + userData.userslug}, {text: '[[user:edit]]'}]);
res.render('account/edit', userData);
callback(null, userData);
});
};
}
editController.uploadPicture = function (req, res, next) {
var userPhoto = req.files.files[0];

@ -17,6 +17,9 @@ module.exports = function (app, middleware, controllers) {
setupPageRoute(app, '/user/:userslug/favourites', middleware, accountMiddlewares, controllers.accounts.posts.getFavourites);
setupPageRoute(app, '/user/:userslug/watched', middleware, accountMiddlewares, controllers.accounts.posts.getWatchedTopics);
setupPageRoute(app, '/user/:userslug/edit', middleware, accountMiddlewares, controllers.accounts.edit.get);
setupPageRoute(app, '/user/:userslug/edit/username', middleware, accountMiddlewares, controllers.accounts.edit.username);
setupPageRoute(app, '/user/:userslug/edit/email', middleware, accountMiddlewares, controllers.accounts.edit.email);
setupPageRoute(app, '/user/:userslug/edit/password', middleware, accountMiddlewares, controllers.accounts.edit.password);
setupPageRoute(app, '/user/:userslug/settings', middleware, accountMiddlewares, controllers.accounts.settings.get);
setupPageRoute(app, '/notifications', middleware, [middleware.authenticate], controllers.accounts.notifications.get);

@ -116,19 +116,6 @@ SocketUser.reset.commit = function(socket, data, callback) {
});
};
SocketUser.isAdminOrSelf = function(socket, uid, callback) {
if (socket.uid === parseInt(uid, 10)) {
return callback();
}
user.isAdministrator(socket.uid, function(err, isAdmin) {
if (err || !isAdmin) {
return callback(err || new Error('[[error:no-privileges]]'));
}
callback();
});
};
SocketUser.follow = function(socket, data, callback) {
if (!socket.uid || !data) {
return;
@ -182,7 +169,7 @@ SocketUser.saveSettings = function(socket, data, callback) {
return callback(new Error('[[error:invalid-data]]'));
}
SocketUser.isAdminOrSelf(socket, data.uid, function(err) {
user.isAdminOrSelf(socket.uid, data.uid, function(err) {
if (err) {
return callback(err);
}

@ -28,7 +28,7 @@ module.exports = function(SocketUser) {
async.waterfall([
function (next) {
SocketUser.isAdminOrSelf(socket, data.uid, next);
user.isAdminOrSelf(socket.uid, data.uid, next);
},
function (next) {
user.getUserField(data.uid, type, next);
@ -44,7 +44,7 @@ module.exports = function(SocketUser) {
return;
}
SocketUser.isAdminOrSelf(socket, data.uid, function(err) {
user.isAdminOrSelf(socket.uid, data.uid, function(err) {
if (err) {
return callback(err);
}
@ -61,7 +61,7 @@ module.exports = function(SocketUser) {
async.waterfall([
function (next) {
SocketUser.isAdminOrSelf(socket, data.uid, next);
user.isAdminOrSelf(socket.uid, data.uid, next);
},
function (next) {
user.getUserField(data.uid, 'uploadedpicture', next);

@ -8,6 +8,47 @@ var events = require('../../events');
module.exports = function(SocketUser) {
SocketUser.changeUsernameEmail = function(socket, data, callback) {
if (!data || !data.uid || !socket.uid) {
return callback(new Error('[[error:invalid-data]]'));
}
async.waterfall([
function (next) {
isAdminOrSelfAndPasswordMatch(socket.uid, data, next);
},
function (next) {
SocketUser.updateProfile(socket, data, next);
}
], callback);
};
function isAdminOrSelfAndPasswordMatch(uid, data, callback) {
async.parallel({
isAdmin: function(next) {
user.isAdministrator(uid, next);
},
passwordMatch: function(next) {
user.isPasswordCorrect(data.uid, data.password, next);
}
}, function(err, results) {
if (err) {
return callback(err);
}
var self = parseInt(uid, 10) === parseInt(data.uid, 10);
if (!results.isAdmin && !self) {
return callback(new Error('[[error:no-privileges]]'));
}
if (self && !results.passwordMatch) {
return callback(new Error('[[error:invalid-password]]'));
}
callback();
});
}
SocketUser.changePassword = function(socket, data, callback) {
if (!data || !data.uid || data.newPassword.length < meta.config.minimumPasswordLength) {
return callback(new Error('[[error:invalid-data]]'));
@ -31,7 +72,6 @@ module.exports = function(SocketUser) {
});
};
SocketUser.updateProfile = function(socket, data, callback) {
if (!socket.uid) {
return callback('[[error:invalid-uid]]');
@ -55,9 +95,10 @@ module.exports = function(SocketUser) {
if (parseInt(meta.config['username:disableEdit'], 10) === 1) {
data.username = oldUserData.username;
}
SocketUser.isAdminOrSelf(socket, data.uid, next);
user.isAdminOrSelf(socket.uid, data.uid, next);
},
function (next) {
console.log('updating profile', data)
user.updateProfile(data.uid, data, next);
},
function (userData, next) {

@ -3,14 +3,11 @@
var async = require('async'),
nconf = require('nconf'),
gravatar = require('gravatar'),
validator = require('validator'),
plugins = require('./plugins'),
db = require('./database'),
meta = require('./meta'),
topics = require('./topics'),
groups = require('./groups'),
Password = require('./password'),
privileges = require('./privileges'),
utils = require('../public/src/utils');
@ -36,6 +33,7 @@ var async = require('async'),
require('./user/picture')(User);
require('./user/approval')(User);
require('./user/invite')(User);
require('./user/password')(User);
User.updateLastOnlineTime = function(uid, callback) {
callback = callback || function() {};
@ -160,14 +158,6 @@ var async = require('async'),
return gravatar.url(email, options, true);
};
User.hashPassword = function(password, callback) {
if (!password) {
return callback(null, password);
}
Password.hash(nconf.get('bcrypt_rounds') || 12, password, callback);
};
User.exists = function(uid, callback) {
db.isSortedSetMember('users:joindate', uid, callback);
};
@ -176,7 +166,7 @@ var async = require('async'),
User.getUidByUserslug(userslug, function(err, exists) {
callback(err, !! exists);
});
}
};
User.getUidByUsername = function(username, callback) {
if (!username) {
@ -242,6 +232,18 @@ var async = require('async'),
privileges.users.isAdministrator(uid, callback);
};
User.isAdminOrSelf = function(callerUid, uid, callback) {
if (parseInt(callerUid, 10) === parseInt(uid, 10)) {
return callback();
}
User.isAdministrator(callerUid, function(err, isAdmin) {
if (err || !isAdmin) {
return callback(err || new Error('[[error:no-privileges]]'));
}
callback();
});
};
}(exports));

@ -0,0 +1,28 @@
'use strict';
var nconf = require('nconf');
var db = require('../database');
var Password = require('../password');
module.exports = function(User) {
User.hashPassword = function(password, callback) {
if (!password) {
return callback(null, password);
}
Password.hash(nconf.get('bcrypt_rounds') || 12, password, callback);
};
User.isPasswordCorrect = function(uid, password, callback) {
db.getObjectField('user:' + uid, 'password', function(err, hashedPassword) {
if (err || !hashedPassword) {
return callback(err);
}
Password.compare(password || '', hashedPassword, callback);
});
};
};

@ -273,30 +273,21 @@ module.exports = function(User) {
return callback(new Error('[[user:change_password_error]]'));
}
if(parseInt(uid, 10) !== parseInt(data.uid, 10)) {
if (parseInt(uid, 10) !== parseInt(data.uid, 10)) {
User.isAdministrator(uid, function(err, isAdmin) {
if(err || !isAdmin) {
if (err || !isAdmin) {
return callback(err || new Error('[[user:change_password_error_privileges'));
}
hashAndSetPassword(callback);
});
} else {
db.getObjectField('user:' + uid, 'password', function(err, currentPassword) {
if(err) {
return callback(err);
}
if (!currentPassword) {
return hashAndSetPassword(callback);
User.isPasswordCorrect(uid, data.currentPassword, function(err, correct) {
if (err || !correct) {
return callback(err || new Error('[[user:change_password_error_wrong_current]]'));
}
Password.compare(data.currentPassword, currentPassword, function(err, res) {
if (err || !res) {
return callback(err || new Error('[[user:change_password_error_wrong_current]]'));
}
hashAndSetPassword(callback);
});
hashAndSetPassword(callback);
});
}
};

Loading…
Cancel
Save