Merge pull request #3096 from overleaf/jel-security-alert-primary-email

Send security alert email when primary email changed

GitOrigin-RevId: a01f38a2478dc280261b9a43ef1a01751d4601fb
This commit is contained in:
Timothée Alby 2020-08-12 16:19:55 +02:00 committed by Copybot
parent 3babf23444
commit bbf3132a16
3 changed files with 76 additions and 8 deletions

View file

@ -125,13 +125,20 @@ const UserEmailsController = {
initiatorId: userId,
ipAddress: req.ip
}
UserUpdater.setDefaultEmailAddress(userId, email, false, auditLog, err => {
if (err) {
return UserEmailsController._handleEmailError(err, req, res, next)
UserUpdater.setDefaultEmailAddress(
userId,
email,
false,
auditLog,
true,
err => {
if (err) {
return UserEmailsController._handleEmailError(err, req, res, next)
}
AuthenticationController.setInSessionUser(req, { email: email })
res.sendStatus(200)
}
AuthenticationController.setInSessionUser(req, { email: email })
res.sendStatus(200)
})
)
},
endorse(req, res, next) {

View file

@ -13,6 +13,7 @@ const {
} = require('../Institutions/InstitutionsAPI')
const Features = require('../../infrastructure/Features')
const FeaturesUpdater = require('../Subscription/FeaturesUpdater')
const EmailHandler = require('../Email/EmailHandler')
const EmailHelper = require('../Helpers/EmailHelper')
const Errors = require('../Errors/Errors')
const NewsletterManager = require('../Newsletter/NewsletterManager')
@ -23,7 +24,8 @@ async function setDefaultEmailAddress(
userId,
email,
allowUnconfirmed,
auditLog
auditLog,
sendSecurityAlert
) {
email = EmailHelper.parseEmail(email)
if (email == null) {
@ -67,6 +69,25 @@ async function setDefaultEmailAddress(
throw new Error('email update error')
}
if (sendSecurityAlert) {
// send email to both old and new primary email
const emailOptions = {
actionDescribed: `the primary email address on your account was changed to ${email}`,
action: 'change of primary email address'
}
const toOld = Object.assign({}, emailOptions, { to: oldEmail })
const toNew = Object.assign({}, emailOptions, { to: email })
try {
await EmailHandler.promises.sendEmail('securityAlert', toOld)
await EmailHandler.promises.sendEmail('securityAlert', toNew)
} catch (error) {
logger.error(
{ err: error, userId },
'could not send security alert email when primary email changed'
)
}
}
try {
await NewsletterManager.promises.changeEmail(user, email)
} catch (error) {
@ -155,6 +176,7 @@ const UserUpdater = {
newEmail,
true,
auditLog,
true,
cb
),
cb => UserUpdater.removeEmailAddress(userId, oldEmail, cb)

View file

@ -59,6 +59,11 @@ describe('UserUpdater', function() {
addAffiliation: this.addAffiliation,
removeAffiliation: this.removeAffiliation
},
'../Email/EmailHandler': (this.EmailHandler = {
promises: {
sendEmail: sinon.stub()
}
}),
'../../infrastructure/Features': (this.Features = {
hasFeature: sinon.stub().returns(false)
}),
@ -151,7 +156,13 @@ describe('UserUpdater', function() {
.calledWith(this.stubbedUser._id, this.newEmail)
.should.equal(true)
this.UserUpdater.setDefaultEmailAddress
.calledWith(this.stubbedUser._id, this.newEmail, true)
.calledWith(
this.stubbedUser._id,
this.newEmail,
true,
this.auditLog,
true
)
.should.equal(true)
this.UserUpdater.removeEmailAddress
.calledWith(this.stubbedUser._id, this.stubbedUser.email)
@ -562,6 +573,34 @@ describe('UserUpdater', function() {
)
})
})
describe('security alert', function() {
it('should be sent to old and new email when sendSecurityAlert=true', function(done) {
// this.UserGetter.promises.getUser.resolves(this.stubbedUser)
this.UserUpdater.promises.updateUser = sinon.stub().resolves({ n: 1 })
this.UserUpdater.setDefaultEmailAddress(
this.stubbedUser._id,
this.newEmail,
false,
this.auditLog,
true,
error => {
expect(error).to.not.exist
this.EmailHandler.promises.sendEmail.callCount.should.equal(2)
const toOldEmailAlert = this.EmailHandler.promises.sendEmail
.firstCall
expect(toOldEmailAlert.args[0]).to.equal('securityAlert')
const toNewEmailAlert = this.EmailHandler.promises.sendEmail
.lastCall
expect(toOldEmailAlert.args[1].to).to.equal(this.stubbedUser.email)
expect(toNewEmailAlert.args[0]).to.equal('securityAlert')
expect(toNewEmailAlert.args[1].to).to.equal(this.newEmail)
done()
}
)
})
})
})
describe('confirmEmail', function() {