From 06ec86d831f8bcb4e98067a12d092c566188fc4f Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Wed, 28 Dec 2022 14:28:46 +0800 Subject: [PATCH] refactor: rename `MessageTypes` -> `VerificationCodeType` (#2745) --- packages/core/src/__mocks__/index.ts | 4 +- packages/core/src/connectors/types.ts | 4 +- packages/core/src/libraries/passcode.test.ts | 18 +-- packages/core/src/libraries/passcode.ts | 14 ++- packages/core/src/queries/passcode.test.ts | 6 +- packages/core/src/queries/passcode.ts | 9 +- packages/core/src/routes/connector.test.ts | 6 +- packages/core/src/routes/connector.ts | 4 +- .../utils/passcode-validation.test.ts | 14 +-- .../interaction/utils/passcode-validation.ts | 20 ++-- .../core/src/routes/session/continue.test.ts | 6 +- .../routes/session/forgot-password.test.ts | 18 +-- .../session/middleware/passwordless-action.ts | 10 +- .../src/routes/session/passwordless.test.ts | 110 +++++++++--------- .../core/src/routes/session/passwordless.ts | 14 +-- packages/core/src/routes/session/types.ts | 14 +-- packages/core/src/routes/session/utils.ts | 4 +- packages/integration-tests/src/api/session.ts | 18 +-- packages/toolkit/connector-kit/src/types.ts | 19 ++- 19 files changed, 166 insertions(+), 146 deletions(-) diff --git a/packages/core/src/__mocks__/index.ts b/packages/core/src/__mocks__/index.ts index 2f9929f99..43119ae93 100644 --- a/packages/core/src/__mocks__/index.ts +++ b/packages/core/src/__mocks__/index.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import type { Application, Passcode, Resource, Role, Setting } from '@logto/schemas'; import { ApplicationType } from '@logto/schemas'; @@ -55,7 +55,7 @@ export const mockPasscode: Passcode = { interactionJti: 'jti', phone: '888 888 8888', email: 'foo@logto.io', - type: MessageTypes.SignIn, + type: VerificationCodeType.SignIn, code: 'asdfghjkl', consumed: false, tryCount: 2, diff --git a/packages/core/src/connectors/types.ts b/packages/core/src/connectors/types.ts index 501849bb0..8dc51c23e 100644 --- a/packages/core/src/connectors/types.ts +++ b/packages/core/src/connectors/types.ts @@ -1,10 +1,10 @@ -import type { AllConnector, CreateConnector, MessageTypes } from '@logto/connector-kit'; +import type { AllConnector, CreateConnector, VerificationCodeType } from '@logto/connector-kit'; import type { Connector } from '@logto/schemas'; import { z } from 'zod'; export { ConnectorType } from '@logto/schemas'; -export type TemplateType = MessageTypes; +export type TemplateType = VerificationCodeType; export const socialUserInfoGuard = z.object({ id: z.string(), diff --git a/packages/core/src/libraries/passcode.test.ts b/packages/core/src/libraries/passcode.test.ts index 2f3e27ae2..196440716 100644 --- a/packages/core/src/libraries/passcode.test.ts +++ b/packages/core/src/libraries/passcode.test.ts @@ -1,4 +1,4 @@ -import { ConnectorType, MessageTypes } from '@logto/connector-kit'; +import { ConnectorType, VerificationCodeType } from '@logto/connector-kit'; import { Passcode } from '@logto/schemas'; import { createMockUtils } from '@logto/shared/esm'; import { any } from 'zod'; @@ -60,7 +60,7 @@ afterEach(() => { describe('createPasscode', () => { it('should generate `passcodeLength` digits code for phone and insert to database', async () => { const phone = '13000000000'; - const passcode = await createPasscode('jti', MessageTypes.SignIn, { + const passcode = await createPasscode('jti', VerificationCodeType.SignIn, { phone, }); expect(new RegExp(`^\\d{${passcodeLength}}$`).test(passcode.code)).toBeTruthy(); @@ -69,7 +69,7 @@ describe('createPasscode', () => { it('should generate `passcodeLength` digits code for email and insert to database', async () => { const email = 'jony@example.com'; - const passcode = await createPasscode('jti', MessageTypes.SignIn, { + const passcode = await createPasscode('jti', VerificationCodeType.SignIn, { email, }); expect(new RegExp(`^\\d{${passcodeLength}}$`).test(passcode.code)).toBeTruthy(); @@ -84,7 +84,7 @@ describe('createPasscode', () => { id: 'id', interactionJti: jti, code: '1234', - type: MessageTypes.SignIn, + type: VerificationCodeType.SignIn, createdAt: Date.now(), phone: '', email, @@ -92,7 +92,7 @@ describe('createPasscode', () => { tryCount: 0, }, ]); - await createPasscode(jti, MessageTypes.SignIn, { + await createPasscode(jti, VerificationCodeType.SignIn, { email, }); expect(deletePasscodesByIds).toHaveBeenCalledWith(['id']); @@ -106,7 +106,7 @@ describe('sendPasscode', () => { interactionJti: 'jti', phone: null, email: null, - type: MessageTypes.SignIn, + type: VerificationCodeType.SignIn, code: '1234', consumed: false, tryCount: 0, @@ -139,7 +139,7 @@ describe('sendPasscode', () => { interactionJti: 'jti', phone: 'phone', email: null, - type: MessageTypes.SignIn, + type: VerificationCodeType.SignIn, code: '1234', consumed: false, tryCount: 0, @@ -190,7 +190,7 @@ describe('sendPasscode', () => { interactionJti: 'jti', phone: 'phone', email: null, - type: MessageTypes.SignIn, + type: VerificationCodeType.SignIn, code: '1234', consumed: false, tryCount: 0, @@ -213,7 +213,7 @@ describe('verifyPasscode', () => { interactionJti: 'jti', phone: 'phone', email: null, - type: MessageTypes.SignIn, + type: VerificationCodeType.SignIn, code: '1234', consumed: false, tryCount: 0, diff --git a/packages/core/src/libraries/passcode.ts b/packages/core/src/libraries/passcode.ts index dc4ca8c2d..b2c4bb528 100644 --- a/packages/core/src/libraries/passcode.ts +++ b/packages/core/src/libraries/passcode.ts @@ -1,5 +1,9 @@ -import type { EmailConnector, MessageTypes, SmsConnector } from '@logto/connector-kit'; -import { messageTypesGuard, ConnectorError, ConnectorErrorCodes } from '@logto/connector-kit'; +import type { EmailConnector, VerificationCodeType, SmsConnector } from '@logto/connector-kit'; +import { + verificationCodeTypeGuard, + ConnectorError, + ConnectorErrorCodes, +} from '@logto/connector-kit'; import type { Passcode } from '@logto/schemas'; import { customAlphabet, nanoid } from 'nanoid'; @@ -22,7 +26,7 @@ const randomCode = customAlphabet('1234567890', passcodeLength); export const createPasscode = async ( jti: string, - type: MessageTypes, + type: VerificationCodeType, payload: { phone: string } | { email: string } ) => { // Disable existing passcodes. @@ -66,7 +70,7 @@ export const sendPasscode = async (passcode: Passcode) => { const { dbEntry, metadata, sendMessage } = connector; - const messageTypeResult = messageTypesGuard.safeParse(passcode.type); + const messageTypeResult = verificationCodeTypeGuard.safeParse(passcode.type); if (!messageTypeResult.success) { throw new ConnectorError(ConnectorErrorCodes.InvalidConfig); @@ -88,7 +92,7 @@ export const passcodeMaxTryCount = 10; export const verifyPasscode = async ( sessionId: string, - type: MessageTypes, + type: VerificationCodeType, code: string, payload: { phone: string } | { email: string } ): Promise => { diff --git a/packages/core/src/queries/passcode.test.ts b/packages/core/src/queries/passcode.test.ts index 1605b0a65..c6f912831 100644 --- a/packages/core/src/queries/passcode.test.ts +++ b/packages/core/src/queries/passcode.test.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import { Passcodes } from '@logto/schemas'; import { convertToIdentifiers, convertToPrimitiveOrSql, excludeAutoSetFields } from '@logto/shared'; import { createMockPool, createMockQueryResult, sql } from 'slonik'; @@ -35,7 +35,7 @@ describe('passcode query', () => { it('findUnconsumedPasscodeByJtiAndType', async () => { const jti = 'foo'; - const type = MessageTypes.SignIn; + const type = VerificationCodeType.SignIn; const expectSql = sql` select ${sql.join(Object.values(fields), sql`, `)} @@ -55,7 +55,7 @@ describe('passcode query', () => { it('findUnconsumedPasscodesByJtiAndType', async () => { const jti = 'foo'; - const type = MessageTypes.SignIn; + const type = VerificationCodeType.SignIn; const expectSql = sql` select ${sql.join(Object.values(fields), sql`, `)} diff --git a/packages/core/src/queries/passcode.ts b/packages/core/src/queries/passcode.ts index 3350faeac..763f1efd1 100644 --- a/packages/core/src/queries/passcode.ts +++ b/packages/core/src/queries/passcode.ts @@ -1,4 +1,4 @@ -import type { MessageTypes } from '@logto/connector-kit'; +import type { VerificationCodeType } from '@logto/connector-kit'; import type { Passcode, CreatePasscode } from '@logto/schemas'; import { Passcodes } from '@logto/schemas'; import { convertToIdentifiers } from '@logto/shared'; @@ -10,14 +10,17 @@ import { DeletionError } from '#src/errors/SlonikError/index.js'; const { table, fields } = convertToIdentifiers(Passcodes); -export const findUnconsumedPasscodeByJtiAndType = async (jti: string, type: MessageTypes) => +export const findUnconsumedPasscodeByJtiAndType = async (jti: string, type: VerificationCodeType) => envSet.pool.maybeOne(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} where ${fields.interactionJti}=${jti} and ${fields.type}=${type} and ${fields.consumed} = false `); -export const findUnconsumedPasscodesByJtiAndType = async (jti: string, type: MessageTypes) => +export const findUnconsumedPasscodesByJtiAndType = async ( + jti: string, + type: VerificationCodeType +) => envSet.pool.any(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} diff --git a/packages/core/src/routes/connector.test.ts b/packages/core/src/routes/connector.test.ts index d3949a20f..35ebd2ca6 100644 --- a/packages/core/src/routes/connector.test.ts +++ b/packages/core/src/routes/connector.test.ts @@ -1,6 +1,6 @@ /* eslint-disable max-lines */ import type { EmailConnector, SmsConnector } from '@logto/connector-kit'; -import { ConnectorPlatform, MessageTypes } from '@logto/connector-kit'; +import { ConnectorPlatform, VerificationCodeType } from '@logto/connector-kit'; import { ConnectorType } from '@logto/schemas'; import { pickDefault, createMockUtils } from '@logto/shared/esm'; import { any } from 'zod'; @@ -390,7 +390,7 @@ describe('connector route', () => { expect(sendMessage).toHaveBeenCalledWith( { to: '12345678901', - type: MessageTypes.Test, + type: VerificationCodeType.Test, payload: { code: '123456', }, @@ -418,7 +418,7 @@ describe('connector route', () => { expect(sendMessage).toHaveBeenCalledWith( { to: 'test@email.com', - type: MessageTypes.Test, + type: VerificationCodeType.Test, payload: { code: 'email-test', }, diff --git a/packages/core/src/routes/connector.ts b/packages/core/src/routes/connector.ts index b4dd499db..9a5ae72a9 100644 --- a/packages/core/src/routes/connector.ts +++ b/packages/core/src/routes/connector.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import { emailRegEx, phoneRegEx, buildIdGenerator } from '@logto/core-kit'; import type { ConnectorFactoryResponse, ConnectorResponse } from '@logto/schemas'; import { arbitraryObjectGuard, Connectors, ConnectorType } from '@logto/schemas'; @@ -282,7 +282,7 @@ export default function connectorRoutes(router: T) { await sendMessage( { to: subject, - type: MessageTypes.Test, + type: VerificationCodeType.Test, payload: { code: phone ? '123456' : 'email-test', }, diff --git a/packages/core/src/routes/interaction/utils/passcode-validation.test.ts b/packages/core/src/routes/interaction/utils/passcode-validation.test.ts index 845e4b68f..ae3177e04 100644 --- a/packages/core/src/routes/interaction/utils/passcode-validation.test.ts +++ b/packages/core/src/routes/interaction/utils/passcode-validation.test.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import { InteractionEvent } from '@logto/schemas'; import { createMockUtils } from '@logto/shared/esm'; @@ -19,27 +19,27 @@ const { sendPasscodeToIdentifier } = await import('./passcode-validation.js'); const sendPasscodeTestCase = [ { payload: { email: 'email', event: InteractionEvent.SignIn }, - createPasscodeParams: [MessageTypes.SignIn, { email: 'email' }], + createPasscodeParams: [VerificationCodeType.SignIn, { email: 'email' }], }, { payload: { email: 'email', event: InteractionEvent.Register }, - createPasscodeParams: [MessageTypes.Register, { email: 'email' }], + createPasscodeParams: [VerificationCodeType.Register, { email: 'email' }], }, { payload: { email: 'email', event: InteractionEvent.ForgotPassword }, - createPasscodeParams: [MessageTypes.ForgotPassword, { email: 'email' }], + createPasscodeParams: [VerificationCodeType.ForgotPassword, { email: 'email' }], }, { payload: { phone: 'phone', event: InteractionEvent.SignIn }, - createPasscodeParams: [MessageTypes.SignIn, { phone: 'phone' }], + createPasscodeParams: [VerificationCodeType.SignIn, { phone: 'phone' }], }, { payload: { phone: 'phone', event: InteractionEvent.Register }, - createPasscodeParams: [MessageTypes.Register, { phone: 'phone' }], + createPasscodeParams: [VerificationCodeType.Register, { phone: 'phone' }], }, { payload: { phone: 'phone', event: InteractionEvent.ForgotPassword }, - createPasscodeParams: [MessageTypes.ForgotPassword, { phone: 'phone' }], + createPasscodeParams: [VerificationCodeType.ForgotPassword, { phone: 'phone' }], }, ]; diff --git a/packages/core/src/routes/interaction/utils/passcode-validation.ts b/packages/core/src/routes/interaction/utils/passcode-validation.ts index f74e85714..5d4c5a518 100644 --- a/packages/core/src/routes/interaction/utils/passcode-validation.ts +++ b/packages/core/src/routes/interaction/utils/passcode-validation.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import type { InteractionEvent } from '@logto/schemas'; import { createPasscode, sendPasscode, verifyPasscode } from '#src/libraries/passcode.js'; @@ -8,16 +8,16 @@ import type { SendPasscodePayload, PasscodeIdentifierPayload } from '../types/in /** * Refactor Needed: - * This is a work around to map the latest interaction event type to old MessageTypes + * This is a work around to map the latest interaction event type to old VerificationCodeType * */ -const eventToMessageTypesMap: Record = { - SignIn: MessageTypes.SignIn, - Register: MessageTypes.Register, - ForgotPassword: MessageTypes.ForgotPassword, +const eventToVerificationCodeTypeMap: Record = { + SignIn: VerificationCodeType.SignIn, + Register: VerificationCodeType.Register, + ForgotPassword: VerificationCodeType.ForgotPassword, }; -const getMessageTypesByEvent = (event: InteractionEvent): MessageTypes => - eventToMessageTypesMap[event]; +const getVerificationCodeTypeByEvent = (event: InteractionEvent): VerificationCodeType => + eventToVerificationCodeTypeMap[event]; export const sendPasscodeToIdentifier = async ( payload: SendPasscodePayload & { event: InteractionEvent }, @@ -25,7 +25,7 @@ export const sendPasscodeToIdentifier = async ( createLog: LogContext['createLog'] ) => { const { event, ...identifier } = payload; - const messageType = getMessageTypesByEvent(event); + const messageType = getVerificationCodeTypeByEvent(event); const log = createLog(`Interaction.${event}.Identifier.VerificationCode.Create`); log.append(identifier); @@ -42,7 +42,7 @@ export const verifyIdentifierByPasscode = async ( createLog: LogContext['createLog'] ) => { const { event, passcode, ...identifier } = payload; - const messageType = getMessageTypesByEvent(event); + const messageType = getVerificationCodeTypeByEvent(event); // TODO: @Simeng maybe we should just log all interaction payload in every request? const log = createLog(`Interaction.${event}.Identifier.VerificationCode.Submit`); diff --git a/packages/core/src/routes/session/continue.test.ts b/packages/core/src/routes/session/continue.test.ts index 1f14c0b74..b47bc4000 100644 --- a/packages/core/src/routes/session/continue.test.ts +++ b/packages/core/src/routes/session/continue.test.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import { addDays, subSeconds } from 'date-fns'; import { Provider } from 'oidc-provider'; @@ -140,7 +140,7 @@ describe('session -> continueRoutes', () => { continueSignIn: { userId: mockUser.id, expiresAt: getTomorrowIsoString(), - type: MessageTypes.Continue, + type: VerificationCodeType.Continue, }, }, }); @@ -172,7 +172,7 @@ describe('session -> continueRoutes', () => { continueSignIn: { userId: mockUser.id, expiresAt: getTomorrowIsoString(), - type: MessageTypes.Continue, + type: VerificationCodeType.Continue, }, }, }); diff --git a/packages/core/src/routes/session/forgot-password.test.ts b/packages/core/src/routes/session/forgot-password.test.ts index 7cc2a843d..212cac71f 100644 --- a/packages/core/src/routes/session/forgot-password.test.ts +++ b/packages/core/src/routes/session/forgot-password.test.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import type { User } from '@logto/schemas'; import { addDays, subDays } from 'date-fns'; import { Provider } from 'oidc-provider'; @@ -97,7 +97,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getTomorrowDate().toISOString(), - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, }, }, }); @@ -118,7 +118,7 @@ describe('session -> forgotPasswordRoutes', () => { result: { verification: { expiresAt: getTomorrowDate().toISOString(), - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, }, }, }); @@ -134,7 +134,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getTomorrowDate().toISOString(), - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, }, }, }); @@ -147,7 +147,7 @@ describe('session -> forgotPasswordRoutes', () => { it('should throw when `verification.expiresAt` is not string', async () => { interactionDetails.mockResolvedValueOnce({ result: { - verification: { userId: 'id', expiresAt: 0, flow: MessageTypes.ForgotPassword }, + verification: { userId: 'id', expiresAt: 0, flow: VerificationCodeType.ForgotPassword }, }, }); const response = await sessionRequest @@ -162,7 +162,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: 'invalid date string', - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, }, }, }); @@ -178,7 +178,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getYesterdayDate().toISOString(), - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, }, }, }); @@ -194,7 +194,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getTomorrowDate().toISOString(), - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, }, }, }); @@ -211,7 +211,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getTomorrowDate().toISOString(), - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, }, }, }); diff --git a/packages/core/src/routes/session/middleware/passwordless-action.ts b/packages/core/src/routes/session/middleware/passwordless-action.ts index af2daa4ae..617b60a43 100644 --- a/packages/core/src/routes/session/middleware/passwordless-action.ts +++ b/packages/core/src/routes/session/middleware/passwordless-action.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import { SignInIdentifier } from '@logto/schemas'; import type { MiddlewareType } from 'koa'; import type { Provider } from 'oidc-provider'; @@ -52,7 +52,7 @@ export const smsSignInAction = passwordlessRoutes', () => { it('should call sendPasscode (with flow `sign-in`)', async () => { const response = await sessionRequest .post('/session/passwordless/sms/send') - .send({ phone: '13000000000', flow: MessageTypes.SignIn }); + .send({ phone: '13000000000', flow: VerificationCodeType.SignIn }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.SignIn, { + expect(createPasscode).toHaveBeenCalledWith('jti', VerificationCodeType.SignIn, { phone: '13000000000', }); expect(sendPasscode).toHaveBeenCalled(); @@ -118,9 +118,9 @@ describe('session -> passwordlessRoutes', () => { it('should call sendPasscode (with flow `register`)', async () => { const response = await sessionRequest .post('/session/passwordless/sms/send') - .send({ phone: '13000000000', flow: MessageTypes.Register }); + .send({ phone: '13000000000', flow: VerificationCodeType.Register }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.Register, { + expect(createPasscode).toHaveBeenCalledWith('jti', VerificationCodeType.Register, { phone: '13000000000', }); expect(sendPasscode).toHaveBeenCalled(); @@ -128,9 +128,9 @@ describe('session -> passwordlessRoutes', () => { it('should call sendPasscode (with flow `forgot-password`)', async () => { const response = await sessionRequest .post('/session/passwordless/sms/send') - .send({ phone: '13000000000', flow: MessageTypes.ForgotPassword }); + .send({ phone: '13000000000', flow: VerificationCodeType.ForgotPassword }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.ForgotPassword, { + expect(createPasscode).toHaveBeenCalledWith('jti', VerificationCodeType.ForgotPassword, { phone: '13000000000', }); expect(sendPasscode).toHaveBeenCalled(); @@ -138,7 +138,7 @@ describe('session -> passwordlessRoutes', () => { it('throw when phone not given in input params', async () => { const response = await sessionRequest .post('/session/passwordless/sms/send') - .send({ flow: MessageTypes.Register }); + .send({ flow: VerificationCodeType.Register }); expect(response.statusCode).toEqual(400); }); }); @@ -152,9 +152,9 @@ describe('session -> passwordlessRoutes', () => { it('should call sendPasscode (with flow `sign-in`)', async () => { const response = await sessionRequest .post('/session/passwordless/email/send') - .send({ email: 'a@a.com', flow: MessageTypes.SignIn }); + .send({ email: 'a@a.com', flow: VerificationCodeType.SignIn }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.SignIn, { + expect(createPasscode).toHaveBeenCalledWith('jti', VerificationCodeType.SignIn, { email: 'a@a.com', }); expect(sendPasscode).toHaveBeenCalled(); @@ -162,9 +162,9 @@ describe('session -> passwordlessRoutes', () => { it('should call sendPasscode (with flow `register`)', async () => { const response = await sessionRequest .post('/session/passwordless/email/send') - .send({ email: 'a@a.com', flow: MessageTypes.Register }); + .send({ email: 'a@a.com', flow: VerificationCodeType.Register }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.Register, { + expect(createPasscode).toHaveBeenCalledWith('jti', VerificationCodeType.Register, { email: 'a@a.com', }); expect(sendPasscode).toHaveBeenCalled(); @@ -172,9 +172,9 @@ describe('session -> passwordlessRoutes', () => { it('should call sendPasscode (with flow `forgot-password`)', async () => { const response = await sessionRequest .post('/session/passwordless/email/send') - .send({ email: 'a@a.com', flow: MessageTypes.ForgotPassword }); + .send({ email: 'a@a.com', flow: VerificationCodeType.ForgotPassword }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.ForgotPassword, { + expect(createPasscode).toHaveBeenCalledWith('jti', VerificationCodeType.ForgotPassword, { email: 'a@a.com', }); expect(sendPasscode).toHaveBeenCalled(); @@ -182,7 +182,7 @@ describe('session -> passwordlessRoutes', () => { it('throw when email not given in input params', async () => { const response = await sessionRequest .post('/session/passwordless/email/send') - .send({ flow: MessageTypes.Register }); + .send({ flow: VerificationCodeType.Register }); expect(response.statusCode).toEqual(400); }); }); @@ -204,14 +204,14 @@ describe('session -> passwordlessRoutes', () => { await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000000', code: '1234', flow: MessageTypes.SignIn }); + .send({ phone: '13000000000', code: '1234', flow: VerificationCodeType.SignIn }); expect(interactionResult).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.objectContaining({ verification: { - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, phone: '13000000000', expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), }, @@ -228,14 +228,14 @@ describe('session -> passwordlessRoutes', () => { await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000000', code: '1234', flow: MessageTypes.Register }); + .send({ phone: '13000000000', code: '1234', flow: VerificationCodeType.Register }); expect(interactionResult).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.objectContaining({ verification: { - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, phone: '13000000000', expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), }, @@ -251,7 +251,7 @@ describe('session -> passwordlessRoutes', () => { const response = await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000000', code: '1234', flow: MessageTypes.ForgotPassword }); + .send({ phone: '13000000000', code: '1234', flow: VerificationCodeType.ForgotPassword }); expect(response.statusCode).toEqual(204); @@ -262,7 +262,7 @@ describe('session -> passwordlessRoutes', () => { verification: { userId: mockUser.id, expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, }, }) ); @@ -272,7 +272,7 @@ describe('session -> passwordlessRoutes', () => { findUserByPhone.mockResolvedValueOnce(null); const response = await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000001', code: '1234', flow: MessageTypes.ForgotPassword }); + .send({ phone: '13000000001', code: '1234', flow: VerificationCodeType.ForgotPassword }); expect(response.statusCode).toEqual(404); expect(interactionResult).toHaveBeenCalledTimes(0); }); @@ -280,7 +280,7 @@ describe('session -> passwordlessRoutes', () => { it('throw when code is wrong', async () => { const response = await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000000', code: '1231', flow: MessageTypes.SignIn }); + .send({ phone: '13000000000', code: '1231', flow: VerificationCodeType.SignIn }); expect(response.statusCode).toEqual(400); }); }); @@ -302,14 +302,14 @@ describe('session -> passwordlessRoutes', () => { await sessionRequest .post('/session/passwordless/email/verify') - .send({ email: 'a@a.com', code: '1234', flow: MessageTypes.SignIn }); + .send({ email: 'a@a.com', code: '1234', flow: VerificationCodeType.SignIn }); expect(interactionResult).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.objectContaining({ verification: { - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, email: 'a@a.com', expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), }, @@ -325,14 +325,14 @@ describe('session -> passwordlessRoutes', () => { await sessionRequest .post('/session/passwordless/email/verify') - .send({ email: 'a@a.com', code: '1234', flow: MessageTypes.Register }); + .send({ email: 'a@a.com', code: '1234', flow: VerificationCodeType.Register }); expect(interactionResult).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.objectContaining({ verification: { - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, email: 'a@a.com', expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), }, @@ -348,7 +348,7 @@ describe('session -> passwordlessRoutes', () => { const response = await sessionRequest .post('/session/passwordless/email/verify') - .send({ email: 'a@a.com', code: '1234', flow: MessageTypes.ForgotPassword }); + .send({ email: 'a@a.com', code: '1234', flow: VerificationCodeType.ForgotPassword }); expect(response.statusCode).toEqual(204); @@ -359,7 +359,7 @@ describe('session -> passwordlessRoutes', () => { verification: { userId: mockUser.id, expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, }, }) ); @@ -371,7 +371,7 @@ describe('session -> passwordlessRoutes', () => { findUserByEmail.mockResolvedValueOnce(null); const response = await sessionRequest .post('/session/passwordless/email/verify') - .send({ email: 'b@a.com', code: '1234', flow: MessageTypes.ForgotPassword }); + .send({ email: 'b@a.com', code: '1234', flow: VerificationCodeType.ForgotPassword }); expect(response.statusCode).toEqual(404); expect(interactionResult).toHaveBeenCalledTimes(0); }); @@ -379,7 +379,7 @@ describe('session -> passwordlessRoutes', () => { it('throw when code is wrong', async () => { const response = await sessionRequest .post('/session/passwordless/email/verify') - .send({ email: 'a@a.com', code: '1231', flow: MessageTypes.SignIn }); + .send({ email: 'a@a.com', code: '1231', flow: VerificationCodeType.SignIn }); expect(response.statusCode).toEqual(400); }); }); @@ -390,7 +390,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -414,7 +414,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -449,7 +449,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, expiresAt: getTomorrowIsoString(), }, }, @@ -463,7 +463,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: 'invalid date string', }, }, @@ -477,7 +477,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: subDays(Date.now(), 1).toISOString(), }, }, @@ -491,7 +491,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'XX@foo', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -505,7 +505,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000001', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -524,7 +524,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -572,7 +572,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -596,7 +596,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -633,7 +633,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, expiresAt: getTomorrowIsoString(), }, }, @@ -646,7 +646,7 @@ describe('session -> passwordlessRoutes', () => { interactionDetails.mockResolvedValueOnce({ result: { verification: { - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -660,7 +660,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'b@a.com', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -679,7 +679,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -726,7 +726,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000001', - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -748,7 +748,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000001', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -783,7 +783,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000001', - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, expiresAt: getTomorrowIsoString(), }, }, @@ -796,7 +796,7 @@ describe('session -> passwordlessRoutes', () => { interactionDetails.mockResolvedValueOnce({ result: { verification: { - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -810,7 +810,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -854,7 +854,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'b@a.com', - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -876,7 +876,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'b@a.com', - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -911,7 +911,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'b@a.com', - flow: MessageTypes.ForgotPassword, + flow: VerificationCodeType.ForgotPassword, expiresAt: getTomorrowIsoString(), }, }, @@ -924,7 +924,7 @@ describe('session -> passwordlessRoutes', () => { interactionDetails.mockResolvedValueOnce({ result: { verification: { - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -938,7 +938,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, expiresAt: getTomorrowIsoString(), }, }, diff --git a/packages/core/src/routes/session/passwordless.ts b/packages/core/src/routes/session/passwordless.ts index 27b432010..0e722c2fc 100644 --- a/packages/core/src/routes/session/passwordless.ts +++ b/packages/core/src/routes/session/passwordless.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import { emailRegEx, phoneRegEx } from '@logto/core-kit'; import type { Provider } from 'oidc-provider'; import { object, string } from 'zod'; @@ -103,7 +103,7 @@ export default function passwordlessRoutes( await verifyPasscode(jti, flow, code, { phone }); - if (flow === MessageTypes.ForgotPassword) { + if (flow === VerificationCodeType.ForgotPassword) { const user = await findUserByPhone(phone); assertThat(user, new RequestError({ code: 'user.phone_not_exist', status: 404 })); @@ -113,13 +113,13 @@ export default function passwordlessRoutes( return next(); } - if (flow === MessageTypes.SignIn) { + if (flow === VerificationCodeType.SignIn) { await assignVerificationResult(ctx, provider, { flow, phone }); return smsSignInAction(provider)(ctx, next); } - if (flow === MessageTypes.Register) { + if (flow === VerificationCodeType.Register) { await assignVerificationResult(ctx, provider, { flow, phone }); return smsRegisterAction(provider)(ctx, next); @@ -152,7 +152,7 @@ export default function passwordlessRoutes( await verifyPasscode(jti, flow, code, { email }); - if (flow === MessageTypes.ForgotPassword) { + if (flow === VerificationCodeType.ForgotPassword) { const user = await findUserByEmail(email); assertThat(user, new RequestError({ code: 'user.email_not_exist', status: 404 })); @@ -163,13 +163,13 @@ export default function passwordlessRoutes( return next(); } - if (flow === MessageTypes.SignIn) { + if (flow === VerificationCodeType.SignIn) { await assignVerificationResult(ctx, provider, { flow, email }); return emailSignInAction(provider)(ctx, next); } - if (flow === MessageTypes.Register) { + if (flow === VerificationCodeType.Register) { await assignVerificationResult(ctx, provider, { flow, email }); return emailRegisterAction(provider)(ctx, next); diff --git a/packages/core/src/routes/session/types.ts b/packages/core/src/routes/session/types.ts index e2407b6b2..9866f99b7 100644 --- a/packages/core/src/routes/session/types.ts +++ b/packages/core/src/routes/session/types.ts @@ -1,9 +1,9 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import { pick } from '@silverhand/essentials'; import { z } from 'zod'; export const flowTypeGuard = z.nativeEnum( - pick(MessageTypes, 'Continue', 'ForgotPassword', 'Register', 'SignIn') + pick(VerificationCodeType, 'Continue', 'ForgotPassword', 'Register', 'SignIn') ); export const methodGuard = z.enum(['email', 'sms']); @@ -15,7 +15,7 @@ export const operationGuard = z.enum(['send', 'verify']); export type Operation = z.infer; const smsSessionStorageGuard = z.object({ - flow: z.literal(MessageTypes.SignIn).or(z.literal(MessageTypes.Register)), + flow: z.literal(VerificationCodeType.SignIn).or(z.literal(VerificationCodeType.Register)), expiresAt: z.string(), phone: z.string(), }); @@ -25,7 +25,7 @@ export type SmsSessionStorage = z.infer; export const smsSessionResultGuard = z.object({ verification: smsSessionStorageGuard }); const emailSessionStorageGuard = z.object({ - flow: z.literal(MessageTypes.SignIn).or(z.literal(MessageTypes.Register)), + flow: z.literal(VerificationCodeType.SignIn).or(z.literal(VerificationCodeType.Register)), expiresAt: z.string(), email: z.string(), }); @@ -37,7 +37,7 @@ export const emailSessionResultGuard = z.object({ }); const forgotPasswordSessionStorageGuard = z.object({ - flow: z.literal(MessageTypes.ForgotPassword), + flow: z.literal(VerificationCodeType.ForgotPassword), expiresAt: z.string(), userId: z.string(), }); @@ -49,7 +49,7 @@ export const forgotPasswordSessionResultGuard = z.object({ }); const continueEmailSessionStorageGuard = z.object({ - flow: z.literal(MessageTypes.Continue), + flow: z.literal(VerificationCodeType.Continue), expiresAt: z.string(), email: z.string(), }); @@ -61,7 +61,7 @@ export const continueEmailSessionResultGuard = z.object({ }); const continueSmsSessionStorageGuard = z.object({ - flow: z.literal(MessageTypes.Continue), + flow: z.literal(VerificationCodeType.Continue), expiresAt: z.string(), phone: z.string(), }); diff --git a/packages/core/src/routes/session/utils.ts b/packages/core/src/routes/session/utils.ts index 5fa209aff..4030626f6 100644 --- a/packages/core/src/routes/session/utils.ts +++ b/packages/core/src/routes/session/utils.ts @@ -1,4 +1,4 @@ -import type { MessageTypes } from '@logto/connector-kit'; +import type { VerificationCodeType } from '@logto/connector-kit'; import type { SignInExperience, User } from '@logto/schemas'; import { SignInIdentifier } from '@logto/schemas'; import type { LogPayload, LogType } from '@logto/schemas/lib/types/log-legacy.js'; @@ -37,7 +37,7 @@ export const getRoutePrefix = ( }; export const getPasswordlessRelatedLogType = ( - flow: MessageTypes, + flow: VerificationCodeType, method: Method, operation?: Operation ): LogType => { diff --git a/packages/integration-tests/src/api/session.ts b/packages/integration-tests/src/api/session.ts index b3087e887..2b9f1db0d 100644 --- a/packages/integration-tests/src/api/session.ts +++ b/packages/integration-tests/src/api/session.ts @@ -1,4 +1,4 @@ -import { MessageTypes } from '@logto/connector-kit'; +import { VerificationCodeType } from '@logto/connector-kit'; import api from './api.js'; @@ -69,7 +69,7 @@ export const sendRegisterUserWithEmailPasscode = (email: string, interactionCook }, json: { email, - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, }, }); @@ -86,7 +86,7 @@ export const verifyRegisterUserWithEmailPasscode = ( json: { email, code, - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, }, }) .json(); @@ -107,7 +107,7 @@ export const sendSignInUserWithEmailPasscode = (email: string, interactionCookie }, json: { email, - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, }, }); @@ -124,7 +124,7 @@ export const verifySignInUserWithEmailPasscode = ( json: { email, code, - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, }, }) .json(); @@ -145,7 +145,7 @@ export const sendRegisterUserWithSmsPasscode = (phone: string, interactionCookie }, json: { phone, - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, }, }); @@ -162,7 +162,7 @@ export const verifyRegisterUserWithSmsPasscode = ( json: { phone, code, - flow: MessageTypes.Register, + flow: VerificationCodeType.Register, }, }) .json(); @@ -183,7 +183,7 @@ export const sendSignInUserWithSmsPasscode = (phone: string, interactionCookie: }, json: { phone, - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, }, }); @@ -200,7 +200,7 @@ export const verifySignInUserWithSmsPasscode = ( json: { phone, code, - flow: MessageTypes.SignIn, + flow: VerificationCodeType.SignIn, }, }) .json(); diff --git a/packages/toolkit/connector-kit/src/types.ts b/packages/toolkit/connector-kit/src/types.ts index 3eea349fa..2b453de71 100644 --- a/packages/toolkit/connector-kit/src/types.ts +++ b/packages/toolkit/connector-kit/src/types.ts @@ -68,7 +68,7 @@ export class ConnectorError extends Error { } } -export enum MessageTypes { +export enum VerificationCodeType { SignIn = 'SignIn', Register = 'Register', ForgotPassword = 'ForgotPassword', @@ -76,7 +76,20 @@ export enum MessageTypes { Test = 'Test', } -export const messageTypesGuard = z.nativeEnum(MessageTypes); +export const verificationCodeTypeGuard = z.nativeEnum(VerificationCodeType); + +// Enum is string actually, keep this exported until GA for compatibility. +/** @deprecated Use `VerificationCodeType` instead. */ +export enum MessageType { + SignIn = 'SignIn', + Register = 'Register', + ForgotPassword = 'ForgotPassword', + Continue = 'Continue', + Test = 'Test', +} + +/** @deprecated Use `verificationCodeTypeGuard` instead. */ +export const messageTypesGuard = verificationCodeTypeGuard; const connectorMetadataGuard = z.object({ id: z.string(), @@ -139,7 +152,7 @@ export type EmailConnector = BaseConnector & { }; export type SendMessageFunction = ( - data: { to: string; type: MessageTypes; payload: { code: string } }, + data: { to: string; type: VerificationCodeType; payload: { code: string } }, config?: unknown ) => Promise;