[web] Use 6-digits code to confirm existing email in Account Settings (#23931)

* Rename `checkSecondaryEmailConfirmationCode` to `checkAddSecondaryEmailConfirmationCode`

* Create function `sendCodeAndStoreInSession`

* Create function `sendExistingSecondaryEmailConfirmationCode`

* Create function `_checkConfirmationCode`

* Create function `checkExistingEmailConfirmationCode`

* Rename `resendSecondaryEmailConfirmationCode` to `resendAddSecondaryEmailConfirmationCode`

* Create function `_resendConfirmationCode`

* Create function `resendExistingSecondaryEmailConfirmationCode`

* Add `ResendConfirmationCodeModal`

* Remove `ResendConfirmationEmailButton`

* `bin/run web npm run extract-translations`

* Update frontend test

* Fix: don't throw on render when send-confirmation-code fails!

* Update phrasing in the UI

Per https://docs.google.com/document/d/1PE1vlZWQN--PjmXpyHR9rV2YPd7OIPIsUbnZaHj0cDI/edit?usp=sharing

* Add unit test

* Don't share the "send-confirmation" and "resend-confirmation" rate-limits

* Update frontend test after copy change

* Rename `checkAddSecondaryEmailConfirmationCode` to `checkNewSecondaryEmailConfirmationCode` and `resendAddSecondaryEmailConfirmationCode` to `resendNewSecondaryEmailConfirmationCode`

* Rename `cb` to `beforeConfirmEmail`

Co-authored-by: Jakob Ackermann <jakob.ackermann@overleaf.com>

* Return `422` on missing session data

Co-authored-by: Jakob Ackermann <jakob.ackermann@overleaf.com>

* Add `userId` to log

* Replace `isSecondary` param by `welcomeUser`

Co-authored-by: Jakob Ackermann <jakob.ackermann@overleaf.com>

* Rename `resend-confirm-email-code`'s `existingEmail` to `email`

* Remove "secondary" from rate-limiters

Co-authored-by: Jakob Ackermann <jakob.ackermann@overleaf.com>

* Remove unnecessary `userId` check behind `AuthenticationController.requireLogin()`

* Only open the modal if the code was sent successfully

---------

Co-authored-by: Jakob Ackermann <jakob.ackermann@overleaf.com>
GitOrigin-RevId: df892064641d9f722785699777383b2d863124e1
This commit is contained in:
Antoine Clausse
2025-03-07 09:06:50 +00:00
committed by Copybot
co-authored by Jakob Ackermann
parent e52f3543a7
commit c4e6dfbbbd
13 changed files with 743 additions and 293 deletions
@@ -81,7 +81,7 @@ describe('<EmailsSection />', function () {
fetchMock.get('/user/emails?ensureAffiliation=true', [unconfirmedUserData])
render(<EmailsSection />)
await screen.findByText(/please check your inbox/i)
await screen.findByText(/unconfirmed/i)
})
it('hides confirmation status for confirmed users', async function () {
@@ -96,7 +96,7 @@ describe('<EmailsSection />', function () {
fetchMock.get('/user/emails?ensureAffiliation=true', [unconfirmedUserData])
render(<EmailsSection />)
await screen.findByRole('button', { name: /resend confirmation email/i })
await screen.findByRole('button', { name: /resend confirmation code/i })
})
it('renders professional label', async function () {
@@ -115,16 +115,16 @@ describe('<EmailsSection />', function () {
render(<EmailsSection />)
await waitForElementToBeRemoved(() => screen.getByText(/loading/i))
fetchMock.post('/user/emails/resend_confirmation', 200)
fetchMock.post('/user/emails/send-confirmation-code', 200)
const button = screen.getByRole('button', {
name: /resend confirmation email/i,
name: /resend confirmation code/i,
})
fireEvent.click(button)
expect(
screen.queryByRole('button', {
name: /resend confirmation email/i,
name: /resend confirmation code/i,
})
).to.be.null
@@ -135,7 +135,7 @@ describe('<EmailsSection />', function () {
).to.be.null
await screen.findByRole('button', {
name: /resend confirmation email/i,
name: /resend confirmation code/i,
})
})
@@ -145,22 +145,19 @@ describe('<EmailsSection />', function () {
render(<EmailsSection />)
await waitForElementToBeRemoved(() => screen.getByText(/loading/i))
fetchMock.post('/user/emails/resend_confirmation', 503)
fetchMock.post('/user/emails/send-confirmation-code', 503)
const button = screen.getByRole('button', {
name: /resend confirmation email/i,
name: /resend confirmation code/i,
})
fireEvent.click(button)
expect(
screen.queryByRole('button', {
name: /resend confirmation email/i,
})
).to.be.null
expect(screen.queryByRole('button', { name: /resend confirmation code/i }))
.to.be.null
await waitForElementToBeRemoved(() => screen.getByText(/sending/i))
screen.getByText(/sorry, something went wrong/i)
screen.getByRole('button', { name: /resend confirmation email/i })
screen.getByRole('button', { name: /resend confirmation code/i })
})
})