chore(server): emails IoC 5 - requestEmailVerificationFactory
This commit is contained in:
@@ -1,8 +1,20 @@
|
||||
import { db } from '@/db/knex'
|
||||
import { Resolvers } from '@/modules/core/graph/generated/graphql'
|
||||
import { getUserByEmail } from '@/modules/core/repositories/users'
|
||||
import { getPendingTokenFactory } from '@/modules/emails/repositories'
|
||||
import { requestEmailVerification } from '@/modules/emails/services/verification/request'
|
||||
import { findPrimaryEmailForUserFactory } from '@/modules/core/repositories/userEmails'
|
||||
import { getUser, getUserByEmail } from '@/modules/core/repositories/users'
|
||||
import { getServerInfo } from '@/modules/core/services/generic'
|
||||
import {
|
||||
deleteOldAndInsertNewVerificationFactory,
|
||||
getPendingTokenFactory
|
||||
} from '@/modules/emails/repositories'
|
||||
import { requestEmailVerificationFactory } from '@/modules/emails/services/verification/request'
|
||||
|
||||
const requestEmailVerification = requestEmailVerificationFactory({
|
||||
getUser,
|
||||
getServerInfo,
|
||||
deleteOldAndInsertNewVerification: deleteOldAndInsertNewVerificationFactory({ db }),
|
||||
findPrimaryEmailForUser: findPrimaryEmailForUserFactory({ db })
|
||||
})
|
||||
|
||||
export = {
|
||||
User: {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { FindEmail } from '@/modules/core/domain/userEmails/operations'
|
||||
import {
|
||||
FindEmail,
|
||||
FindPrimaryEmailForUser
|
||||
} from '@/modules/core/domain/userEmails/operations'
|
||||
import { UserEmail } from '@/modules/core/domain/userEmails/types'
|
||||
import { UsersEmitter, UsersEvents } from '@/modules/core/events/usersEmitter'
|
||||
import { getEmailVerificationFinalizationRoute } from '@/modules/core/helpers/routeHelper'
|
||||
@@ -14,48 +17,51 @@ import {
|
||||
} from '@/modules/emails/services/emailRendering'
|
||||
import { sendEmail } from '@/modules/emails/services/sending'
|
||||
import { getServerOrigin } from '@/modules/shared/helpers/envHelper'
|
||||
import { db } from '@/db/knex'
|
||||
import {
|
||||
DeleteOldAndInsertNewVerification,
|
||||
RequestNewEmailVerification
|
||||
} from '@/modules/emails/domain/operations'
|
||||
import { db } from '@/db/knex'
|
||||
|
||||
const EMAIL_SUBJECT = 'Speckle Account E-mail Verification'
|
||||
|
||||
const findPrimaryEmailForUser = findPrimaryEmailForUserFactory({ db })
|
||||
|
||||
async function createNewVerification(
|
||||
userId: string
|
||||
): Promise<VerificationRequestContext> {
|
||||
if (!userId)
|
||||
throw new EmailVerificationRequestError('User for verification not specified')
|
||||
|
||||
const [user, email, serverInfo] = await Promise.all([
|
||||
getUser(userId),
|
||||
findPrimaryEmailForUser({ userId }),
|
||||
getServerInfo()
|
||||
])
|
||||
|
||||
if (!user || !email)
|
||||
throw new EmailVerificationRequestError(
|
||||
'Unable to resolve verification target user'
|
||||
)
|
||||
|
||||
if (user.verified)
|
||||
throw new EmailVerificationRequestError("User's email is already verified")
|
||||
|
||||
const verificationId = await deleteOldAndInsertNewVerificationFactory({ db })(
|
||||
user.email
|
||||
)
|
||||
|
||||
return {
|
||||
user,
|
||||
email,
|
||||
verificationId,
|
||||
serverInfo
|
||||
}
|
||||
type CreateNewVerificationDeps = {
|
||||
getUser: typeof getUser
|
||||
findPrimaryEmailForUser: FindPrimaryEmailForUser
|
||||
getServerInfo: typeof getServerInfo
|
||||
deleteOldAndInsertNewVerification: DeleteOldAndInsertNewVerification
|
||||
}
|
||||
|
||||
const createNewVerificationFactory =
|
||||
(deps: CreateNewVerificationDeps) =>
|
||||
async (userId: string): Promise<VerificationRequestContext> => {
|
||||
if (!userId)
|
||||
throw new EmailVerificationRequestError('User for verification not specified')
|
||||
|
||||
const [user, email, serverInfo] = await Promise.all([
|
||||
deps.getUser(userId),
|
||||
deps.findPrimaryEmailForUser({ userId }),
|
||||
deps.getServerInfo()
|
||||
])
|
||||
|
||||
if (!user || !email)
|
||||
throw new EmailVerificationRequestError(
|
||||
'Unable to resolve verification target user'
|
||||
)
|
||||
|
||||
if (user.verified)
|
||||
throw new EmailVerificationRequestError("User's email is already verified")
|
||||
|
||||
const verificationId = await deps.deleteOldAndInsertNewVerification(user.email)
|
||||
|
||||
return {
|
||||
user,
|
||||
email,
|
||||
verificationId,
|
||||
serverInfo
|
||||
}
|
||||
}
|
||||
|
||||
type VerificationRequestContext = {
|
||||
user: UserRecord
|
||||
verificationId: string
|
||||
@@ -165,10 +171,11 @@ async function sendVerificationEmail(state: VerificationRequestContext) {
|
||||
/**
|
||||
* Request email verification (send out verification message) for user with specified ID
|
||||
*/
|
||||
export async function requestEmailVerification(userId: string) {
|
||||
const newVerificationState = await createNewVerification(userId)
|
||||
await sendVerificationEmail(newVerificationState)
|
||||
}
|
||||
export const requestEmailVerificationFactory =
|
||||
(deps: CreateNewVerificationDeps) => async (userId: string) => {
|
||||
const newVerificationState = await createNewVerificationFactory(deps)(userId)
|
||||
await sendVerificationEmail(newVerificationState)
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for user:created events and trigger email verification initialization
|
||||
@@ -178,6 +185,15 @@ export function initializeVerificationOnRegistration() {
|
||||
// user might already be verified because of registration through an external identity provider
|
||||
if (user.verified) return
|
||||
|
||||
const requestEmailVerification = requestEmailVerificationFactory({
|
||||
getUser,
|
||||
getServerInfo,
|
||||
deleteOldAndInsertNewVerification: deleteOldAndInsertNewVerificationFactory({
|
||||
db
|
||||
}),
|
||||
findPrimaryEmailForUser: findPrimaryEmailForUserFactory({ db })
|
||||
})
|
||||
|
||||
await requestEmailVerification(user.id)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { buildApp, truncateTables } from '@/test/hooks'
|
||||
import request from 'supertest'
|
||||
import { expect } from 'chai'
|
||||
import {
|
||||
deleteOldAndInsertNewVerificationFactory,
|
||||
deleteVerificationsFactory,
|
||||
getPendingTokenFactory
|
||||
} from '@/modules/emails/repositories'
|
||||
@@ -11,7 +12,6 @@ import {
|
||||
getPendingEmailVerificationStatus,
|
||||
requestVerification
|
||||
} from '@/test/graphql/users'
|
||||
import { requestEmailVerification } from '@/modules/emails/services/verification/request'
|
||||
import { getEmailVerificationFinalizationRoute } from '@/modules/core/helpers/routeHelper'
|
||||
import { Express } from 'express'
|
||||
import { getUser } from '@/modules/core/repositories/users'
|
||||
@@ -24,10 +24,21 @@ import {
|
||||
} from '@/test/graphqlHelper'
|
||||
import { buildApolloServer } from '@/app'
|
||||
import { db } from '@/db/knex'
|
||||
import { requestEmailVerificationFactory } from '@/modules/emails/services/verification/request'
|
||||
import { getServerInfo } from '@/modules/core/services/generic'
|
||||
import { findPrimaryEmailForUserFactory } from '@/modules/core/repositories/userEmails'
|
||||
|
||||
const mailerMock = EmailSendingServiceMock
|
||||
const getPendingToken = getPendingTokenFactory({ db })
|
||||
const deleteVerifications = deleteVerificationsFactory({ db })
|
||||
const requestEmailVerification = requestEmailVerificationFactory({
|
||||
getUser,
|
||||
getServerInfo,
|
||||
deleteOldAndInsertNewVerification: deleteOldAndInsertNewVerificationFactory({
|
||||
db
|
||||
}),
|
||||
findPrimaryEmailForUser: findPrimaryEmailForUserFactory({ db })
|
||||
})
|
||||
|
||||
const cleanup = async () => {
|
||||
await truncateTables([Users.name, EmailVerifications.name, UserEmails.name])
|
||||
|
||||
Reference in New Issue
Block a user