From 01f718b258fc54633d53668bae186eadd8067643 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Tue, 27 Dec 2022 14:13:42 +0800 Subject: [PATCH] refactor!: align `PasscodeType` to `MessageTypes` refactor: apply suggestions from code review Co-authored-by: Darcy Ye refactor(core): fix type names --- packages/core/src/__mocks__/index.ts | 5 +- packages/core/src/connectors/types.ts | 6 +- packages/core/src/libraries/passcode.test.ts | 25 ++-- packages/core/src/libraries/passcode.ts | 8 +- packages/core/src/queries/passcode.test.ts | 7 +- packages/core/src/queries/passcode.ts | 7 +- .../utils/passcode-validation.test.ts | 15 +-- .../interaction/utils/passcode-validation.ts | 24 ++-- .../core/src/routes/session/continue.test.ts | 6 +- .../routes/session/forgot-password.test.ts | 18 +-- .../session/middleware/passwordless-action.ts | 11 +- .../src/routes/session/passwordless.test.ts | 111 +++++++++--------- .../core/src/routes/session/passwordless.ts | 24 ++-- packages/core/src/routes/session/types.ts | 17 +-- packages/core/src/routes/session/utils.ts | 5 +- packages/integration-tests/package.json | 1 + packages/integration-tests/src/api/session.ts | 18 +-- ...0-align-passcode-type-with-message-type.ts | 27 +++++ packages/schemas/tables/passcodes.sql | 10 +- packages/ui/package.json | 1 + packages/ui/src/apis/continue.test.ts | 10 +- packages/ui/src/apis/continue.ts | 10 +- packages/ui/src/apis/forgot-password.ts | 10 +- packages/ui/src/apis/index.test.ts | 26 ++-- packages/ui/src/apis/register.ts | 10 +- packages/ui/src/apis/sign-in.ts | 10 +- pnpm-lock.yaml | 4 + 27 files changed, 236 insertions(+), 190 deletions(-) create mode 100644 packages/schemas/alterations/next-1672119200-align-passcode-type-with-message-type.ts diff --git a/packages/core/src/__mocks__/index.ts b/packages/core/src/__mocks__/index.ts index 552ac3fc1..2f9929f99 100644 --- a/packages/core/src/__mocks__/index.ts +++ b/packages/core/src/__mocks__/index.ts @@ -1,5 +1,6 @@ +import { MessageTypes } from '@logto/connector-kit'; import type { Application, Passcode, Resource, Role, Setting } from '@logto/schemas'; -import { ApplicationType, PasscodeType } from '@logto/schemas'; +import { ApplicationType } from '@logto/schemas'; export * from './connector.js'; export * from './sign-in-experience.js'; @@ -54,7 +55,7 @@ export const mockPasscode: Passcode = { interactionJti: 'jti', phone: '888 888 8888', email: 'foo@logto.io', - type: PasscodeType.SignIn, + type: MessageTypes.SignIn, code: 'asdfghjkl', consumed: false, tryCount: 2, diff --git a/packages/core/src/connectors/types.ts b/packages/core/src/connectors/types.ts index aa3714a28..501849bb0 100644 --- a/packages/core/src/connectors/types.ts +++ b/packages/core/src/connectors/types.ts @@ -1,10 +1,10 @@ -import type { AllConnector, CreateConnector } from '@logto/connector-kit'; -import type { Connector, PasscodeType } from '@logto/schemas'; +import type { AllConnector, CreateConnector, MessageTypes } from '@logto/connector-kit'; +import type { Connector } from '@logto/schemas'; import { z } from 'zod'; export { ConnectorType } from '@logto/schemas'; -export type TemplateType = PasscodeType | 'Test'; +export type TemplateType = MessageTypes; 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 b94d38cd4..46262cc8a 100644 --- a/packages/core/src/libraries/passcode.test.ts +++ b/packages/core/src/libraries/passcode.test.ts @@ -1,6 +1,5 @@ -import { ConnectorType } from '@logto/connector-kit'; -import type { Passcode } from '@logto/schemas'; -import { PasscodeType } from '@logto/schemas'; +import { ConnectorType, MessageTypes } from '@logto/connector-kit'; +import { Passcode } from '@logto/schemas'; import { createMockUtils } from '@logto/shared/esm'; import { any } from 'zod'; @@ -61,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', PasscodeType.SignIn, { + const passcode = await createPasscode('jti', MessageTypes.SignIn, { phone, }); expect(new RegExp(`^\\d{${passcodeLength}}$`).test(passcode.code)).toBeTruthy(); @@ -70,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', PasscodeType.SignIn, { + const passcode = await createPasscode('jti', MessageTypes.SignIn, { email, }); expect(new RegExp(`^\\d{${passcodeLength}}$`).test(passcode.code)).toBeTruthy(); @@ -85,7 +84,7 @@ describe('createPasscode', () => { id: 'id', interactionJti: jti, code: '1234', - type: PasscodeType.SignIn, + type: MessageTypes.SignIn, createdAt: Date.now(), phone: '', email, @@ -93,7 +92,7 @@ describe('createPasscode', () => { tryCount: 0, }, ]); - await createPasscode(jti, PasscodeType.SignIn, { + await createPasscode(jti, MessageTypes.SignIn, { email, }); expect(deletePasscodesByIds).toHaveBeenCalledWith(['id']); @@ -107,7 +106,7 @@ describe('sendPasscode', () => { interactionJti: 'jti', phone: null, email: null, - type: PasscodeType.SignIn, + type: MessageTypes.SignIn, code: '1234', consumed: false, tryCount: 0, @@ -140,7 +139,7 @@ describe('sendPasscode', () => { interactionJti: 'jti', phone: 'phone', email: null, - type: PasscodeType.SignIn, + type: MessageTypes.SignIn, code: '1234', consumed: false, tryCount: 0, @@ -191,7 +190,7 @@ describe('sendPasscode', () => { interactionJti: 'jti', phone: 'phone', email: null, - type: PasscodeType.SignIn, + type: MessageTypes.SignIn, code: '1234', consumed: false, tryCount: 0, @@ -209,17 +208,17 @@ describe('sendPasscode', () => { }); describe('verifyPasscode', () => { - const passcode: Passcode = { + const passcode = { id: 'id', interactionJti: 'jti', phone: 'phone', email: null, - type: PasscodeType.SignIn, + type: MessageTypes.SignIn, code: '1234', consumed: false, tryCount: 0, createdAt: Date.now(), - }; + } satisfies Passcode; it('should mark as consumed on successful verification', async () => { findUnconsumedPasscodeByJtiAndType.mockResolvedValue(passcode); diff --git a/packages/core/src/libraries/passcode.ts b/packages/core/src/libraries/passcode.ts index 96b6d32e2..5e8f99ef3 100644 --- a/packages/core/src/libraries/passcode.ts +++ b/packages/core/src/libraries/passcode.ts @@ -1,6 +1,6 @@ -import type { EmailConnector, SmsConnector } from '@logto/connector-kit'; +import type { EmailConnector, MessageTypes, SmsConnector } from '@logto/connector-kit'; import { messageTypesGuard, ConnectorError, ConnectorErrorCodes } from '@logto/connector-kit'; -import type { Passcode, PasscodeType } from '@logto/schemas'; +import type { Passcode } from '@logto/schemas'; import { customAlphabet, nanoid } from 'nanoid'; import { getLogtoConnectors } from '#src/connectors/index.js'; @@ -22,7 +22,7 @@ const randomCode = customAlphabet('1234567890', passcodeLength); export const createPasscode = async ( jti: string, - type: PasscodeType, + type: MessageTypes, payload: { phone: string } | { email: string } ) => { // Disable existing passcodes. @@ -88,7 +88,7 @@ export const passcodeMaxTryCount = 10; export const verifyPasscode = async ( sessionId: string, - type: PasscodeType, + type: MessageTypes, 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 1fc48eac7..1605b0a65 100644 --- a/packages/core/src/queries/passcode.test.ts +++ b/packages/core/src/queries/passcode.test.ts @@ -1,4 +1,5 @@ -import { Passcodes, PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; +import { Passcodes } from '@logto/schemas'; import { convertToIdentifiers, convertToPrimitiveOrSql, excludeAutoSetFields } from '@logto/shared'; import { createMockPool, createMockQueryResult, sql } from 'slonik'; import { snakeCase } from 'snake-case'; @@ -34,7 +35,7 @@ describe('passcode query', () => { it('findUnconsumedPasscodeByJtiAndType', async () => { const jti = 'foo'; - const type = PasscodeType.SignIn; + const type = MessageTypes.SignIn; const expectSql = sql` select ${sql.join(Object.values(fields), sql`, `)} @@ -54,7 +55,7 @@ describe('passcode query', () => { it('findUnconsumedPasscodesByJtiAndType', async () => { const jti = 'foo'; - const type = PasscodeType.SignIn; + const type = MessageTypes.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 21431888b..3350faeac 100644 --- a/packages/core/src/queries/passcode.ts +++ b/packages/core/src/queries/passcode.ts @@ -1,4 +1,5 @@ -import type { PasscodeType, Passcode, CreatePasscode } from '@logto/schemas'; +import type { MessageTypes } from '@logto/connector-kit'; +import type { Passcode, CreatePasscode } from '@logto/schemas'; import { Passcodes } from '@logto/schemas'; import { convertToIdentifiers } from '@logto/shared'; import { sql } from 'slonik'; @@ -9,14 +10,14 @@ import { DeletionError } from '#src/errors/SlonikError/index.js'; const { table, fields } = convertToIdentifiers(Passcodes); -export const findUnconsumedPasscodeByJtiAndType = async (jti: string, type: PasscodeType) => +export const findUnconsumedPasscodeByJtiAndType = async (jti: string, type: MessageTypes) => 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: PasscodeType) => +export const findUnconsumedPasscodesByJtiAndType = async (jti: string, type: MessageTypes) => envSet.pool.any(sql` select ${sql.join(Object.values(fields), sql`, `)} from ${table} 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 0f1420921..41bbc442e 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,5 @@ -import { PasscodeType, InteractionEvent } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; +import { InteractionEvent } from '@logto/schemas'; import { createMockUtils } from '@logto/shared/esm'; import { createMockLogContext } from '#src/test-utils/koa-audit-log.js'; @@ -20,27 +21,27 @@ const { sendPasscodeToIdentifier } = await import('./passcode-validation.js'); const sendPasscodeTestCase = [ { payload: { email: 'email', event: InteractionEvent.SignIn }, - createPasscodeParams: [PasscodeType.SignIn, { email: 'email' }], + createPasscodeParams: [MessageTypes.SignIn, { email: 'email' }], }, { payload: { email: 'email', event: InteractionEvent.Register }, - createPasscodeParams: [PasscodeType.Register, { email: 'email' }], + createPasscodeParams: [MessageTypes.Register, { email: 'email' }], }, { payload: { email: 'email', event: InteractionEvent.ForgotPassword }, - createPasscodeParams: [PasscodeType.ForgotPassword, { email: 'email' }], + createPasscodeParams: [MessageTypes.ForgotPassword, { email: 'email' }], }, { payload: { phone: 'phone', event: InteractionEvent.SignIn }, - createPasscodeParams: [PasscodeType.SignIn, { phone: 'phone' }], + createPasscodeParams: [MessageTypes.SignIn, { phone: 'phone' }], }, { payload: { phone: 'phone', event: InteractionEvent.Register }, - createPasscodeParams: [PasscodeType.Register, { phone: 'phone' }], + createPasscodeParams: [MessageTypes.Register, { phone: 'phone' }], }, { payload: { phone: 'phone', event: InteractionEvent.ForgotPassword }, - createPasscodeParams: [PasscodeType.ForgotPassword, { phone: 'phone' }], + createPasscodeParams: [MessageTypes.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 0f0b6352c..104c6d1c2 100644 --- a/packages/core/src/routes/interaction/utils/passcode-validation.ts +++ b/packages/core/src/routes/interaction/utils/passcode-validation.ts @@ -1,5 +1,5 @@ +import { MessageTypes } from '@logto/connector-kit'; import type { InteractionEvent } from '@logto/schemas'; -import { PasscodeType } from '@logto/schemas'; import { createPasscode, sendPasscode, verifyPasscode } from '#src/libraries/passcode.js'; import type { LogContext } from '#src/middleware/koa-audit-log.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 PasscodeType + * This is a work around to map the latest interaction event type to old MessageTypes * */ -const eventToPasscodeTypeMap: Record = { - SignIn: PasscodeType.SignIn, - Register: PasscodeType.Register, - ForgotPassword: PasscodeType.ForgotPassword, +const eventToMessageTypesMap: Record = { + SignIn: MessageTypes.SignIn, + Register: MessageTypes.Register, + ForgotPassword: MessageTypes.ForgotPassword, }; -const getPasscodeTypeByEvent = (event: InteractionEvent): PasscodeType => - eventToPasscodeTypeMap[event]; +const getMessageTypesByEvent = (event: InteractionEvent): MessageTypes => + eventToMessageTypesMap[event]; export const sendPasscodeToIdentifier = async ( payload: SendPasscodePayload, @@ -25,12 +25,12 @@ export const sendPasscodeToIdentifier = async ( createLog: LogContext['createLog'] ) => { const { event, ...identifier } = payload; - const passcodeType = getPasscodeTypeByEvent(event); + const messageType = getMessageTypesByEvent(event); const log = createLog(`Interaction.${event}.Identifier.VerificationCode.Create`); log.append(identifier); - const passcode = await createPasscode(jti, passcodeType, identifier); + const passcode = await createPasscode(jti, messageType, identifier); const { dbEntry } = await sendPasscode(passcode); log.append({ connectorId: dbEntry.id }); @@ -42,11 +42,11 @@ export const verifyIdentifierByPasscode = async ( createLog: LogContext['createLog'] ) => { const { event, passcode, ...identifier } = payload; - const passcodeType = getPasscodeTypeByEvent(event); + const messageType = getMessageTypesByEvent(event); // TODO: @Simeng maybe we should just log all interaction payload in every request? const log = createLog(`Interaction.${event}.Identifier.VerificationCode.Submit`); log.append(identifier); - await verifyPasscode(jti, passcodeType, passcode, identifier); + await verifyPasscode(jti, messageType, passcode, identifier); }; diff --git a/packages/core/src/routes/session/continue.test.ts b/packages/core/src/routes/session/continue.test.ts index d46fa0424..1f14c0b74 100644 --- a/packages/core/src/routes/session/continue.test.ts +++ b/packages/core/src/routes/session/continue.test.ts @@ -1,4 +1,4 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } 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: PasscodeType.Continue, + type: MessageTypes.Continue, }, }, }); @@ -172,7 +172,7 @@ describe('session -> continueRoutes', () => { continueSignIn: { userId: mockUser.id, expiresAt: getTomorrowIsoString(), - type: PasscodeType.Continue, + type: MessageTypes.Continue, }, }, }); diff --git a/packages/core/src/routes/session/forgot-password.test.ts b/packages/core/src/routes/session/forgot-password.test.ts index 88630d211..4d416743c 100644 --- a/packages/core/src/routes/session/forgot-password.test.ts +++ b/packages/core/src/routes/session/forgot-password.test.ts @@ -1,5 +1,5 @@ +import { MessageTypes } from '@logto/connector-kit'; import type { User } from '@logto/schemas'; -import { PasscodeType } 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: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }, }); @@ -118,7 +118,7 @@ describe('session -> forgotPasswordRoutes', () => { result: { verification: { expiresAt: getTomorrowDate().toISOString(), - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }, }); @@ -134,7 +134,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getTomorrowDate().toISOString(), - flow: PasscodeType.SignIn, + flow: MessageTypes.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: PasscodeType.ForgotPassword }, + verification: { userId: 'id', expiresAt: 0, flow: MessageTypes.ForgotPassword }, }, }); const response = await sessionRequest @@ -162,7 +162,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: 'invalid date string', - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }, }); @@ -178,7 +178,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getYesterdayDate().toISOString(), - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }, }); @@ -194,7 +194,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getTomorrowDate().toISOString(), - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }, }); @@ -211,7 +211,7 @@ describe('session -> forgotPasswordRoutes', () => { verification: { userId: 'id', expiresAt: getTomorrowDate().toISOString(), - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }, }); diff --git a/packages/core/src/routes/session/middleware/passwordless-action.ts b/packages/core/src/routes/session/middleware/passwordless-action.ts index 416e7e694..af2daa4ae 100644 --- a/packages/core/src/routes/session/middleware/passwordless-action.ts +++ b/packages/core/src/routes/session/middleware/passwordless-action.ts @@ -1,4 +1,5 @@ -import { PasscodeType, SignInIdentifier } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; +import { SignInIdentifier } from '@logto/schemas'; import type { MiddlewareType } from 'koa'; import type { Provider } from 'oidc-provider'; @@ -51,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: PasscodeType.SignIn }); + .send({ phone: '13000000000', flow: MessageTypes.SignIn }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', PasscodeType.SignIn, { + expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.SignIn, { phone: '13000000000', }); expect(sendPasscode).toHaveBeenCalled(); @@ -117,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: PasscodeType.Register }); + .send({ phone: '13000000000', flow: MessageTypes.Register }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', PasscodeType.Register, { + expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.Register, { phone: '13000000000', }); expect(sendPasscode).toHaveBeenCalled(); @@ -127,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: PasscodeType.ForgotPassword }); + .send({ phone: '13000000000', flow: MessageTypes.ForgotPassword }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', PasscodeType.ForgotPassword, { + expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.ForgotPassword, { phone: '13000000000', }); expect(sendPasscode).toHaveBeenCalled(); @@ -137,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: PasscodeType.Register }); + .send({ flow: MessageTypes.Register }); expect(response.statusCode).toEqual(400); }); }); @@ -151,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: PasscodeType.SignIn }); + .send({ email: 'a@a.com', flow: MessageTypes.SignIn }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', PasscodeType.SignIn, { + expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.SignIn, { email: 'a@a.com', }); expect(sendPasscode).toHaveBeenCalled(); @@ -161,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: PasscodeType.Register }); + .send({ email: 'a@a.com', flow: MessageTypes.Register }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', PasscodeType.Register, { + expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.Register, { email: 'a@a.com', }); expect(sendPasscode).toHaveBeenCalled(); @@ -171,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: PasscodeType.ForgotPassword }); + .send({ email: 'a@a.com', flow: MessageTypes.ForgotPassword }); expect(response.statusCode).toEqual(204); - expect(createPasscode).toHaveBeenCalledWith('jti', PasscodeType.ForgotPassword, { + expect(createPasscode).toHaveBeenCalledWith('jti', MessageTypes.ForgotPassword, { email: 'a@a.com', }); expect(sendPasscode).toHaveBeenCalled(); @@ -181,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: PasscodeType.Register }); + .send({ flow: MessageTypes.Register }); expect(response.statusCode).toEqual(400); }); }); @@ -203,14 +204,14 @@ describe('session -> passwordlessRoutes', () => { await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000000', code: '1234', flow: PasscodeType.SignIn }); + .send({ phone: '13000000000', code: '1234', flow: MessageTypes.SignIn }); expect(interactionResult).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.objectContaining({ verification: { - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, phone: '13000000000', expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), }, @@ -227,14 +228,14 @@ describe('session -> passwordlessRoutes', () => { await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000000', code: '1234', flow: PasscodeType.Register }); + .send({ phone: '13000000000', code: '1234', flow: MessageTypes.Register }); expect(interactionResult).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.objectContaining({ verification: { - flow: PasscodeType.Register, + flow: MessageTypes.Register, phone: '13000000000', expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), }, @@ -250,7 +251,7 @@ describe('session -> passwordlessRoutes', () => { const response = await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000000', code: '1234', flow: PasscodeType.ForgotPassword }); + .send({ phone: '13000000000', code: '1234', flow: MessageTypes.ForgotPassword }); expect(response.statusCode).toEqual(204); @@ -261,7 +262,7 @@ describe('session -> passwordlessRoutes', () => { verification: { userId: mockUser.id, expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }) ); @@ -271,7 +272,7 @@ describe('session -> passwordlessRoutes', () => { findUserByPhone.mockResolvedValueOnce(null); const response = await sessionRequest .post('/session/passwordless/sms/verify') - .send({ phone: '13000000001', code: '1234', flow: PasscodeType.ForgotPassword }); + .send({ phone: '13000000001', code: '1234', flow: MessageTypes.ForgotPassword }); expect(response.statusCode).toEqual(404); expect(interactionResult).toHaveBeenCalledTimes(0); }); @@ -279,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: PasscodeType.SignIn }); + .send({ phone: '13000000000', code: '1231', flow: MessageTypes.SignIn }); expect(response.statusCode).toEqual(400); }); }); @@ -301,14 +302,14 @@ describe('session -> passwordlessRoutes', () => { await sessionRequest .post('/session/passwordless/email/verify') - .send({ email: 'a@a.com', code: '1234', flow: PasscodeType.SignIn }); + .send({ email: 'a@a.com', code: '1234', flow: MessageTypes.SignIn }); expect(interactionResult).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.objectContaining({ verification: { - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, email: 'a@a.com', expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), }, @@ -324,14 +325,14 @@ describe('session -> passwordlessRoutes', () => { await sessionRequest .post('/session/passwordless/email/verify') - .send({ email: 'a@a.com', code: '1234', flow: PasscodeType.Register }); + .send({ email: 'a@a.com', code: '1234', flow: MessageTypes.Register }); expect(interactionResult).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.objectContaining({ verification: { - flow: PasscodeType.Register, + flow: MessageTypes.Register, email: 'a@a.com', expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), }, @@ -347,7 +348,7 @@ describe('session -> passwordlessRoutes', () => { const response = await sessionRequest .post('/session/passwordless/email/verify') - .send({ email: 'a@a.com', code: '1234', flow: PasscodeType.ForgotPassword }); + .send({ email: 'a@a.com', code: '1234', flow: MessageTypes.ForgotPassword }); expect(response.statusCode).toEqual(204); @@ -358,7 +359,7 @@ describe('session -> passwordlessRoutes', () => { verification: { userId: mockUser.id, expiresAt: addSeconds(fakeTime, verificationTimeout).toISOString(), - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }) ); @@ -370,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: PasscodeType.ForgotPassword }); + .send({ email: 'b@a.com', code: '1234', flow: MessageTypes.ForgotPassword }); expect(response.statusCode).toEqual(404); expect(interactionResult).toHaveBeenCalledTimes(0); }); @@ -378,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: PasscodeType.SignIn }); + .send({ email: 'a@a.com', code: '1231', flow: MessageTypes.SignIn }); expect(response.statusCode).toEqual(400); }); }); @@ -389,7 +390,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -413,7 +414,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: PasscodeType.Register, + flow: MessageTypes.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -448,7 +449,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, expiresAt: getTomorrowIsoString(), }, }, @@ -462,7 +463,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: 'invalid date string', }, }, @@ -476,7 +477,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: subDays(Date.now(), 1).toISOString(), }, }, @@ -490,7 +491,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'XX@foo', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -504,7 +505,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000001', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -523,7 +524,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -571,7 +572,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -595,7 +596,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: PasscodeType.Register, + flow: MessageTypes.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -632,7 +633,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, expiresAt: getTomorrowIsoString(), }, }, @@ -645,7 +646,7 @@ describe('session -> passwordlessRoutes', () => { interactionDetails.mockResolvedValueOnce({ result: { verification: { - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -659,7 +660,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'b@a.com', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -678,7 +679,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -725,7 +726,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000001', - flow: PasscodeType.Register, + flow: MessageTypes.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -747,7 +748,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000001', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -782,7 +783,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000001', - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, expiresAt: getTomorrowIsoString(), }, }, @@ -795,7 +796,7 @@ describe('session -> passwordlessRoutes', () => { interactionDetails.mockResolvedValueOnce({ result: { verification: { - flow: PasscodeType.Register, + flow: MessageTypes.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -809,7 +810,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { phone: '13000000000', - flow: PasscodeType.Register, + flow: MessageTypes.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -853,7 +854,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'b@a.com', - flow: PasscodeType.Register, + flow: MessageTypes.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -875,7 +876,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'b@a.com', - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, expiresAt: getTomorrowIsoString(), }, }, @@ -910,7 +911,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'b@a.com', - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, expiresAt: getTomorrowIsoString(), }, }, @@ -923,7 +924,7 @@ describe('session -> passwordlessRoutes', () => { interactionDetails.mockResolvedValueOnce({ result: { verification: { - flow: PasscodeType.Register, + flow: MessageTypes.Register, expiresAt: getTomorrowIsoString(), }, }, @@ -937,7 +938,7 @@ describe('session -> passwordlessRoutes', () => { result: { verification: { email: 'a@a.com', - flow: PasscodeType.Register, + flow: MessageTypes.Register, expiresAt: getTomorrowIsoString(), }, }, diff --git a/packages/core/src/routes/session/passwordless.ts b/packages/core/src/routes/session/passwordless.ts index 0c6bfa468..27b432010 100644 --- a/packages/core/src/routes/session/passwordless.ts +++ b/packages/core/src/routes/session/passwordless.ts @@ -1,5 +1,5 @@ +import { MessageTypes } from '@logto/connector-kit'; import { emailRegEx, phoneRegEx } from '@logto/core-kit'; -import { PasscodeType } from '@logto/schemas'; import type { Provider } from 'oidc-provider'; import { object, string } from 'zod'; @@ -7,7 +7,6 @@ import RequestError from '#src/errors/RequestError/index.js'; import { createPasscode, sendPasscode, verifyPasscode } from '#src/libraries/passcode.js'; import koaGuard from '#src/middleware/koa-guard.js'; import { findUserByEmail, findUserByPhone } from '#src/queries/user.js'; -import { passcodeTypeGuard } from '#src/routes/session/types.js'; import assertThat from '#src/utils/assert-that.js'; import type { AnonymousRouterLegacy } from '../types.js'; @@ -17,6 +16,7 @@ import { smsRegisterAction, emailRegisterAction, } from './middleware/passwordless-action.js'; +import { flowTypeGuard } from './types.js'; import { assignVerificationResult, getPasswordlessRelatedLogType, @@ -35,7 +35,7 @@ export default function passwordlessRoutes( koaGuard({ body: object({ phone: string().regex(phoneRegEx), - flow: passcodeTypeGuard, + flow: flowTypeGuard, }), }), async (ctx, next) => { @@ -61,7 +61,7 @@ export default function passwordlessRoutes( koaGuard({ body: object({ email: string().regex(emailRegEx), - flow: passcodeTypeGuard, + flow: flowTypeGuard, }), }), async (ctx, next) => { @@ -88,7 +88,7 @@ export default function passwordlessRoutes( body: object({ phone: string().regex(phoneRegEx), code: string(), - flow: passcodeTypeGuard, + flow: flowTypeGuard, }), }), async (ctx, next) => { @@ -103,7 +103,7 @@ export default function passwordlessRoutes( await verifyPasscode(jti, flow, code, { phone }); - if (flow === PasscodeType.ForgotPassword) { + if (flow === MessageTypes.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 === PasscodeType.SignIn) { + if (flow === MessageTypes.SignIn) { await assignVerificationResult(ctx, provider, { flow, phone }); return smsSignInAction(provider)(ctx, next); } - if (flow === PasscodeType.Register) { + if (flow === MessageTypes.Register) { await assignVerificationResult(ctx, provider, { flow, phone }); return smsRegisterAction(provider)(ctx, next); @@ -138,7 +138,7 @@ export default function passwordlessRoutes( body: object({ email: string().regex(emailRegEx), code: string(), - flow: passcodeTypeGuard, + flow: flowTypeGuard, }), }), async (ctx, next) => { @@ -152,7 +152,7 @@ export default function passwordlessRoutes( await verifyPasscode(jti, flow, code, { email }); - if (flow === PasscodeType.ForgotPassword) { + if (flow === MessageTypes.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 === PasscodeType.SignIn) { + if (flow === MessageTypes.SignIn) { await assignVerificationResult(ctx, provider, { flow, email }); return emailSignInAction(provider)(ctx, next); } - if (flow === PasscodeType.Register) { + if (flow === MessageTypes.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 82469b79d..e2407b6b2 100644 --- a/packages/core/src/routes/session/types.ts +++ b/packages/core/src/routes/session/types.ts @@ -1,7 +1,10 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; +import { pick } from '@silverhand/essentials'; import { z } from 'zod'; -export const passcodeTypeGuard = z.nativeEnum(PasscodeType); +export const flowTypeGuard = z.nativeEnum( + pick(MessageTypes, 'Continue', 'ForgotPassword', 'Register', 'SignIn') +); export const methodGuard = z.enum(['email', 'sms']); @@ -12,7 +15,7 @@ export const operationGuard = z.enum(['send', 'verify']); export type Operation = z.infer; const smsSessionStorageGuard = z.object({ - flow: z.literal(PasscodeType.SignIn).or(z.literal(PasscodeType.Register)), + flow: z.literal(MessageTypes.SignIn).or(z.literal(MessageTypes.Register)), expiresAt: z.string(), phone: z.string(), }); @@ -22,7 +25,7 @@ export type SmsSessionStorage = z.infer; export const smsSessionResultGuard = z.object({ verification: smsSessionStorageGuard }); const emailSessionStorageGuard = z.object({ - flow: z.literal(PasscodeType.SignIn).or(z.literal(PasscodeType.Register)), + flow: z.literal(MessageTypes.SignIn).or(z.literal(MessageTypes.Register)), expiresAt: z.string(), email: z.string(), }); @@ -34,7 +37,7 @@ export const emailSessionResultGuard = z.object({ }); const forgotPasswordSessionStorageGuard = z.object({ - flow: z.literal(PasscodeType.ForgotPassword), + flow: z.literal(MessageTypes.ForgotPassword), expiresAt: z.string(), userId: z.string(), }); @@ -46,7 +49,7 @@ export const forgotPasswordSessionResultGuard = z.object({ }); const continueEmailSessionStorageGuard = z.object({ - flow: z.literal(PasscodeType.Continue), + flow: z.literal(MessageTypes.Continue), expiresAt: z.string(), email: z.string(), }); @@ -58,7 +61,7 @@ export const continueEmailSessionResultGuard = z.object({ }); const continueSmsSessionStorageGuard = z.object({ - flow: z.literal(PasscodeType.Continue), + flow: z.literal(MessageTypes.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 1d70e61fa..5fa209aff 100644 --- a/packages/core/src/routes/session/utils.ts +++ b/packages/core/src/routes/session/utils.ts @@ -1,4 +1,5 @@ -import type { PasscodeType, SignInExperience, User } from '@logto/schemas'; +import type { MessageTypes } 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'; import { logTypeGuard } from '@logto/schemas/lib/types/log-legacy.js'; @@ -36,7 +37,7 @@ export const getRoutePrefix = ( }; export const getPasswordlessRelatedLogType = ( - flow: PasscodeType, + flow: MessageTypes, method: Method, operation?: Operation ): LogType => { diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index b2491d351..505a010a8 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -21,6 +21,7 @@ }, "devDependencies": { "@jest/types": "^29.1.2", + "@logto/connector-kit": "workspace:1.0.0-beta.30", "@logto/js": "1.0.0-beta.14", "@logto/node": "1.0.0-beta.14", "@logto/schemas": "workspace:*", diff --git a/packages/integration-tests/src/api/session.ts b/packages/integration-tests/src/api/session.ts index 66485df35..b3087e887 100644 --- a/packages/integration-tests/src/api/session.ts +++ b/packages/integration-tests/src/api/session.ts @@ -1,4 +1,4 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; import api from './api.js'; @@ -69,7 +69,7 @@ export const sendRegisterUserWithEmailPasscode = (email: string, interactionCook }, json: { email, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }); @@ -86,7 +86,7 @@ export const verifyRegisterUserWithEmailPasscode = ( json: { email, code, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }) .json(); @@ -107,7 +107,7 @@ export const sendSignInUserWithEmailPasscode = (email: string, interactionCookie }, json: { email, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }); @@ -124,7 +124,7 @@ export const verifySignInUserWithEmailPasscode = ( json: { email, code, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }) .json(); @@ -145,7 +145,7 @@ export const sendRegisterUserWithSmsPasscode = (phone: string, interactionCookie }, json: { phone, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }); @@ -162,7 +162,7 @@ export const verifyRegisterUserWithSmsPasscode = ( json: { phone, code, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }) .json(); @@ -183,7 +183,7 @@ export const sendSignInUserWithSmsPasscode = (phone: string, interactionCookie: }, json: { phone, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }); @@ -200,7 +200,7 @@ export const verifySignInUserWithSmsPasscode = ( json: { phone, code, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }) .json(); diff --git a/packages/schemas/alterations/next-1672119200-align-passcode-type-with-message-type.ts b/packages/schemas/alterations/next-1672119200-align-passcode-type-with-message-type.ts new file mode 100644 index 000000000..fb13927a8 --- /dev/null +++ b/packages/schemas/alterations/next-1672119200-align-passcode-type-with-message-type.ts @@ -0,0 +1,27 @@ +import { sql } from 'slonik'; + +import type { AlterationScript } from '../lib/types/alteration.js'; + +const alteration: AlterationScript = { + up: async (pool) => { + await pool.query(sql` + alter table passcodes alter column "type" type varchar(32); + drop type passcode_type; + create index passcodes__interaction_jti_type + on passcodes ( + interaction_jti, + type + ); + `); + }, + down: async (pool) => { + // We don't handle potential type casting failures here as they need to be handled manually + await pool.query(sql` + create type passcode_type as enum ('SignIn', 'Register', 'ForgotPassword', 'Continue'); + drop index passcodes__interaction_jti_type; + alter table passcodes alter column "type" type passcode_type using type::passcode_type; + `); + }, +}; + +export default alteration; diff --git a/packages/schemas/tables/passcodes.sql b/packages/schemas/tables/passcodes.sql index d596747d8..9954ab18d 100644 --- a/packages/schemas/tables/passcodes.sql +++ b/packages/schemas/tables/passcodes.sql @@ -1,14 +1,18 @@ -create type passcode_type as enum ('SignIn', 'Register', 'ForgotPassword', 'Continue'); - create table passcodes ( id varchar(21) not null, interaction_jti varchar(128) not null, phone varchar(32), email varchar(128), - type passcode_type not null, + type varchar(32) not null, code varchar(6) not null, consumed boolean not null default FALSE, try_count int2 not null default 0, created_at timestamptz not null default(now()), primary key (id) ); + +create index passcodes__interaction_jti_type +on passcodes ( + interaction_jti, + type +); diff --git a/packages/ui/package.json b/packages/ui/package.json index 840a458c3..59c8dda2c 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -17,6 +17,7 @@ "test": "jest" }, "devDependencies": { + "@logto/connector-kit": "workspace:*", "@logto/core-kit": "workspace:*", "@logto/language-kit": "workspace:*", "@logto/phrases": "workspace:*", diff --git a/packages/ui/src/apis/continue.test.ts b/packages/ui/src/apis/continue.test.ts index 54b9c8539..b4bf7e5c0 100644 --- a/packages/ui/src/apis/continue.test.ts +++ b/packages/ui/src/apis/continue.test.ts @@ -1,4 +1,4 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; import ky from 'ky'; import { @@ -75,7 +75,7 @@ describe('continue API', () => { expect(ky.post).toBeCalledWith('/api/session/passwordless/email/send', { json: { email: 'email', - flow: PasscodeType.Continue, + flow: MessageTypes.Continue, }, }); }); @@ -86,7 +86,7 @@ describe('continue API', () => { expect(ky.post).toBeCalledWith('/api/session/passwordless/sms/send', { json: { phone: '111111', - flow: PasscodeType.Continue, + flow: MessageTypes.Continue, }, }); }); @@ -98,7 +98,7 @@ describe('continue API', () => { json: { email: 'email', code: 'passcode', - flow: PasscodeType.Continue, + flow: MessageTypes.Continue, }, }); }); @@ -110,7 +110,7 @@ describe('continue API', () => { json: { phone: 'phone', code: 'passcode', - flow: PasscodeType.Continue, + flow: MessageTypes.Continue, }, }); }); diff --git a/packages/ui/src/apis/continue.ts b/packages/ui/src/apis/continue.ts index 4300c518e..eef440e61 100644 --- a/packages/ui/src/apis/continue.ts +++ b/packages/ui/src/apis/continue.ts @@ -1,4 +1,4 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; import api from './api'; import { bindSocialAccount } from './social'; @@ -31,7 +31,7 @@ export const sendContinueSetEmailPasscode = async (email: string) => { .post(`${passwordlessApiPrefix}/email/send`, { json: { email, - flow: PasscodeType.Continue, + flow: MessageTypes.Continue, }, }) .json(); @@ -44,7 +44,7 @@ export const sendContinueSetPhonePasscode = async (phone: string) => { .post(`${passwordlessApiPrefix}/sms/send`, { json: { phone, - flow: PasscodeType.Continue, + flow: MessageTypes.Continue, }, }) .json(); @@ -55,7 +55,7 @@ export const sendContinueSetPhonePasscode = async (phone: string) => { export const verifyContinueSetEmailPasscode = async (email: string, code: string) => { await api .post(`${passwordlessApiPrefix}/email/verify`, { - json: { email, code, flow: PasscodeType.Continue }, + json: { email, code, flow: MessageTypes.Continue }, }) .json(); @@ -65,7 +65,7 @@ export const verifyContinueSetEmailPasscode = async (email: string, code: string export const verifyContinueSetSmsPasscode = async (phone: string, code: string) => { await api .post(`${passwordlessApiPrefix}/sms/verify`, { - json: { phone, code, flow: PasscodeType.Continue }, + json: { phone, code, flow: MessageTypes.Continue }, }) .json(); diff --git a/packages/ui/src/apis/forgot-password.ts b/packages/ui/src/apis/forgot-password.ts index c4c4b00d6..752d8c1eb 100644 --- a/packages/ui/src/apis/forgot-password.ts +++ b/packages/ui/src/apis/forgot-password.ts @@ -1,4 +1,4 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; import api from './api'; @@ -13,7 +13,7 @@ export const sendForgotPasswordSmsPasscode = async (phone: string) => { .post('/api/session/passwordless/sms/send', { json: { phone, - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }) .json(); @@ -27,7 +27,7 @@ export const verifyForgotPasswordSmsPasscode = async (phone: string, code: strin json: { phone, code, - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }) .json(); @@ -40,7 +40,7 @@ export const sendForgotPasswordEmailPasscode = async (email: string) => { .post('/api/session/passwordless/email/send', { json: { email, - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }) .json(); @@ -54,7 +54,7 @@ export const verifyForgotPasswordEmailPasscode = async (email: string, code: str json: { email, code, - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }) .json(); diff --git a/packages/ui/src/apis/index.test.ts b/packages/ui/src/apis/index.test.ts index 33140f51e..e791e927d 100644 --- a/packages/ui/src/apis/index.test.ts +++ b/packages/ui/src/apis/index.test.ts @@ -1,4 +1,4 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; import ky from 'ky'; import { consent } from './consent'; @@ -188,7 +188,7 @@ describe('api', () => { expect(ky.post).toBeCalledWith('/api/session/passwordless/sms/send', { json: { phone, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }); }); @@ -206,7 +206,7 @@ describe('api', () => { json: { phone, code, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }); }); @@ -216,7 +216,7 @@ describe('api', () => { expect(ky.post).toBeCalledWith('/api/session/passwordless/email/send', { json: { email, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }); }); @@ -234,7 +234,7 @@ describe('api', () => { json: { email, code, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }); }); @@ -278,7 +278,7 @@ describe('api', () => { expect(ky.post).toBeCalledWith('/api/session/passwordless/sms/send', { json: { phone, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }); }); @@ -289,7 +289,7 @@ describe('api', () => { json: { phone, code, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }); }); @@ -299,7 +299,7 @@ describe('api', () => { expect(ky.post).toBeCalledWith('/api/session/passwordless/email/send', { json: { email, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }); }); @@ -310,7 +310,7 @@ describe('api', () => { json: { email, code, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }); }); @@ -320,7 +320,7 @@ describe('api', () => { expect(ky.post).toBeCalledWith('/api/session/passwordless/sms/send', { json: { phone, - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }); }); @@ -331,7 +331,7 @@ describe('api', () => { json: { phone, code, - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }); }); @@ -341,7 +341,7 @@ describe('api', () => { expect(ky.post).toBeCalledWith('/api/session/passwordless/email/send', { json: { email, - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }); }); @@ -352,7 +352,7 @@ describe('api', () => { json: { email, code, - flow: PasscodeType.ForgotPassword, + flow: MessageTypes.ForgotPassword, }, }); }); diff --git a/packages/ui/src/apis/register.ts b/packages/ui/src/apis/register.ts index f749ada42..1ca3f8749 100644 --- a/packages/ui/src/apis/register.ts +++ b/packages/ui/src/apis/register.ts @@ -1,4 +1,4 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; import api from './api'; @@ -30,7 +30,7 @@ export const sendRegisterSmsPasscode = async (phone: string) => { .post(`${apiPrefix}/passwordless/sms/send`, { json: { phone, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }) .json(); @@ -44,7 +44,7 @@ export const verifyRegisterSmsPasscode = async (phone: string, code: string) => json: { phone, code, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }) .json(); @@ -54,7 +54,7 @@ export const sendRegisterEmailPasscode = async (email: string) => { .post(`${apiPrefix}/passwordless/email/send`, { json: { email, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }) .json(); @@ -68,7 +68,7 @@ export const verifyRegisterEmailPasscode = async (email: string, code: string) = json: { email, code, - flow: PasscodeType.Register, + flow: MessageTypes.Register, }, }) .json(); diff --git a/packages/ui/src/apis/sign-in.ts b/packages/ui/src/apis/sign-in.ts index 1f960605f..2b30b7c3a 100644 --- a/packages/ui/src/apis/sign-in.ts +++ b/packages/ui/src/apis/sign-in.ts @@ -1,4 +1,4 @@ -import { PasscodeType } from '@logto/schemas'; +import { MessageTypes } from '@logto/connector-kit'; import api from './api'; import { bindSocialAccount } from './social'; @@ -97,7 +97,7 @@ export const sendSignInSmsPasscode = async (phone: string) => { .post(`${apiPrefix}/passwordless/sms/send`, { json: { phone, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }) .json(); @@ -115,7 +115,7 @@ export const verifySignInSmsPasscode = async ( json: { phone, code, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }) .json(); @@ -132,7 +132,7 @@ export const sendSignInEmailPasscode = async (email: string) => { .post(`${apiPrefix}/passwordless/email/send`, { json: { email, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }) .json(); @@ -150,7 +150,7 @@ export const verifySignInEmailPasscode = async ( json: { email, code, - flow: PasscodeType.SignIn, + flow: MessageTypes.SignIn, }, }) .json(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9bc732354..8d015d4d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -460,6 +460,7 @@ importers: packages/integration-tests: specifiers: '@jest/types': ^29.1.2 + '@logto/connector-kit': workspace:1.0.0-beta.30 '@logto/js': 1.0.0-beta.14 '@logto/node': 1.0.0-beta.14 '@logto/schemas': workspace:* @@ -487,6 +488,7 @@ importers: '@withtyped/server': 0.3.1 devDependencies: '@jest/types': 29.1.2 + '@logto/connector-kit': link:../toolkit/connector-kit '@logto/js': 1.0.0-beta.14 '@logto/node': 1.0.0-beta.14 '@logto/schemas': link:../schemas @@ -763,6 +765,7 @@ importers: packages/ui: specifiers: + '@logto/connector-kit': workspace:* '@logto/core-kit': workspace:* '@logto/language-kit': workspace:* '@logto/phrases': workspace:* @@ -817,6 +820,7 @@ importers: use-debounced-loader: ^0.1.1 zod: ^3.20.2 devDependencies: + '@logto/connector-kit': link:../toolkit/connector-kit '@logto/core-kit': link:../toolkit/core-kit '@logto/language-kit': link:../toolkit/language-kit '@logto/phrases': link:../phrases