From 76301e0cc89c3cdeddf8c774093e18c331dd595b Mon Sep 17 00:00:00 2001 From: Antoine Clausse Date: Mon, 17 Feb 2025 16:56:27 +0100 Subject: [PATCH] [web] Send security alert email when secondary is added (#23657) * [web] Send security alert email when secondary is added * [web] Add test: checkSecondaryEmailConfirmationCode - sends a security alert email * Move `_sendSecurityAlertEmail` before `addEmailAddress` GitOrigin-RevId: 8d9c496fffd953871e03d8c7f011c42459eeb0bc --- .../src/Features/User/UserEmailsController.js | 20 +++++++-------- .../src/User/UserEmailsControllerTests.js | 25 +++++++++++++++++++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/services/web/app/src/Features/User/UserEmailsController.js b/services/web/app/src/Features/User/UserEmailsController.js index a119fb0012..44c907e0d0 100644 --- a/services/web/app/src/Features/User/UserEmailsController.js +++ b/services/web/app/src/Features/User/UserEmailsController.js @@ -252,12 +252,12 @@ async function checkSecondaryEmailConfirmationCode(req, res) { }) } + const newSecondaryEmail = req.session.pendingSecondaryEmail.email + try { - await checkSecondaryConfirmCodeRateLimiter.consume( - req.session.pendingSecondaryEmail.email, - 1, - { method: 'email' } - ) + await checkSecondaryConfirmCodeRateLimiter.consume(newSecondaryEmail, 1, { + method: 'email', + }) } catch (err) { if (err?.remainingPoints === 0) { return res.sendStatus(429) @@ -290,14 +290,14 @@ async function checkSecondaryEmailConfirmationCode(req, res) { 'add-email-via-code', userId, req.ip, - { - newSecondaryEmail: req.session.pendingSecondaryEmail.email, - } + { newSecondaryEmail } ) + await _sendSecurityAlertEmail(user, newSecondaryEmail) + await UserUpdater.promises.addEmailAddress( userId, - req.session.pendingSecondaryEmail.email, + newSecondaryEmail, req.session.pendingSecondaryEmail.affiliationOptions, { initiatorId: user._id, @@ -307,7 +307,7 @@ async function checkSecondaryEmailConfirmationCode(req, res) { await UserUpdater.promises.confirmEmail( userId, - req.session.pendingSecondaryEmail.email, + newSecondaryEmail, req.session.pendingSecondaryEmail.affiliationOptions ) diff --git a/services/web/test/unit/src/User/UserEmailsControllerTests.js b/services/web/test/unit/src/User/UserEmailsControllerTests.js index 0513528737..d83f641f44 100644 --- a/services/web/test/unit/src/User/UserEmailsControllerTests.js +++ b/services/web/test/unit/src/User/UserEmailsControllerTests.js @@ -409,6 +409,31 @@ describe('UserEmailsController', function () { } ) }) + + it('sends a security alert email', async function () { + this.req.session.pendingSecondaryEmail = { + confirmCode: '123456', + email: this.newEmail, + confirmCodeExpiresTimestamp: new Date(Math.max), + affiliationOptions: {}, + } + this.req.body.code = '123456' + + await this.UserEmailsController.checkSecondaryEmailConfirmationCode( + this.req, + { + json: sinon.stub().resolves(), + } + ) + + const emailCall = this.EmailHandler.promises.sendEmail.getCall(0) + expect(emailCall.args[0]).to.equal('securityAlert') + expect(emailCall.args[1].to).to.equal(this.user.email) + expect(emailCall.args[1].actionDescribed).to.contain( + 'a secondary email address' + ) + expect(emailCall.args[1].message[0]).to.contain(this.newEmail) + }) }) describe('with an invalid confirmation code', function () {