Merge pull request #19861 from overleaf/ab-overleaf-integration-delete-flow

[web] Remove /user/delete override from overleaf-integration

GitOrigin-RevId: 4f679f6835522c2325fe7b0368f58e7a952ee73d
This commit is contained in:
Alexandre Bourdin 2024-08-13 16:51:58 +02:00 committed by Copybot
parent cf83990459
commit 61891e3c80
3 changed files with 63 additions and 8 deletions

View file

@ -225,17 +225,30 @@ async function tryDeleteUser(req, res, next) {
const { password } = req.body const { password } = req.body
req.logger.addFields({ userId }) req.logger.addFields({ userId })
logger.debug({ userId }, 'trying to delete user account')
if (password == null || password === '') { if (password == null || password === '') {
logger.err({ userId }, 'no password supplied for attempt to delete account') logger.err({ userId }, 'no password supplied for attempt to delete account')
return res.sendStatus(403) return res.sendStatus(403)
} }
const { user } = await AuthenticationManager.promises.authenticate( let user
{ _id: userId }, try {
password, user = (
null, await AuthenticationManager.promises.authenticate(
{ enforceHIBPCheck: false } { _id: userId },
) password,
null,
{ enforceHIBPCheck: false }
)
).user
} catch (err) {
throw OError.tag(
err,
'error authenticating during attempt to delete account',
{ userId }
)
}
if (!user) { if (!user) {
logger.err({ userId }, 'auth failed during attempt to delete account') logger.err({ userId }, 'auth failed during attempt to delete account')
return res.sendStatus(403) return res.sendStatus(403)
@ -265,10 +278,12 @@ async function tryDeleteUser(req, res, next) {
errorData.info.public errorData.info.public
) )
} else { } else {
throw err throw OError.tag(err, errorData.message, errorData.info)
} }
} }
await Modules.promises.hooks.fire('tryDeleteV1Account', user)
const sessionId = req.sessionID const sessionId = req.sessionID
if (typeof req.logout === 'function') { if (typeof req.logout === 'function') {

View file

@ -696,7 +696,6 @@ describe('LaunchpadController', function () {
describe('when overleaf', function () { describe('when overleaf', function () {
beforeEach(function () { beforeEach(function () {
this.Settings.overleaf = { one: 1 } this.Settings.overleaf = { one: 1 }
this.Settings.createV1AccountOnLogin = true
this._atLeastOneAdminExists.resolves(false) this._atLeastOneAdminExists.resolves(false)
this.email = 'someone@example.com' this.email = 'someone@example.com'
this.password = 'a_really_bad_password' this.password = 'a_really_bad_password'

View file

@ -133,6 +133,14 @@ describe('UserController', function () {
promises: { expireAllTokensForUser: sinon.stub().resolves() }, promises: { expireAllTokensForUser: sinon.stub().resolves() },
} }
this.Modules = {
promises: {
hooks: {
fire: sinon.stub().resolves(),
},
},
}
this.UserController = SandboxedModule.require(modulePath, { this.UserController = SandboxedModule.require(modulePath, {
requires: { requires: {
'../Helpers/UrlHelper': this.UrlHelper, '../Helpers/UrlHelper': this.UrlHelper,
@ -156,6 +164,7 @@ describe('UserController', function () {
'../Security/OneTimeTokenHandler': this.OneTimeTokenHandler, '../Security/OneTimeTokenHandler': this.OneTimeTokenHandler,
'../../infrastructure/RequestContentTypeDetection': '../../infrastructure/RequestContentTypeDetection':
this.RequestContentTypeDetection, this.RequestContentTypeDetection,
'../../infrastructure/Modules': this.Modules,
}, },
}) })
@ -215,6 +224,17 @@ describe('UserController', function () {
this.UserController.tryDeleteUser(this.req, this.res, this.next) this.UserController.tryDeleteUser(this.req, this.res, this.next)
}) })
it('should call hook to try to delete v1 account', function (done) {
this.res.sendStatus = code => {
expect(this.Modules.promises.hooks.fire).to.have.been.calledWith(
'tryDeleteV1Account',
this.user
)
done()
}
this.UserController.tryDeleteUser(this.req, this.res, this.next)
})
describe('when no password is supplied', function () { describe('when no password is supplied', function () {
beforeEach(function () { beforeEach(function () {
this.req.body.password = '' this.req.body.password = ''
@ -873,6 +893,7 @@ describe('UserController', function () {
} }
this.EmailHandler.promises.sendEmail.rejects(anError) this.EmailHandler.promises.sendEmail.rejects(anError)
}) })
it('should not return error but should log it', function (done) { it('should not return error but should log it', function (done) {
this.res.json.callsFake(result => { this.res.json.callsFake(result => {
expect(result.message.type).to.equal('success') expect(result.message.type).to.equal('success')
@ -901,16 +922,19 @@ describe('UserController', function () {
this.next this.next
) )
}) })
it('should not run affiliation check', function () { it('should not run affiliation check', function () {
expect(this.UserGetter.promises.getUser).to.not.have.been.called expect(this.UserGetter.promises.getUser).to.not.have.been.called
expect(this.UserUpdater.promises.confirmEmail).to.not.have.been.called expect(this.UserUpdater.promises.confirmEmail).to.not.have.been.called
expect(this.UserUpdater.promises.addAffiliationForNewUser).to.not.have expect(this.UserUpdater.promises.addAffiliationForNewUser).to.not.have
.been.called .been.called
}) })
it('should not return an error', function () { it('should not return an error', function () {
expect(this.next).to.be.calledWith() expect(this.next).to.be.calledWith()
}) })
}) })
describe('without ensureAffiliation query parameter', function () { describe('without ensureAffiliation query parameter', function () {
beforeEach(async function () { beforeEach(async function () {
this.Features.hasFeature.withArgs('affiliations').returns(true) this.Features.hasFeature.withArgs('affiliations').returns(true)
@ -920,16 +944,19 @@ describe('UserController', function () {
this.next this.next
) )
}) })
it('should not run middleware', function () { it('should not run middleware', function () {
expect(this.UserGetter.promises.getUser).to.not.have.been.called expect(this.UserGetter.promises.getUser).to.not.have.been.called
expect(this.UserUpdater.promises.confirmEmail).to.not.have.been.called expect(this.UserUpdater.promises.confirmEmail).to.not.have.been.called
expect(this.UserUpdater.promises.addAffiliationForNewUser).to.not.have expect(this.UserUpdater.promises.addAffiliationForNewUser).to.not.have
.been.called .been.called
}) })
it('should not return an error', function () { it('should not return an error', function () {
expect(this.next).to.be.calledWith() expect(this.next).to.be.calledWith()
}) })
}) })
describe('no flagged email', function () { describe('no flagged email', function () {
beforeEach(async function () { beforeEach(async function () {
const email = 'unit-test@overleaf.com' const email = 'unit-test@overleaf.com'
@ -947,19 +974,23 @@ describe('UserController', function () {
this.next this.next
) )
}) })
it('should get the user', function () { it('should get the user', function () {
expect(this.UserGetter.promises.getUser).to.have.been.calledWith( expect(this.UserGetter.promises.getUser).to.have.been.calledWith(
this.user._id this.user._id
) )
}) })
it('should not try to add affiliation or update user', function () { it('should not try to add affiliation or update user', function () {
expect(this.UserUpdater.promises.addAffiliationForNewUser).to.not.have expect(this.UserUpdater.promises.addAffiliationForNewUser).to.not.have
.been.called .been.called
}) })
it('should not return an error', function () { it('should not return an error', function () {
expect(this.next).to.be.calledWith() expect(this.next).to.be.calledWith()
}) })
}) })
describe('flagged non-SSO email', function () { describe('flagged non-SSO email', function () {
let emailFlagged let emailFlagged
beforeEach(async function () { beforeEach(async function () {
@ -980,11 +1011,13 @@ describe('UserController', function () {
this.next this.next
) )
}) })
it('should check the user has permission', function () { it('should check the user has permission', function () {
expect(this.req.assertPermission).to.have.been.calledWith( expect(this.req.assertPermission).to.have.been.calledWith(
'add-affiliation' 'add-affiliation'
) )
}) })
it('should unflag the emails but not confirm', function () { it('should unflag the emails but not confirm', function () {
expect( expect(
this.UserUpdater.promises.addAffiliationForNewUser this.UserUpdater.promises.addAffiliationForNewUser
@ -993,10 +1026,12 @@ describe('UserController', function () {
this.UserUpdater.promises.confirmEmail this.UserUpdater.promises.confirmEmail
).to.not.have.been.calledWith(this.user._id, emailFlagged) ).to.not.have.been.calledWith(this.user._id, emailFlagged)
}) })
it('should not return an error', function () { it('should not return an error', function () {
expect(this.next).to.be.calledWith() expect(this.next).to.be.calledWith()
}) })
}) })
describe('flagged SSO email', function () { describe('flagged SSO email', function () {
let emailFlagged let emailFlagged
beforeEach(async function () { beforeEach(async function () {
@ -1018,11 +1053,13 @@ describe('UserController', function () {
this.next this.next
) )
}) })
it('should check the user has permission', function () { it('should check the user has permission', function () {
expect(this.req.assertPermission).to.have.been.calledWith( expect(this.req.assertPermission).to.have.been.calledWith(
'add-affiliation' 'add-affiliation'
) )
}) })
it('should add affiliation to v1, unflag and confirm on v2', function () { it('should add affiliation to v1, unflag and confirm on v2', function () {
expect(this.UserUpdater.promises.addAffiliationForNewUser).to.have.not expect(this.UserUpdater.promises.addAffiliationForNewUser).to.have.not
.been.called .been.called
@ -1031,10 +1068,12 @@ describe('UserController', function () {
emailFlagged emailFlagged
) )
}) })
it('should not return an error', function () { it('should not return an error', function () {
expect(this.next).to.be.calledWith() expect(this.next).to.be.calledWith()
}) })
}) })
describe('when v1 returns an error', function () { describe('when v1 returns an error', function () {
let emailFlagged let emailFlagged
beforeEach(async function () { beforeEach(async function () {
@ -1056,11 +1095,13 @@ describe('UserController', function () {
this.next this.next
) )
}) })
it('should check the user has permission', function () { it('should check the user has permission', function () {
expect(this.req.assertPermission).to.have.been.calledWith( expect(this.req.assertPermission).to.have.been.calledWith(
'add-affiliation' 'add-affiliation'
) )
}) })
it('should return the error', function () { it('should return the error', function () {
expect(this.next).to.be.calledWith(sinon.match.instanceOf(Error)) expect(this.next).to.be.calledWith(sinon.match.instanceOf(Error))
}) })