From baaa58ca0b0dc6ec8c9e1341746aea2b59679f31 Mon Sep 17 00:00:00 2001 From: simeng-li <simeng@silverhand.io> Date: Fri, 23 Dec 2022 19:09:09 +0800 Subject: [PATCH] refactor(core): per review add the missing file refactor: remove unused code fix(core): rename interactionSie middleware rename interactionSie middleware fix(core): update context type name update context type name refactor: per review --- packages/core/src/env-set/index.ts | 3 ++ packages/core/src/index.ts | 26 +++++++++------ packages/core/src/libraries/hook.ts | 13 +------- packages/core/src/routes/interaction/index.ts | 18 +++++------ .../middleware/koa-interaction-sie.ts | 32 +++++++++++++++++++ .../mandatory-user-profile-validation.ts | 4 +-- packages/schemas/src/models/hooks.ts | 5 +-- 7 files changed, 65 insertions(+), 36 deletions(-) create mode 100644 packages/core/src/routes/interaction/middleware/koa-interaction-sie.ts diff --git a/packages/core/src/env-set/index.ts b/packages/core/src/env-set/index.ts index e50b6f42a..5f1a775d1 100644 --- a/packages/core/src/env-set/index.ts +++ b/packages/core/src/env-set/index.ts @@ -87,6 +87,9 @@ function createEnvSet() { return queryClient; }, + get queryClientSafe() { + return queryClient; + }, get oidc() { if (!oidc) { return throwNotLoadedError(); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 91d0e2924..428f52bf4 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,16 +1,24 @@ +import { noop } from '@silverhand/essentials'; import Koa from 'koa'; import { configDotEnv } from './env-set/dot-env.js'; import envSet from './env-set/index.js'; import initI18n from './i18n/init.js'; -await configDotEnv(); -await envSet.load(); -const app = new Koa({ - proxy: envSet.values.trustProxyHeader, -}); -await initI18n(); +try { + await configDotEnv(); + await envSet.load(); + const app = new Koa({ + proxy: envSet.values.trustProxyHeader, + }); + await initI18n(); -// Import last until init completed -const { default: initApp } = await import('./app/init.js'); -await initApp(app); + // Import last until init completed + const { default: initApp } = await import('./app/init.js'); + await initApp(app); +} catch (error: unknown) { + console.error('Error while initializing app:'); + console.error(error); + + await Promise.all([envSet.poolSafe?.end(), envSet.queryClientSafe?.end()]).catch(noop); +} diff --git a/packages/core/src/libraries/hook.ts b/packages/core/src/libraries/hook.ts index 6f1b5fd7b..3f6ab99c3 100644 --- a/packages/core/src/libraries/hook.ts +++ b/packages/core/src/libraries/hook.ts @@ -1,7 +1,7 @@ import { Event, userInfoSelectFields } from '@logto/schemas'; import { HookEventPayload, HookEvent } from '@logto/schemas/models'; import { trySafe } from '@logto/shared'; -import { conditional } from '@silverhand/essentials'; +import { conditional, pick } from '@silverhand/essentials'; import { got } from 'got'; import type { Provider } from 'oidc-provider'; @@ -16,17 +16,6 @@ const eventToHook: Record<Event, HookEvent> = { [Event.ForgotPassword]: HookEvent.PostResetPassword, }; -// TODO: replace `lodash.pick` -const pick = <T, Keys extends Array<keyof T>>( - object: T, - ...keys: Keys -): { [key in Keys[number]]: T[key] } => { - // eslint-disable-next-line no-restricted-syntax - return Object.fromEntries(keys.map((key) => [key, object[key]])) as { - [key in Keys[number]]: T[key]; - }; -}; - export type Interaction = Awaited<ReturnType<Provider['interactionDetails']>>; export const triggerInteractionHooksIfNeeded = async ( diff --git a/packages/core/src/routes/interaction/index.ts b/packages/core/src/routes/interaction/index.ts index 92170e8b9..5eb8e51aa 100644 --- a/packages/core/src/routes/interaction/index.ts +++ b/packages/core/src/routes/interaction/index.ts @@ -15,7 +15,7 @@ import submitInteraction from './actions/submit-interaction.js'; import koaInteractionDetails from './middleware/koa-interaction-details.js'; import type { WithInteractionDetailsContext } from './middleware/koa-interaction-details.js'; import koaInteractionHooks from './middleware/koa-interaction-hooks.js'; -import koaInteractionSIE from './middleware/koa-interaction-sie.js'; +import koaInteractionSie from './middleware/koa-interaction-sie.js'; import { sendPasscodePayloadGuard, socialAuthorizationUrlPayloadGuard } from './types/guard.js'; import { getInteractionStorage, @@ -63,7 +63,7 @@ export default function interactionRoutes<T extends AnonymousRouter>( profile: profileGuard.optional(), }), }), - koaInteractionSIE(), + koaInteractionSie(), async (ctx, next) => { const { event, identifier, profile } = ctx.guard.body; const { signInExperience } = ctx; @@ -108,7 +108,7 @@ export default function interactionRoutes<T extends AnonymousRouter>( router.put( `${interactionPrefix}/event`, koaGuard({ body: z.object({ event: eventGuard }) }), - koaInteractionSIE(), + koaInteractionSie(), async (ctx, next) => { const { event } = ctx.guard.body; const { signInExperience, interactionDetails } = ctx; @@ -141,7 +141,7 @@ export default function interactionRoutes<T extends AnonymousRouter>( koaGuard({ body: identifierPayloadGuard, }), - koaInteractionSIE(), + koaInteractionSie(), async (ctx, next) => { const identifierPayload = ctx.guard.body; const { signInExperience, interactionDetails } = ctx; @@ -172,7 +172,7 @@ export default function interactionRoutes<T extends AnonymousRouter>( koaGuard({ body: profileGuard, }), - koaInteractionSIE(), + koaInteractionSie(), async (ctx, next) => { const profilePayload = ctx.guard.body; const { signInExperience, interactionDetails } = ctx; @@ -213,7 +213,7 @@ export default function interactionRoutes<T extends AnonymousRouter>( // Submit Interaction router.post( `${interactionPrefix}/submit`, - koaInteractionSIE(), + koaInteractionSie(), koaInteractionHooks(), async (ctx, next) => { const { interactionDetails } = ctx; @@ -260,11 +260,11 @@ export default function interactionRoutes<T extends AnonymousRouter>( body: sendPasscodePayloadGuard, }), async (ctx, next) => { + const { interactionDetails, guard, createLog } = ctx; // Check interaction exists - getInteractionStorage(ctx.interactionDetails.result); + getInteractionStorage(interactionDetails.result); - const { jti } = await provider.interactionDetails(ctx.req, ctx.res); - await sendPasscodeToIdentifier(ctx.guard.body, jti, ctx.createLog); + await sendPasscodeToIdentifier(guard.body, interactionDetails.jti, createLog); ctx.status = 204; diff --git a/packages/core/src/routes/interaction/middleware/koa-interaction-sie.ts b/packages/core/src/routes/interaction/middleware/koa-interaction-sie.ts new file mode 100644 index 000000000..8d88e7a83 --- /dev/null +++ b/packages/core/src/routes/interaction/middleware/koa-interaction-sie.ts @@ -0,0 +1,32 @@ +import type { SignInExperience } from '@logto/schemas'; +import { conditional } from '@silverhand/essentials'; +import type { MiddlewareType } from 'koa'; + +import { getSignInExperienceForApplication } from '#src/libraries/sign-in-experience/index.js'; + +import type { WithInteractionDetailsContext } from './koa-interaction-details.js'; + +export type WithInteractionSieContext<ContextT> = WithInteractionDetailsContext<ContextT> & { + signInExperience: SignInExperience; +}; + +export default function koaInteractionSie<StateT, ContextT, ResponseT>(): MiddlewareType< + StateT, + WithInteractionSieContext<ContextT>, + ResponseT +> { + return async (ctx, next) => { + const { interactionDetails } = ctx; + + const signInExperience = await getSignInExperienceForApplication( + conditional( + typeof interactionDetails.params.client_id === 'string' && + interactionDetails.params.client_id + ) + ); + + ctx.signInExperience = signInExperience; + + return next(); + }; +} diff --git a/packages/core/src/routes/interaction/verifications/mandatory-user-profile-validation.ts b/packages/core/src/routes/interaction/verifications/mandatory-user-profile-validation.ts index b5db2786d..4edf54c54 100644 --- a/packages/core/src/routes/interaction/verifications/mandatory-user-profile-validation.ts +++ b/packages/core/src/routes/interaction/verifications/mandatory-user-profile-validation.ts @@ -7,7 +7,7 @@ import RequestError from '#src/errors/RequestError/index.js'; import { findUserById } from '#src/queries/user.js'; import assertThat from '#src/utils/assert-that.js'; -import type { WithInteractionSIEContext } from '../middleware/koa-interaction-sie.js'; +import type { WithInteractionSieContext } from '../middleware/koa-interaction-sie.js'; import type { IdentifierVerifiedInteractionResult } from '../types/index.js'; import { isUserPasswordSet } from '../utils/index.js'; @@ -70,7 +70,7 @@ const getMissingProfileBySignUpIdentifiers = ({ }; export default async function validateMandatoryUserProfile( - ctx: WithInteractionSIEContext<Context>, + ctx: WithInteractionSieContext<Context>, interaction: IdentifierVerifiedInteractionResult ) { const { signUp } = ctx.signInExperience; diff --git a/packages/schemas/src/models/hooks.ts b/packages/schemas/src/models/hooks.ts index 595b8c8b9..e74cc775d 100644 --- a/packages/schemas/src/models/hooks.ts +++ b/packages/schemas/src/models/hooks.ts @@ -2,7 +2,7 @@ import { generateStandardId } from '@logto/core-kit'; import { createModel } from '@withtyped/server'; import { z } from 'zod'; -import type { Application, Connector, User } from '../db-entries/index.js'; +import type { Application, User } from '../db-entries/index.js'; import type { userInfoSelectFields } from '../types/index.js'; export enum HookEvent { @@ -20,9 +20,6 @@ export type HookEventPayload = { userId?: string; user?: Pick<User, typeof userInfoSelectFields[number]>; application?: Pick<Application, 'id' | 'type' | 'name' | 'description'>; - connectors?: Array< - Pick<Connector, 'id'> & Pick<Connector['metadata'], 'name'> & Record<string, unknown> - >; } & Record<string, unknown>; export type HookConfig = {