diff --git a/services/web/app/src/Features/User/UserEmailsConfirmationHandler.js b/services/web/app/src/Features/User/UserEmailsConfirmationHandler.js index e44ab27d5f..cefae54e36 100644 --- a/services/web/app/src/Features/User/UserEmailsConfirmationHandler.js +++ b/services/web/app/src/Features/User/UserEmailsConfirmationHandler.js @@ -5,7 +5,7 @@ const settings = require('@overleaf/settings') const Errors = require('../Errors/Errors') const UserUpdater = require('./UserUpdater') const UserGetter = require('./UserGetter') -const { callbackify, promisify } = require('util') +const { callbackify } = require('util') const crypto = require('crypto') const SessionManager = require('../Authentication/SessionManager') @@ -14,33 +14,27 @@ const TOKEN_EXPIRY_IN_S = 90 * 24 * 60 * 60 const TOKEN_USE = 'email_confirmation' const CONFIRMATION_CODE_EXPIRY_IN_S = 10 * 60 -function sendConfirmationEmail(userId, email, emailTemplate, callback) { - if (arguments.length === 3) { - callback = emailTemplate - emailTemplate = 'confirmEmail' - } - +async function sendConfirmationEmail( + userId, + email, + emailTemplate = 'confirmEmail' +) { email = EmailHelper.parseEmail(email) if (!email) { - return callback(new Error('invalid email')) + throw new Error('invalid email') } const data = { user_id: userId, email } - OneTimeTokenHandler.getNewToken( + const token = await OneTimeTokenHandler.promises.getNewToken( TOKEN_USE, data, - { expiresIn: TOKEN_EXPIRY_IN_S }, - function (err, token) { - if (err) { - return callback(err) - } - const emailOptions = { - to: email, - confirmEmailUrl: `${settings.siteUrl}/user/emails/confirm?token=${token}`, - sendingUser_id: userId, - } - EmailHandler.sendEmail(emailTemplate, emailOptions, callback) - } + { expiresIn: TOKEN_EXPIRY_IN_S } ) + const emailOptions = { + to: email, + confirmEmailUrl: `${settings.siteUrl}/user/emails/confirm?token=${token}`, + sendingUser_id: userId, + } + await EmailHandler.promises.sendEmail(emailTemplate, emailOptions) } async function sendConfirmationCode(email, welcomeUser) { @@ -100,12 +94,12 @@ async function confirmEmailFromToken(req, token) { } const UserEmailsConfirmationHandler = { - sendConfirmationEmail, confirmEmailFromToken: callbackify(confirmEmailFromToken), + sendConfirmationEmail: callbackify(sendConfirmationEmail), } UserEmailsConfirmationHandler.promises = { - sendConfirmationEmail: promisify(sendConfirmationEmail), + sendConfirmationEmail, confirmEmailFromToken, sendConfirmationCode, } diff --git a/services/web/test/unit/src/User/UserEmailsConfirmationHandlerTests.js b/services/web/test/unit/src/User/UserEmailsConfirmationHandlerTests.js index f01a1c3250..aa447fd1e4 100644 --- a/services/web/test/unit/src/User/UserEmailsConfirmationHandlerTests.js +++ b/services/web/test/unit/src/User/UserEmailsConfirmationHandlerTests.js @@ -49,7 +49,7 @@ describe('UserEmailsConfirmationHandler', function () { getUser: sinon.stub().resolves(this.mockUser), }, }), - '../Email/EmailHandler': (this.EmailHandler = {}), + '../Email/EmailHandler': (this.EmailHandler = { promises: {} }), '../Helpers/EmailHelper': EmailHelper, '../Authentication/SessionManager': (this.SessionManager = { getLoggedInUserId: sinon.stub().returns(this.mockUser._id), @@ -61,23 +61,22 @@ describe('UserEmailsConfirmationHandler', function () { describe('sendConfirmationEmail', function () { beforeEach(function () { - this.OneTimeTokenHandler.getNewToken = sinon + this.OneTimeTokenHandler.promises.getNewToken = sinon .stub() - .yields(null, (this.token = 'new-token')) - return (this.EmailHandler.sendEmail = sinon.stub().yields()) + .resolves((this.token = 'new-token')) + return (this.EmailHandler.promises.sendEmail = sinon.stub().resolves()) }) describe('successfully', function () { - beforeEach(function () { - return this.UserEmailsConfirmationHandler.sendConfirmationEmail( + beforeEach(async function () { + await this.UserEmailsConfirmationHandler.promises.sendConfirmationEmail( this.user_id, - this.email, - this.callback + this.email ) }) it('should generate a token for the user which references their id and email', function () { - return this.OneTimeTokenHandler.getNewToken + return this.OneTimeTokenHandler.promises.getNewToken .calledWith( 'email_confirmation', { user_id: this.user_id, email: this.email }, @@ -87,7 +86,7 @@ describe('UserEmailsConfirmationHandler', function () { }) it('should send an email to the user', function () { - return this.EmailHandler.sendEmail + return this.EmailHandler.promises.sendEmail .calledWith('confirmEmail', { to: this.email, confirmEmailUrl: @@ -96,40 +95,30 @@ describe('UserEmailsConfirmationHandler', function () { }) .should.equal(true) }) - - it('should call the callback', function () { - return this.callback.called.should.equal(true) - }) }) describe('with invalid email', function () { - beforeEach(function () { - return this.UserEmailsConfirmationHandler.sendConfirmationEmail( - this.user_id, - '!"£$%^&*()', - this.callback - ) - }) - - it('should return an error', function () { - return this.callback - .calledWith(sinon.match.instanceOf(Error)) - .should.equal(true) + it('should reject with an error', async function () { + await expect( + this.UserEmailsConfirmationHandler.promises.sendConfirmationEmail( + this.user_id, + '!"£$%^&*()' + ) + ).to.be.rejectedWith(Error) }) }) describe('a custom template', function () { - beforeEach(function () { - return this.UserEmailsConfirmationHandler.sendConfirmationEmail( + beforeEach(async function () { + await this.UserEmailsConfirmationHandler.promises.sendConfirmationEmail( this.user_id, this.email, - 'myCustomTemplate', - this.callback + 'myCustomTemplate' ) }) it('should send an email with the given template', function () { - return this.EmailHandler.sendEmail + return this.EmailHandler.promises.sendEmail .calledWith('myCustomTemplate') .should.equal(true) })