diff --git a/packages/core/src/lib/social.ts b/packages/core/src/lib/social.ts index cbbca6a9f..c304dfbf7 100644 --- a/packages/core/src/lib/social.ts +++ b/packages/core/src/lib/social.ts @@ -8,12 +8,7 @@ import { getLogtoConnectorById } from '@/connectors'; import type { SocialUserInfo } from '@/connectors/types'; import { socialUserInfoGuard } from '@/connectors/types'; import RequestError from '@/errors/RequestError'; -import { - findUserByEmail, - findUserByPhone, - hasUserWithEmail, - hasUserWithPhone, -} from '@/queries/user'; +import { findUserByEmail, findUserByPhone } from '@/queries/user'; import assertThat from '@/utils/assert-that'; export type SocialUserInfoSession = { @@ -88,16 +83,20 @@ export const getUserInfoFromInteractionResult = async ( export const findSocialRelatedUser = async ( info: SocialUserInfo ): Promise> => { - if (info.phone && (await hasUserWithPhone(info.phone))) { + if (info.phone) { const user = await findUserByPhone(info.phone); - return [{ type: 'phone', value: info.phone }, user]; + if (user) { + return [{ type: 'phone', value: info.phone }, user]; + } } - if (info.email && (await hasUserWithEmail(info.email))) { + if (info.email) { const user = await findUserByEmail(info.email); - return [{ type: 'email', value: info.email }, user]; + if (user) { + return [{ type: 'email', value: info.email }, user]; + } } return null; diff --git a/packages/core/src/queries/user.ts b/packages/core/src/queries/user.ts index 65ec70c1c..8f0f06899 100644 --- a/packages/core/src/queries/user.ts +++ b/packages/core/src/queries/user.ts @@ -18,14 +18,14 @@ export const findUserByUsername = async (username: string) => `); export const findUserByEmail = async (email: string) => - envSet.pool.one(sql` + envSet.pool.maybeOne(sql` select ${sql.join(Object.values(fields), sql`,`)} from ${table} where lower(${fields.primaryEmail})=lower(${email}) `); export const findUserByPhone = async (phone: string) => - envSet.pool.one(sql` + envSet.pool.maybeOne(sql` select ${sql.join(Object.values(fields), sql`,`)} from ${table} where ${fields.primaryPhone}=${phone} diff --git a/packages/core/src/routes/session/middleware/passwordless-action.ts b/packages/core/src/routes/session/middleware/passwordless-action.ts index 82c517bef..d44cd1702 100644 --- a/packages/core/src/routes/session/middleware/passwordless-action.ts +++ b/packages/core/src/routes/session/middleware/passwordless-action.ts @@ -53,12 +53,8 @@ export const smsSignInAction = mockUser); const findUserById = jest.fn(async (): Promise => mockUser); -const findUserByEmail = jest.fn(async (): Promise => mockUser); +const findUserByEmail = jest.fn(async (): Promise> => mockUser); +const findUserByPhone = jest.fn(async (): Promise> => mockUser); const updateUserById = jest.fn(async (..._args: unknown[]) => mockUser); const findDefaultSignInExperience = jest.fn(async () => ({ ...mockSignInExperience, @@ -34,7 +36,7 @@ jest.mock('@/lib/user', () => ({ jest.mock('@/queries/user', () => ({ findUserById: async () => findUserById(), - findUserByPhone: async () => mockUser, + findUserByPhone: async () => findUserByPhone(), findUserByEmail: async () => findUserByEmail(), updateUserById: async (...args: unknown[]) => updateUserById(...args), hasUser: async (username: string) => username === 'username1', @@ -260,6 +262,7 @@ describe('session -> passwordlessRoutes', () => { }); it('throw 404 (with flow `forgot-password`)', async () => { + findUserByPhone.mockResolvedValueOnce(null); const response = await sessionRequest .post('/session/passwordless/sms/verify') .send({ phone: '13000000001', code: '1234', flow: PasscodeType.ForgotPassword }); @@ -358,6 +361,7 @@ describe('session -> passwordlessRoutes', () => { it('throw 404 (with flow `forgot-password`)', async () => { const fakeTime = new Date(); jest.useFakeTimers().setSystemTime(fakeTime); + findUserByEmail.mockResolvedValueOnce(null); const response = await sessionRequest .post('/session/passwordless/email/verify') .send({ email: 'b@a.com', code: '1234', flow: PasscodeType.ForgotPassword }); @@ -501,6 +505,7 @@ describe('session -> passwordlessRoutes', () => { }, }, }); + findUserByPhone.mockResolvedValueOnce(null); const response = await sessionRequest.post(`${signInRoute}/sms`); expect(response.statusCode).toEqual(404); }); @@ -639,6 +644,7 @@ describe('session -> passwordlessRoutes', () => { }, }, }); + findUserByEmail.mockResolvedValueOnce(null); const response = await sessionRequest.post(`${signInRoute}/email`); expect(response.statusCode).toEqual(404); }); diff --git a/packages/core/src/routes/session/passwordless.ts b/packages/core/src/routes/session/passwordless.ts index e2f1686c0..c39ba6e0b 100644 --- a/packages/core/src/routes/session/passwordless.ts +++ b/packages/core/src/routes/session/passwordless.ts @@ -6,12 +6,7 @@ import { object, string } from 'zod'; import RequestError from '@/errors/RequestError'; import { createPasscode, sendPasscode, verifyPasscode } from '@/lib/passcode'; import koaGuard from '@/middleware/koa-guard'; -import { - findUserByEmail, - findUserByPhone, - hasUserWithEmail, - hasUserWithPhone, -} from '@/queries/user'; +import { findUserByEmail, findUserByPhone } from '@/queries/user'; import { passcodeTypeGuard } from '@/routes/session/types'; import assertThat from '@/utils/assert-that'; @@ -105,13 +100,10 @@ export default function passwordlessRoutes( await verifyPasscode(jti, flow, code, { phone }); if (flow === PasscodeType.ForgotPassword) { - assertThat( - await hasUserWithPhone(phone), - new RequestError({ code: 'user.phone_not_exists', status: 404 }) - ); + const user = await findUserByPhone(phone); + assertThat(user, new RequestError({ code: 'user.phone_not_exists', status: 404 })); - const { id } = await findUserByPhone(phone); - await assignVerificationResult(ctx, provider, { flow, userId: id }); + await assignVerificationResult(ctx, provider, { flow, userId: user.id }); ctx.status = 204; return next(); @@ -156,14 +148,11 @@ export default function passwordlessRoutes( await verifyPasscode(jti, flow, code, { email }); if (flow === PasscodeType.ForgotPassword) { - assertThat( - await hasUserWithEmail(email), - new RequestError({ code: 'user.email_not_exists', status: 404 }) - ); + const user = await findUserByEmail(email); - const { id } = await findUserByEmail(email); + assertThat(user, new RequestError({ code: 'user.email_not_exists', status: 404 })); - await assignVerificationResult(ctx, provider, { flow, userId: id }); + await assignVerificationResult(ctx, provider, { flow, userId: user.id }); ctx.status = 204; return next();