mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-14 14:13:43 +01:00
[web] In tests, update email confirmation to use the 6-digits flow (#27069)
* Rename `sendExistingSecondaryEmailConfirmationCode` to `sendExistingEmailConfirmationCode` * Deduplicate error handling into `throwIfErrorResponse` * Update `userHelper.confirmEmail` to use the 6-digits flow GitOrigin-RevId: 91bdf7b185407b58520ca6b2aa1a7c71bdd23bc8
This commit is contained in:
@@ -141,7 +141,7 @@ async function sendReconfirmation(req, res) {
|
||||
res.sendStatus(204)
|
||||
}
|
||||
|
||||
async function sendExistingSecondaryEmailConfirmationCode(req, res) {
|
||||
async function sendExistingEmailConfirmationCode(req, res) {
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
const email = EmailHelper.parseEmail(req.body.email)
|
||||
if (!email) {
|
||||
@@ -715,8 +715,8 @@ const UserEmailsController = {
|
||||
|
||||
sendReconfirmation: expressify(sendReconfirmation),
|
||||
|
||||
sendExistingSecondaryEmailConfirmationCode: expressify(
|
||||
sendExistingSecondaryEmailConfirmationCode
|
||||
sendExistingEmailConfirmationCode: expressify(
|
||||
sendExistingEmailConfirmationCode
|
||||
),
|
||||
|
||||
addSecondaryEmailPage: expressify(addSecondaryEmailPage),
|
||||
|
||||
@@ -345,7 +345,7 @@ async function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||
'/user/emails/send-confirmation-code',
|
||||
AuthenticationController.requireLogin(),
|
||||
RateLimiterMiddleware.rateLimit(rateLimiters.sendConfirmation),
|
||||
UserEmailsController.sendExistingSecondaryEmailConfirmationCode
|
||||
UserEmailsController.sendExistingEmailConfirmationCode
|
||||
)
|
||||
|
||||
webRouter.post(
|
||||
|
||||
@@ -7,7 +7,6 @@ import UserGetter from '../../../../app/src/Features/User/UserGetter.js'
|
||||
import UserUpdater from '../../../../app/src/Features/User/UserUpdater.js'
|
||||
import moment from 'moment'
|
||||
import fetch from 'node-fetch'
|
||||
import { db } from '../../../../app/src/infrastructure/mongodb.js'
|
||||
import mongodb from 'mongodb-legacy'
|
||||
|
||||
import { UserAuditLogEntry } from '../../../../app/src/models/UserAuditLogEntry.js'
|
||||
@@ -19,11 +18,20 @@ import { RateLimiter } from '../../../../app/src/infrastructure/RateLimiter.js'
|
||||
const { ObjectId } = mongodb
|
||||
|
||||
const rateLimiters = {
|
||||
resendConfirmation: new RateLimiter('resend-confirmation'),
|
||||
sendConfirmation: new RateLimiter('send-confirmation'),
|
||||
}
|
||||
|
||||
let globalUserNum = Settings.test.counterInit
|
||||
|
||||
const throwIfErrorResponse = async response => {
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
const body = await response.text()
|
||||
throw new Error(
|
||||
`request failed: status=${response.status} body=${JSON.stringify(body)}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class UserHelper {
|
||||
/**
|
||||
* Create UserHelper
|
||||
@@ -129,13 +137,7 @@ class UserHelper {
|
||||
// get csrf token from api and store
|
||||
const response = await this.fetch('/dev/csrf')
|
||||
const body = await response.text()
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`get csrf token failed: status=${response.status} body=${JSON.stringify(
|
||||
body
|
||||
)}`
|
||||
)
|
||||
}
|
||||
await throwIfErrorResponse(response)
|
||||
this._csrfToken = body
|
||||
}
|
||||
|
||||
@@ -145,14 +147,7 @@ class UserHelper {
|
||||
async getSession() {
|
||||
const response = await this.fetch('/dev/session')
|
||||
const body = await response.text()
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`get session failed: status=${response.status} body=${JSON.stringify(
|
||||
body
|
||||
)}`
|
||||
)
|
||||
}
|
||||
await throwIfErrorResponse(response)
|
||||
return JSON.parse(body)
|
||||
}
|
||||
|
||||
@@ -160,24 +155,22 @@ class UserHelper {
|
||||
const response = await this.fetch(
|
||||
`/dev/split_test/get_assignment?splitTestName=${splitTestName}`
|
||||
)
|
||||
await throwIfErrorResponse(response)
|
||||
const body = await response.text()
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`get split test assignment failed: status=${response.status} body=${JSON.stringify(
|
||||
body
|
||||
)}`
|
||||
)
|
||||
}
|
||||
return JSON.parse(body)
|
||||
}
|
||||
|
||||
async getEmailConfirmationCode() {
|
||||
/**
|
||||
*
|
||||
* @param {'pendingExistingEmail'|'pendingUserRegistration'}sessionKey
|
||||
* @return {Promise<*>}
|
||||
*/
|
||||
async getEmailConfirmationCode(sessionKey) {
|
||||
const session = await this.getSession()
|
||||
|
||||
const code = session.pendingUserRegistration?.confirmCode
|
||||
const code = session[sessionKey]?.confirmCode
|
||||
if (!code) {
|
||||
throw new Error('No confirmation code found in session')
|
||||
throw new Error(`No confirmation code found in session (${sessionKey})`)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@@ -383,14 +376,8 @@ class UserHelper {
|
||||
body: JSON.stringify(userData),
|
||||
...options,
|
||||
})
|
||||
await throwIfErrorResponse(response)
|
||||
const body = await response.json()
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`register failed: status=${response.status} body=${JSON.stringify(
|
||||
body
|
||||
)}`
|
||||
)
|
||||
}
|
||||
if (body.message && body.message.type === 'error') {
|
||||
throw new Error(`register api error: ${body.message.text}`)
|
||||
}
|
||||
@@ -400,7 +387,9 @@ class UserHelper {
|
||||
)
|
||||
}
|
||||
|
||||
const code = await userHelper.getEmailConfirmationCode()
|
||||
const code = await userHelper.getEmailConfirmationCode(
|
||||
'pendingUserRegistration'
|
||||
)
|
||||
|
||||
const confirmationResponse = await userHelper.fetch(
|
||||
'/registration/confirm-email',
|
||||
@@ -446,14 +435,7 @@ class UserHelper {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams([['email', email]]),
|
||||
})
|
||||
const body = await response.text()
|
||||
if (response.status !== 204) {
|
||||
throw new Error(
|
||||
`add email failed: status=${response.status} body=${JSON.stringify(
|
||||
body
|
||||
)}`
|
||||
)
|
||||
}
|
||||
await throwIfErrorResponse(response)
|
||||
}
|
||||
|
||||
async addEmailAndConfirm(userId, email) {
|
||||
@@ -519,40 +501,21 @@ class UserHelper {
|
||||
|
||||
async confirmEmail(userId, email) {
|
||||
// clear ratelimiting on resend confirmation endpoint
|
||||
await rateLimiters.resendConfirmation.delete(userId)
|
||||
// UserHelper.createUser does not create a confirmation token
|
||||
let response = await this.fetch('/user/emails/resend_confirmation', {
|
||||
await rateLimiters.sendConfirmation.delete(userId)
|
||||
const requestConfirmationCode = await this.fetch(
|
||||
'/user/emails/send-confirmation-code',
|
||||
{
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({ email }),
|
||||
}
|
||||
)
|
||||
await throwIfErrorResponse(requestConfirmationCode)
|
||||
const code = await this.getEmailConfirmationCode('pendingExistingEmail')
|
||||
const requestConfirmCode = await this.fetch('/user/emails/confirm-code', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams([['email', email]]),
|
||||
body: new URLSearchParams({ code }),
|
||||
})
|
||||
if (response.status !== 200) {
|
||||
const body = await response.text()
|
||||
throw new Error(
|
||||
`resend confirmation failed: status=${
|
||||
response.status
|
||||
} body=${JSON.stringify(body)}`
|
||||
)
|
||||
}
|
||||
const tokenData = await db.tokens
|
||||
.find({
|
||||
use: 'email_confirmation',
|
||||
'data.user_id': userId.toString(),
|
||||
'data.email': email,
|
||||
usedAt: { $exists: false },
|
||||
})
|
||||
.next()
|
||||
response = await this.fetch('/user/emails/confirm', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams([['token', tokenData.token]]),
|
||||
})
|
||||
if (response.status !== 200) {
|
||||
const body = await response.text()
|
||||
throw new Error(
|
||||
`confirm email failed: status=${response.status} body=${JSON.stringify(
|
||||
body
|
||||
)}`
|
||||
)
|
||||
}
|
||||
await throwIfErrorResponse(requestConfirmCode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -905,7 +905,7 @@ describe('UserEmailsController', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('sendExistingSecondaryEmailConfirmationCode', function () {
|
||||
describe('sendExistingEmailConfirmationCode', function () {
|
||||
beforeEach(function () {
|
||||
this.email = 'existing-email@example.com'
|
||||
this.req.body.email = this.email
|
||||
@@ -923,7 +923,7 @@ describe('UserEmailsController', function () {
|
||||
})
|
||||
|
||||
it('should send confirmation code for existing email', async function () {
|
||||
await this.UserEmailsController.sendExistingSecondaryEmailConfirmationCode(
|
||||
await this.UserEmailsController.sendExistingEmailConfirmationCode(
|
||||
this.req,
|
||||
{
|
||||
sendStatus: code => {
|
||||
@@ -944,7 +944,7 @@ describe('UserEmailsController', function () {
|
||||
this.UserEmailsConfirmationHandler.promises.sendConfirmationCode.resolves(
|
||||
{ confirmCode, confirmCodeExpiresTimestamp }
|
||||
)
|
||||
await this.UserEmailsController.sendExistingSecondaryEmailConfirmationCode(
|
||||
await this.UserEmailsController.sendExistingEmailConfirmationCode(
|
||||
this.req,
|
||||
{ sendStatus: sinon.stub() }
|
||||
)
|
||||
@@ -958,7 +958,7 @@ describe('UserEmailsController', function () {
|
||||
|
||||
it('should handle invalid email', async function () {
|
||||
this.EmailHelper.parseEmail.returns(null)
|
||||
await this.UserEmailsController.sendExistingSecondaryEmailConfirmationCode(
|
||||
await this.UserEmailsController.sendExistingEmailConfirmationCode(
|
||||
this.req,
|
||||
{
|
||||
sendStatus: code => {
|
||||
@@ -975,7 +975,7 @@ describe('UserEmailsController', function () {
|
||||
this.UserGetter.promises.getUserByAnyEmail.resolves({
|
||||
_id: 'another-user-id',
|
||||
})
|
||||
await this.UserEmailsController.sendExistingSecondaryEmailConfirmationCode(
|
||||
await this.UserEmailsController.sendExistingEmailConfirmationCode(
|
||||
this.req,
|
||||
{
|
||||
sendStatus: code => {
|
||||
|
||||
Reference in New Issue
Block a user