diff --git a/install/package.json b/install/package.json index e59766f156..db67e3b86b 100644 --- a/install/package.json +++ b/install/package.json @@ -89,7 +89,7 @@ "nodebb-plugin-emoji": "^3.5.0", "nodebb-plugin-emoji-android": "2.0.5", "nodebb-plugin-markdown": "8.14.4", - "nodebb-plugin-mentions": "3.0.1", + "nodebb-plugin-mentions": "3.0.2", "nodebb-plugin-spam-be-gone": "0.7.11", "nodebb-rewards-essentials": "0.2.0", "nodebb-theme-lavender": "5.3.1", diff --git a/src/user/email.js b/src/user/email.js index 85162b8414..d6d2d32b4d 100644 --- a/src/user/email.js +++ b/src/user/email.js @@ -143,6 +143,12 @@ UserEmail.confirmByCode = async function (code, sessionId) { throw new Error('[[error:invalid-data]]'); } + // If another uid has the same email, remove it + const oldUid = await db.sortedSetScore('email:uid', confirmObj.email.toLowerCase()); + if (oldUid) { + await UserEmail.remove(oldUid, sessionId); + } + const oldEmail = await user.getUserField(confirmObj.uid, 'email'); if (oldEmail && confirmObj.email !== oldEmail) { await UserEmail.remove(confirmObj.uid, sessionId); diff --git a/src/user/profile.js b/src/user/profile.js index 2748690b81..a8d1b02d1d 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -71,7 +71,7 @@ module.exports = function (User) { }; async function validateData(callerUid, data) { - await isEmailAvailable(data, data.uid); + await isEmailValid(data); await isUsernameAvailable(data, data.uid); await isWebsiteValid(callerUid, data); await isAboutMeValid(callerUid, data); @@ -82,7 +82,7 @@ module.exports = function (User) { isGroupTitleValid(data); } - async function isEmailAvailable(data, uid) { + async function isEmailValid(data) { if (!data.email) { return; } @@ -91,14 +91,6 @@ module.exports = function (User) { if (!utils.isEmailValid(data.email)) { throw new Error('[[error:invalid-email]]'); } - const email = await User.getUserField(uid, 'email'); - if (email === data.email) { - return; - } - const available = await User.email.available(data.email); - if (!available) { - throw new Error('[[error:email-taken]]'); - } } async function isUsernameAvailable(data, uid) { diff --git a/test/user.js b/test/user.js index e74eb8252d..671cc06d20 100644 --- a/test/user.js +++ b/test/user.js @@ -2462,6 +2462,22 @@ describe('User', () => { assert.strictEqual(parseInt(confirmed, 10), 1); assert.strictEqual(isVerified, true); }); + + it('should remove the email from a different account if the email is already in use', async () => { + const email = 'confirm2@me.com'; + const uid = await User.create({ + username: 'confirme3', + }); + + const oldUid = await db.sortedSetScore('email:uid', email); + const code = await User.email.sendValidationEmail(uid, email); + await User.email.confirmByCode(code); + + const oldUserData = await User.getUserData(oldUid); + + assert.strictEqual((await db.sortedSetScore('email:uid', email)), uid); + assert.strictEqual(oldUserData.email, ''); + }); }); describe('user jobs', () => {