From bb964cd4577060ce9e32b622cfd5b92fab9c6b4b Mon Sep 17 00:00:00 2001 From: Alessandro Magionami Date: Wed, 10 Jul 2024 12:11:22 +0200 Subject: [PATCH] feat(user-emails): mark user email as verified --- .../server/modules/core/repositories/users.ts | 5 +++ .../tests/integration/user-emails.spec.ts | 21 +++++++++++- .../modules/user-emails/domain/operations.ts | 6 ++-- .../user-emails/services/verification.ts | 10 ++++++ .../tests/integration/verification.spec.ts | 32 +++++++++++++++++++ 5 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 packages/server/modules/user-emails/services/verification.ts create mode 100644 packages/server/modules/user-emails/tests/integration/verification.spec.ts diff --git a/packages/server/modules/core/repositories/users.ts b/packages/server/modules/core/repositories/users.ts index 1dc7bfbcb..2fed1706a 100644 --- a/packages/server/modules/core/repositories/users.ts +++ b/packages/server/modules/core/repositories/users.ts @@ -8,6 +8,7 @@ import { Knex } from 'knex' import { Roles, ServerRoles } from '@speckle/shared' import { updateUserEmailFactory } from '@/modules/user-emails/repositories/userEmails' import knexInstance from '@/db/knex' +import { markUserEmailAsVerifiedFactory } from '@/modules/user-emails/services/verification' export type UserWithOptionalRole = User & { /** @@ -163,6 +164,10 @@ export async function markUserAsVerified(email: string) { [UserCols.verified]: true }) + await markUserEmailAsVerifiedFactory({ + updateUserEmail: updateUserEmailFactory({ db: knexInstance }) + })(email.toLowerCase().trim()) + return !!(await q) } diff --git a/packages/server/modules/core/tests/integration/user-emails.spec.ts b/packages/server/modules/core/tests/integration/user-emails.spec.ts index 46fb7cc3f..afb2a089a 100644 --- a/packages/server/modules/core/tests/integration/user-emails.spec.ts +++ b/packages/server/modules/core/tests/integration/user-emails.spec.ts @@ -2,10 +2,13 @@ import { before } from 'mocha' import { createUser } from '@/modules/core/services/users' import { beforeEachContext } from '@/test/hooks' import { expect } from 'chai' -import { getUserByEmail } from '@/modules/core/repositories/users' +import { getUserByEmail, markUserAsVerified } from '@/modules/core/repositories/users' import { deleteUserEmailFactory } from '@/modules/user-emails/repositories/userEmails' import knexInstance from '@/db/knex' import { createRandomEmail, createRandomPassword } from '../../helpers/test-helpers' +import { USER_EMAILS_TABLE_NAME } from '@/modules/user-emails/constants' + +const userEmailTable = knexInstance(USER_EMAILS_TABLE_NAME) describe('Core @user-emails', () => { before(async () => { @@ -34,4 +37,20 @@ describe('Core @user-emails', () => { expect(user.email).to.eq(email) }) }) + + describe('markUserEmailAsVerified', () => { + it('should mark user email as verified', async () => { + const email = createRandomEmail() + await createUser({ + name: 'John Doe', + email, + password: createRandomPassword() + }) + + await markUserAsVerified(email) + + const userEmail = await userEmailTable.where({ email }).first() + expect(userEmail.verified).to.be.true + }) + }) }) diff --git a/packages/server/modules/user-emails/domain/operations.ts b/packages/server/modules/user-emails/domain/operations.ts index 5dc16a962..878aed458 100644 --- a/packages/server/modules/user-emails/domain/operations.ts +++ b/packages/server/modules/user-emails/domain/operations.ts @@ -6,9 +6,9 @@ export type CreateUserEmail = ( export type UpdateUserEmail = ( query: - | (Pick & { primary?: boolean }) + | (Pick & { primary?: boolean }) | (Pick & { primary: true }), - update: Pick, 'email' | 'primary'> + update: Pick, 'email' | 'primary' | 'verified'> ) => Promise export type DeleteUserEmail = ({ @@ -18,3 +18,5 @@ export type DeleteUserEmail = ({ userId: string email: string }) => Promise + +export type MarkUserEmailAsVerified = (email: string) => Promise diff --git a/packages/server/modules/user-emails/services/verification.ts b/packages/server/modules/user-emails/services/verification.ts new file mode 100644 index 000000000..6b7726fe1 --- /dev/null +++ b/packages/server/modules/user-emails/services/verification.ts @@ -0,0 +1,10 @@ +import { MarkUserEmailAsVerified, UpdateUserEmail } from '../domain/operations' + +export const markUserEmailAsVerifiedFactory = + ({ + updateUserEmail + }: { + updateUserEmail: UpdateUserEmail + }): MarkUserEmailAsVerified => + async (email) => + updateUserEmail({ email }, { verified: true }) diff --git a/packages/server/modules/user-emails/tests/integration/verification.spec.ts b/packages/server/modules/user-emails/tests/integration/verification.spec.ts new file mode 100644 index 000000000..0bb872805 --- /dev/null +++ b/packages/server/modules/user-emails/tests/integration/verification.spec.ts @@ -0,0 +1,32 @@ +import { describe } from 'mocha' +import { updateUserEmailFactory } from '../../repositories/userEmails' +import knexInstance from '@/db/knex' +import { createUser } from '@/modules/core/services/users' +import { + createRandomEmail, + createRandomPassword +} from '@/modules/core/helpers/test-helpers' +import { USER_EMAILS_TABLE_NAME } from '../../constants' +import { markUserEmailAsVerifiedFactory } from '../../services/verification' +import { expect } from 'chai' + +const userEmailTable = knexInstance(USER_EMAILS_TABLE_NAME) + +describe('Verification @user-emails', () => { + it('should mark user email as verified', async () => { + const email = createRandomEmail() + + await createUser({ + name: 'John', + email, + password: createRandomPassword() + }) + + await markUserEmailAsVerifiedFactory({ + updateUserEmail: updateUserEmailFactory({ db: knexInstance }) + })(email) + + const userEmail = await userEmailTable.where({ email }).first() + expect(userEmail.verified).to.be.true + }) +})