mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-27 02:51:57 +02:00
Revert "Revert "[web] Convert models and self-referential test files to ESM "" GitOrigin-RevId: f64000ae31d298b075a8722dfc51f294c71bc021
291 lines
8.8 KiB
JavaScript
291 lines
8.8 KiB
JavaScript
// TODO: This file was created by bulk-decaffeinate.
|
|
// Fix any style issues and re-enable lint.
|
|
/*
|
|
* decaffeinate suggestions:
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
*/
|
|
|
|
import { vi, expect } from 'vitest'
|
|
|
|
import sinon from 'sinon'
|
|
import Errors from '../../../../app/src/Features/Errors/Errors.js'
|
|
import EmailHelper from '../../../../app/src/Features/Helpers/EmailHelper.mjs'
|
|
|
|
const modulePath =
|
|
'../../../../app/src/Features/User/UserEmailsConfirmationHandler'
|
|
|
|
vi.mock('../../../../app/src/Features/Errors/Errors.js', () =>
|
|
vi.importActual('../../../../app/src/Features/Errors/Errors.js')
|
|
)
|
|
|
|
describe('UserEmailsConfirmationHandler', function () {
|
|
beforeEach(async function (ctx) {
|
|
ctx.mockUser = {
|
|
_id: 'mock-user-id',
|
|
email: 'mock@example.com',
|
|
emails: [{ email: 'mock@example.com' }],
|
|
}
|
|
ctx.user_id = ctx.mockUser._id
|
|
ctx.email = ctx.mockUser.email
|
|
ctx.req = {}
|
|
|
|
vi.doMock('@overleaf/settings', () => ({
|
|
default: (ctx.settings = {
|
|
siteUrl: 'https://emails.example.com',
|
|
}),
|
|
}))
|
|
|
|
vi.doMock(
|
|
'../../../../app/src/Features/Security/OneTimeTokenHandler',
|
|
() => ({
|
|
default: (ctx.OneTimeTokenHandler = {
|
|
promises: {},
|
|
}),
|
|
})
|
|
)
|
|
|
|
vi.doMock('../../../../app/src/Features/User/UserUpdater', () => ({
|
|
default: (ctx.UserUpdater = {
|
|
promises: {},
|
|
}),
|
|
}))
|
|
|
|
vi.doMock('../../../../app/src/Features/User/UserGetter', () => ({
|
|
default: (ctx.UserGetter = {
|
|
getUser: sinon.stub().yields(null, ctx.mockUser),
|
|
promises: {
|
|
getUser: sinon.stub().resolves(ctx.mockUser),
|
|
},
|
|
}),
|
|
}))
|
|
|
|
vi.doMock('../../../../app/src/Features/Email/EmailHandler', () => ({
|
|
default: (ctx.EmailHandler = {
|
|
promises: {},
|
|
}),
|
|
}))
|
|
|
|
vi.doMock('../../../../app/src/Features/Helpers/EmailHelper', () => ({
|
|
default: EmailHelper,
|
|
}))
|
|
|
|
vi.doMock(
|
|
'../../../../app/src/Features/Authentication/SessionManager',
|
|
() => ({
|
|
default: (ctx.SessionManager = {
|
|
getLoggedInUserId: sinon.stub().returns(ctx.mockUser._id),
|
|
}),
|
|
})
|
|
)
|
|
|
|
ctx.UserEmailsConfirmationHandler = (await import(modulePath)).default
|
|
return (ctx.callback = sinon.stub())
|
|
})
|
|
|
|
describe('sendConfirmationEmail', function () {
|
|
beforeEach(function (ctx) {
|
|
ctx.OneTimeTokenHandler.promises.getNewToken = sinon
|
|
.stub()
|
|
.resolves((ctx.token = 'new-token'))
|
|
return (ctx.EmailHandler.promises.sendEmail = sinon.stub().resolves())
|
|
})
|
|
|
|
describe('successfully', function () {
|
|
beforeEach(async function (ctx) {
|
|
await ctx.UserEmailsConfirmationHandler.promises.sendConfirmationEmail(
|
|
ctx.user_id,
|
|
ctx.email
|
|
)
|
|
})
|
|
|
|
it('should generate a token for the user which references their id and email', function (ctx) {
|
|
return ctx.OneTimeTokenHandler.promises.getNewToken
|
|
.calledWith(
|
|
'email_confirmation',
|
|
{ user_id: ctx.user_id, email: ctx.email },
|
|
{ expiresIn: 90 * 24 * 60 * 60 }
|
|
)
|
|
.should.equal(true)
|
|
})
|
|
|
|
it('should send an email to the user', function (ctx) {
|
|
return ctx.EmailHandler.promises.sendEmail
|
|
.calledWith('confirmEmail', {
|
|
to: ctx.email,
|
|
confirmEmailUrl:
|
|
'https://emails.example.com/user/emails/confirm?token=new-token',
|
|
sendingUser_id: ctx.user_id,
|
|
})
|
|
.should.equal(true)
|
|
})
|
|
})
|
|
|
|
describe('with invalid email', function () {
|
|
it('should reject with an error', async function (ctx) {
|
|
await expect(
|
|
ctx.UserEmailsConfirmationHandler.promises.sendConfirmationEmail(
|
|
ctx.user_id,
|
|
'!"£$%^&*()'
|
|
)
|
|
).to.be.rejectedWith(Error)
|
|
})
|
|
})
|
|
|
|
describe('a custom template', function () {
|
|
beforeEach(async function (ctx) {
|
|
await ctx.UserEmailsConfirmationHandler.promises.sendConfirmationEmail(
|
|
ctx.user_id,
|
|
ctx.email,
|
|
'myCustomTemplate'
|
|
)
|
|
})
|
|
|
|
it('should send an email with the given template', function (ctx) {
|
|
return ctx.EmailHandler.promises.sendEmail
|
|
.calledWith('myCustomTemplate')
|
|
.should.equal(true)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('confirmEmailFromToken', function () {
|
|
beforeEach(function (ctx) {
|
|
ctx.OneTimeTokenHandler.promises.peekValueFromToken = sinon
|
|
.stub()
|
|
.resolves({ data: { user_id: ctx.user_id, email: ctx.email } })
|
|
ctx.OneTimeTokenHandler.promises.expireToken = sinon.stub().resolves()
|
|
ctx.UserUpdater.promises.confirmEmail = sinon.stub().resolves()
|
|
})
|
|
|
|
describe('successfully', function () {
|
|
beforeEach(async function (ctx) {
|
|
await ctx.UserEmailsConfirmationHandler.promises.confirmEmailFromToken(
|
|
ctx.req,
|
|
(ctx.token = 'mock-token')
|
|
)
|
|
})
|
|
|
|
it('should call peekValueFromToken', function (ctx) {
|
|
return ctx.OneTimeTokenHandler.promises.peekValueFromToken
|
|
.calledWith('email_confirmation', ctx.token)
|
|
.should.equal(true)
|
|
})
|
|
|
|
it('should call expireToken', function (ctx) {
|
|
return ctx.OneTimeTokenHandler.promises.expireToken
|
|
.calledWith('email_confirmation', ctx.token)
|
|
.should.equal(true)
|
|
})
|
|
|
|
it('should confirm the email of the user_id', function (ctx) {
|
|
return ctx.UserUpdater.promises.confirmEmail
|
|
.calledWith(ctx.user_id, ctx.email)
|
|
.should.equal(true)
|
|
})
|
|
})
|
|
|
|
describe('with an expired token', function () {
|
|
beforeEach(function (ctx) {
|
|
ctx.OneTimeTokenHandler.promises.peekValueFromToken = sinon
|
|
.stub()
|
|
.rejects(new Errors.NotFoundError('no token found'))
|
|
})
|
|
|
|
it('should reject with a NotFoundError', async function (ctx) {
|
|
await expect(
|
|
ctx.UserEmailsConfirmationHandler.promises.confirmEmailFromToken(
|
|
ctx.req,
|
|
(ctx.token = 'mock-token')
|
|
)
|
|
).to.be.rejectedWith(Errors.NotFoundError)
|
|
})
|
|
})
|
|
|
|
describe('with no user_id in the token', function () {
|
|
beforeEach(function (ctx) {
|
|
ctx.OneTimeTokenHandler.promises.peekValueFromToken = sinon
|
|
.stub()
|
|
.resolves({ data: { email: ctx.email } })
|
|
})
|
|
|
|
it('should reject with a NotFoundError', async function (ctx) {
|
|
await expect(
|
|
ctx.UserEmailsConfirmationHandler.promises.confirmEmailFromToken(
|
|
ctx.req,
|
|
(ctx.token = 'mock-token')
|
|
)
|
|
).to.be.rejectedWith(Errors.NotFoundError)
|
|
})
|
|
})
|
|
|
|
describe('with no email in the token', function () {
|
|
beforeEach(function (ctx) {
|
|
ctx.OneTimeTokenHandler.promises.peekValueFromToken = sinon
|
|
.stub()
|
|
.resolves({ data: { user_id: ctx.user_id } })
|
|
})
|
|
|
|
it('should reject with a NotFoundError', async function (ctx) {
|
|
await expect(
|
|
ctx.UserEmailsConfirmationHandler.promises.confirmEmailFromToken(
|
|
ctx.req,
|
|
(ctx.token = 'mock-token')
|
|
)
|
|
).to.be.rejectedWith(Errors.NotFoundError)
|
|
})
|
|
})
|
|
|
|
describe('with no user found', function () {
|
|
beforeEach(function (ctx) {
|
|
ctx.UserGetter.promises.getUser.resolves(null)
|
|
})
|
|
|
|
it('should reject with a NotFoundError', async function (ctx) {
|
|
await expect(
|
|
ctx.UserEmailsConfirmationHandler.promises.confirmEmailFromToken(
|
|
ctx.req,
|
|
(ctx.token = 'mock-token')
|
|
)
|
|
).to.be.rejectedWith(Errors.NotFoundError)
|
|
})
|
|
})
|
|
|
|
describe('with secondary email missing on user', function () {
|
|
beforeEach(function (ctx) {
|
|
ctx.OneTimeTokenHandler.promises.peekValueFromToken = sinon
|
|
.stub()
|
|
.resolves({
|
|
data: { user_id: ctx.user_id, email: 'deleted@email.com' },
|
|
})
|
|
})
|
|
|
|
it('should reject with a NotFoundError', async function (ctx) {
|
|
await expect(
|
|
ctx.UserEmailsConfirmationHandler.promises.confirmEmailFromToken(
|
|
ctx.req,
|
|
(ctx.token = 'mock-token')
|
|
)
|
|
).to.be.rejectedWith(Errors.NotFoundError)
|
|
})
|
|
})
|
|
|
|
describe('when the logged in user is not the token user', function () {
|
|
beforeEach(function (ctx) {
|
|
ctx.SessionManager.getLoggedInUserId = sinon
|
|
.stub()
|
|
.returns('other-user-id')
|
|
})
|
|
|
|
it('should reject with a ForbiddenError', async function (ctx) {
|
|
await expect(
|
|
ctx.UserEmailsConfirmationHandler.promises.confirmEmailFromToken(
|
|
ctx.req,
|
|
(ctx.token = 'mock-token')
|
|
)
|
|
).to.be.rejectedWith(Errors.ForbiddenError)
|
|
})
|
|
})
|
|
})
|
|
})
|