breaking: remove socket.emit('user.changeUsernameEmail')

remove socket.emit('user.changePassword')
remove socket.emit('user.updateProfile')
isekai-main
Barış Soner Uşaklı 4 years ago
parent cc0a087a70
commit 6b45dee9c5

@ -44,7 +44,7 @@ usersAPI.update = async function (caller, data) {
]); ]);
// Changing own email/username requires password confirmation // Changing own email/username requires password confirmation
if (['email', 'username'].some(prop => Object.keys(data).includes(prop))) { if (data.hasOwnProperty('email') || data.hasOwnProperty('username')) {
await isPrivilegedOrSelfAndPasswordMatch(caller, data); await isPrivilegedOrSelfAndPasswordMatch(caller, data);
} }
@ -63,16 +63,15 @@ usersAPI.update = async function (caller, data) {
await user.updateProfile(caller.uid, data); await user.updateProfile(caller.uid, data);
const userData = await user.getUserData(data.uid); const userData = await user.getUserData(data.uid);
async function log(type, eventData) {
eventData.type = type;
eventData.uid = caller.uid;
eventData.targetUid = data.uid;
eventData.ip = caller.ip;
await events.log(eventData);
}
if (userData.username !== oldUserData.username) { if (userData.username !== oldUserData.username) {
await log('username-change', { oldUsername: oldUserData.username, newUsername: userData.username }); await events.log({
type: 'username-change',
uid: caller.uid,
targetUid: data.uid,
ip: caller.ip,
oldUsername: oldUserData.username,
newUsername: userData.username,
});
} }
return userData; return userData;
}; };

@ -2,26 +2,14 @@
const winston = require('winston'); const winston = require('winston');
const api = require('../../api');
const user = require('../../user'); const user = require('../../user');
const events = require('../../events'); const events = require('../../events');
const notifications = require('../../notifications'); const notifications = require('../../notifications');
const privileges = require('../../privileges'); const privileges = require('../../privileges');
const db = require('../../database'); const db = require('../../database');
const plugins = require('../../plugins'); const plugins = require('../../plugins');
const sockets = require('..');
module.exports = function (SocketUser) { module.exports = function (SocketUser) {
SocketUser.changeUsernameEmail = async function (socket, data) {
sockets.warnDeprecated(socket, 'PUT /api/v3/users/:uid');
if (!data || !data.uid || !socket.uid) {
throw new Error('[[error:invalid-data]]');
}
await isPrivilegedOrSelfAndPasswordMatch(socket, data);
return await SocketUser.updateProfile(socket, data);
};
SocketUser.updateCover = async function (socket, data) { SocketUser.updateCover = async function (socket, data) {
if (!socket.uid) { if (!socket.uid) {
throw new Error('[[error:no-privileges]]'); throw new Error('[[error:no-privileges]]');
@ -56,39 +44,6 @@ module.exports = function (SocketUser) {
}); });
}; };
async function isPrivilegedOrSelfAndPasswordMatch(socket, data) {
const { uid } = socket;
const isSelf = parseInt(uid, 10) === parseInt(data.uid, 10);
const [isAdmin, isTargetAdmin, isGlobalMod] = await Promise.all([
user.isAdministrator(uid),
user.isAdministrator(data.uid),
user.isGlobalModerator(uid),
]);
if ((isTargetAdmin && !isAdmin) || (!isSelf && !(isAdmin || isGlobalMod))) {
throw new Error('[[error:no-privileges]]');
}
const [hasPassword, passwordMatch] = await Promise.all([
user.hasPassword(data.uid),
data.password ? user.isPasswordCorrect(data.uid, data.password, socket.ip) : false,
]);
if (isSelf && hasPassword && !passwordMatch) {
throw new Error('[[error:invalid-password]]');
}
}
SocketUser.changePassword = async function (socket, data) {
sockets.warnDeprecated(socket, 'PUT /api/v3/users/:uid/password');
await api.users.changePassword(socket, data);
};
SocketUser.updateProfile = async function (socket, data) {
sockets.warnDeprecated(socket, 'PUT /api/v3/users/:uid');
return await api.users.update(socket, data);
};
SocketUser.toggleBlock = async function (socket, data) { SocketUser.toggleBlock = async function (socket, data) {
const [is] = await Promise.all([ const [is] = await Promise.all([
user.blocks.is(data.blockeeUid, data.blockerUid), user.blocks.is(data.blockeeUid, data.blockerUid),

@ -799,15 +799,6 @@ describe('User', () => {
}); });
}); });
describe('not logged in', () => {
it('should return error if not logged in', (done) => {
socketUser.updateProfile({ uid: 0 }, { uid: 1 }, (err) => {
assert.equal(err.message, '[[error:invalid-uid]]');
done();
});
});
});
describe('profile methods', () => { describe('profile methods', () => {
let uid; let uid;
let jar; let jar;
@ -821,28 +812,38 @@ describe('User', () => {
({ jar } = await helpers.loginUser('updateprofile', '123456')); ({ jar } = await helpers.loginUser('updateprofile', '123456'));
}); });
it('should return error if data is invalid', (done) => { it('should return error if not logged in', async () => {
socketUser.updateProfile({ uid: uid }, null, (err) => { try {
assert.equal(err.message, '[[error:invalid-data]]'); await apiUser.update({ uid: 0 }, { uid: 1 });
done(); assert(false);
}); } catch (err) {
assert.equal(err.message, '[[error:invalid-uid]]');
}
}); });
it('should return error if data is missing uid', (done) => { it('should return error if data is invalid', async () => {
socketUser.updateProfile({ uid: uid }, { username: 'bip', email: 'bop' }, (err) => { try {
await apiUser.update({ uid: uid }, null);
assert(false);
} catch (err) {
assert.equal(err.message, '[[error:invalid-data]]'); assert.equal(err.message, '[[error:invalid-data]]');
done(); }
}); });
it('should return error if data is missing uid', async () => {
try {
await apiUser.update({ uid: uid }, { username: 'bip', email: 'bop' });
assert(false);
} catch (err) {
assert.equal(err.message, '[[error:invalid-data]]');
}
}); });
describe('.updateProfile()', () => { describe('.updateProfile()', () => {
let uid; let uid;
it('should update a user\'s profile', (done) => { it('should update a user\'s profile', async () => {
User.create({ username: 'justforupdate', email: 'just@for.updated', password: '123456' }, (err, _uid) => { uid = await User.create({ username: 'justforupdate', email: 'just@for.updated', password: '123456' });
uid = _uid;
assert.ifError(err);
const data = { const data = {
uid: uid, uid: uid,
username: 'updatedUserName', username: 'updatedUserName',
@ -855,15 +856,12 @@ describe('User', () => {
signature: 'nodebb is good', signature: 'nodebb is good',
password: '123456', password: '123456',
}; };
socketUser.updateProfile({ uid: uid }, { ...data, password: '123456', invalid: 'field' }, (err, result) => { const result = await apiUser.update({ uid: uid }, { ...data, password: '123456', invalid: 'field' });
assert.ifError(err);
assert.equal(result.username, 'updatedUserName'); assert.equal(result.username, 'updatedUserName');
assert.equal(result.userslug, 'updatedusername'); assert.equal(result.userslug, 'updatedusername');
assert.equal(result.location, 'izmir'); assert.equal(result.location, 'izmir');
db.getObject(`user:${uid}`, (err, userData) => { const userData = await db.getObject(`user:${uid}`);
assert.ifError(err);
Object.keys(data).forEach((key) => { Object.keys(data).forEach((key) => {
if (key === 'email') { if (key === 'email') {
assert.strictEqual(userData.email, 'just@for.updated'); // email remains the same until confirmed assert.strictEqual(userData.email, 'just@for.updated'); // email remains the same until confirmed
@ -875,10 +873,6 @@ describe('User', () => {
}); });
// updateProfile only saves valid fields // updateProfile only saves valid fields
assert.strictEqual(userData.invalid, undefined); assert.strictEqual(userData.invalid, undefined);
done();
});
});
});
}); });
it('should also generate an email confirmation code for the changed email', async () => { it('should also generate an email confirmation code for the changed email', async () => {
@ -887,44 +881,34 @@ describe('User', () => {
}); });
}); });
it('should change a user\'s password', (done) => { it('should change a user\'s password', async () => {
User.create({ username: 'changepassword', password: '123456' }, (err, uid) => { const uid = await User.create({ username: 'changepassword', password: '123456' });
assert.ifError(err); await apiUser.changePassword({ uid: uid }, { uid: uid, newPassword: '654321', currentPassword: '123456' });
socketUser.changePassword({ uid: uid }, { uid: uid, newPassword: '654321', currentPassword: '123456' }, (err) => { const correct = await User.isPasswordCorrect(uid, '654321', '127.0.0.1');
assert.ifError(err);
User.isPasswordCorrect(uid, '654321', '127.0.0.1', (err, correct) => {
assert.ifError(err);
assert(correct); assert(correct);
done();
});
});
});
}); });
it('should not let user change another user\'s password', async () => { it('should not let user change another user\'s password', async () => {
const regularUserUid = await User.create({ username: 'regularuserpwdchange', password: 'regularuser1234' }); const regularUserUid = await User.create({ username: 'regularuserpwdchange', password: 'regularuser1234' });
const uid = await User.create({ username: 'changeadminpwd1', password: '123456' }); const uid = await User.create({ username: 'changeadminpwd1', password: '123456' });
let err;
try { try {
await socketUser.changePassword({ uid: uid }, { uid: regularUserUid, newPassword: '654321', currentPassword: '123456' }); await apiUser.changePassword({ uid: uid }, { uid: regularUserUid, newPassword: '654321', currentPassword: '123456' });
} catch (_err) { assert(false);
err = _err; } catch (err) {
}
assert.equal(err.message, '[[user:change_password_error_privileges]]'); assert.equal(err.message, '[[user:change_password_error_privileges]]');
}
}); });
it('should not let user change admin\'s password', async () => { it('should not let user change admin\'s password', async () => {
const adminUid = await User.create({ username: 'adminpwdchange', password: 'admin1234' }); const adminUid = await User.create({ username: 'adminpwdchange', password: 'admin1234' });
await groups.join('administrators', adminUid); await groups.join('administrators', adminUid);
const uid = await User.create({ username: 'changeadminpwd2', password: '123456' }); const uid = await User.create({ username: 'changeadminpwd2', password: '123456' });
let err;
try { try {
await socketUser.changePassword({ uid: uid }, { uid: adminUid, newPassword: '654321', currentPassword: '123456' }); await apiUser.changePassword({ uid: uid }, { uid: adminUid, newPassword: '654321', currentPassword: '123456' });
} catch (_err) { assert(false);
err = _err; } catch (err) {
}
assert.equal(err.message, '[[user:change_password_error_privileges]]'); assert.equal(err.message, '[[user:change_password_error_privileges]]');
}
}); });
it('should let admin change another users password', async () => { it('should let admin change another users password', async () => {
@ -932,7 +916,7 @@ describe('User', () => {
await groups.join('administrators', adminUid); await groups.join('administrators', adminUid);
const uid = await User.create({ username: 'forgotmypassword', password: '123456' }); const uid = await User.create({ username: 'forgotmypassword', password: '123456' });
await socketUser.changePassword({ uid: adminUid }, { uid: uid, newPassword: '654321' }); await apiUser.changePassword({ uid: adminUid }, { uid: uid, newPassword: '654321' });
const correct = await User.isPasswordCorrect(uid, '654321', '127.0.0.1'); const correct = await User.isPasswordCorrect(uid, '654321', '127.0.0.1');
assert(correct); assert(correct);
}); });
@ -941,28 +925,22 @@ describe('User', () => {
const adminUid = await User.create({ username: 'adminforgotpwd', password: 'admin1234' }); const adminUid = await User.create({ username: 'adminforgotpwd', password: 'admin1234' });
await groups.join('administrators', adminUid); await groups.join('administrators', adminUid);
let err;
try { try {
await socketUser.changePassword({ uid: adminUid }, { uid: adminUid, newPassword: '654321', currentPassword: 'wrongpwd' }); await apiUser.changePassword({ uid: adminUid }, { uid: adminUid, newPassword: '654321', currentPassword: 'wrongpwd' });
} catch (_err) { assert(false);
err = _err; } catch (err) {
}
assert.equal(err.message, '[[user:change_password_error_wrong_current]]'); assert.equal(err.message, '[[user:change_password_error_wrong_current]]');
}
}); });
it('should change username', (done) => { it('should change username', async () => {
socketUser.changeUsernameEmail({ uid: uid }, { uid: uid, username: 'updatedAgain', password: '123456' }, (err) => { await apiUser.update({ uid: uid }, { uid: uid, username: 'updatedAgain', password: '123456' });
assert.ifError(err); const username = await db.getObjectField(`user:${uid}`, 'username');
db.getObjectField(`user:${uid}`, 'username', (err, username) => {
assert.ifError(err);
assert.equal(username, 'updatedAgain'); assert.equal(username, 'updatedAgain');
done();
});
});
}); });
it('should not let setting an empty username', async () => { it('should not let setting an empty username', async () => {
await socketUser.changeUsernameEmail({ uid: uid }, { uid: uid, username: '', password: '123456' }); await apiUser.update({ uid: uid }, { uid: uid, username: '', password: '123456' });
const username = await db.getObjectField(`user:${uid}`, 'username'); const username = await db.getObjectField(`user:${uid}`, 'username');
assert.strictEqual(username, 'updatedAgain'); assert.strictEqual(username, 'updatedAgain');
}); });
@ -971,7 +949,7 @@ describe('User', () => {
const maxLength = meta.config.maximumUsernameLength + 1; const maxLength = meta.config.maximumUsernameLength + 1;
const longName = new Array(maxLength).fill('a').join(''); const longName = new Array(maxLength).fill('a').join('');
const uid = await User.create({ username: longName }); const uid = await User.create({ username: longName });
await socketUser.changeUsernameEmail({ uid: uid }, { uid: uid, username: longName, email: 'verylong@name.com' }); await apiUser.update({ uid: uid }, { uid: uid, username: longName, email: 'verylong@name.com' });
const userData = await db.getObject(`user:${uid}`); const userData = await db.getObject(`user:${uid}`);
const awaitingValidation = await User.email.isValidationPending(uid, 'verylong@name.com'); const awaitingValidation = await User.email.isValidationPending(uid, 'verylong@name.com');
@ -979,34 +957,26 @@ describe('User', () => {
assert.strictEqual(awaitingValidation, true); assert.strictEqual(awaitingValidation, true);
}); });
it('should not update a user\'s username if it did not change', (done) => { it('should not update a user\'s username if it did not change', async () => {
socketUser.changeUsernameEmail({ uid: uid }, { uid: uid, username: 'updatedAgain', password: '123456' }, (err) => { await apiUser.update({ uid: uid }, { uid: uid, username: 'updatedAgain', password: '123456' });
assert.ifError(err); const data = await db.getSortedSetRevRange(`user:${uid}:usernames`, 0, -1);
db.getSortedSetRevRange(`user:${uid}:usernames`, 0, -1, (err, data) => {
assert.ifError(err);
assert.equal(data.length, 2); assert.equal(data.length, 2);
assert(data[0].startsWith('updatedAgain')); assert(data[0].startsWith('updatedAgain'));
done();
});
});
}); });
it('should not update a user\'s username if a password is not supplied', async () => { it('should not update a user\'s username if a password is not supplied', async () => {
let _err;
try { try {
await socketUser.updateProfile({ uid: uid }, { uid: uid, username: 'updatedAgain', password: '' }); await apiUser.update({ uid: uid }, { uid: uid, username: 'updatedAgain', password: '' });
assert(false);
} catch (err) { } catch (err) {
_err = err; assert.strictEqual(err.message, '[[error:invalid-password]]');
} }
assert(_err);
assert.strictEqual(_err.message, '[[error:invalid-password]]');
}); });
it('should send validation email', async () => { it('should send validation email', async () => {
const uid = await User.create({ username: 'pooremailupdate', email: 'poor@update.me', password: '123456' }); const uid = await User.create({ username: 'pooremailupdate', email: 'poor@update.me', password: '123456' });
await User.email.expireValidation(uid); await User.email.expireValidation(uid);
await socketUser.changeUsernameEmail({ uid: uid }, { uid: uid, email: 'updatedAgain@me.com', password: '123456' }); await apiUser.update({ uid: uid }, { uid: uid, email: 'updatedAgain@me.com', password: '123456' });
assert.strictEqual(await User.email.isValidationPending(uid), true); assert.strictEqual(await User.email.isValidationPending(uid), true);
}); });

Loading…
Cancel
Save