diff --git a/packages/console/src/pages/JwtClaims/SettingsSection/TestTab.tsx b/packages/console/src/pages/JwtClaims/SettingsSection/TestTab.tsx index cdcf138af..79d3ad1aa 100644 --- a/packages/console/src/pages/JwtClaims/SettingsSection/TestTab.tsx +++ b/packages/console/src/pages/JwtClaims/SettingsSection/TestTab.tsx @@ -1,8 +1,10 @@ -import { type JsonObject, LogtoJwtTokenPath } from '@logto/schemas'; +import { type JsonObject, LogtoJwtTokenPath, type RequestErrorBody } from '@logto/schemas'; import classNames from 'classnames'; +import { HTTPError } from 'ky'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { useFormContext, Controller, type ControllerRenderProps } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; +import { z } from 'zod'; import Button from '@/ds-components/Button'; import Card from '@/ds-components/Card'; @@ -27,6 +29,7 @@ type Props = { const accessTokenModelSettings = [accessTokenPayloadTestModel, userContextTestModel]; const clientCredentialsModelSettings = [clientCredentialsPayloadTestModel]; const testEndpointPath = 'api/configs/jwt-customizer/test'; +const jwtCustomizerGeneralErrorCode = 'jwt_customizer.general'; function TestTab({ isActive }: Props) { const { t } = useTranslation(undefined, { keyPrefix: 'admin_console.jwt_claims' }); @@ -62,7 +65,21 @@ function TestTab({ isActive }: Props) { json: formatFormDataToTestRequestPayload(payload), }) .json() - .catch((error: unknown) => { + .catch(async (error: unknown) => { + if (error instanceof HTTPError) { + const { response } = error; + const metadata = await response.clone().json(); + if (metadata.code === jwtCustomizerGeneralErrorCode) { + const result = z.object({ message: z.string() }).safeParse(metadata.data); + if (result.success) { + setTestResult({ + error: result.data.message, + }); + return; + } + } + } + setTestResult({ error: error instanceof Error ? error.message : String(error), }); diff --git a/packages/core/src/routes/logto-config.ts b/packages/core/src/routes/logto-config.ts index 5590d7876..9d059bae2 100644 --- a/packages/core/src/routes/logto-config.ts +++ b/packages/core/src/routes/logto-config.ts @@ -19,6 +19,7 @@ import { jsonObjectGuard, } from '@logto/schemas'; import { adminTenantId } from '@logto/schemas'; +import { ResponseError } from '@withtyped/client'; import { z } from 'zod'; import { EnvSet } from '#src/env-set/index.js'; @@ -340,13 +341,27 @@ export default function logtoConfigRoutes( const client = await cloudConnection.getClient(); - ctx.body = await client.post(`/api/services/custom-jwt`, { - body: { - ...rest, - token: tokenSample, - context: contextSample, - }, - }); + try { + ctx.body = await client.post(`/api/services/custom-jwt`, { + body: { + ...rest, + token: tokenSample, + context: contextSample, + }, + }); + } catch (error: unknown) { + /** + * `ResponseError` comes from `@withtyped/client` and all `logto/core` API returns error in the + * format of `RequestError`, we manually transform it here to keep the error format consistent. + */ + if (error instanceof ResponseError) { + const { message } = z.object({ message: z.string() }).parse(await error.response.json()); + throw new RequestError({ code: 'jwt_customizer.general', status: 422 }, { message }); + } + + throw error; + } + return next(); } ); diff --git a/packages/phrases/src/locales/de/errors/index.ts b/packages/phrases/src/locales/de/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/de/errors/index.ts +++ b/packages/phrases/src/locales/de/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/de/errors/jwt-customizer.ts b/packages/phrases/src/locales/de/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/de/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/en/errors/index.ts b/packages/phrases/src/locales/en/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/en/errors/index.ts +++ b/packages/phrases/src/locales/en/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/en/errors/jwt-customizer.ts b/packages/phrases/src/locales/en/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/en/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/es/errors/index.ts b/packages/phrases/src/locales/es/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/es/errors/index.ts +++ b/packages/phrases/src/locales/es/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/es/errors/jwt-customizer.ts b/packages/phrases/src/locales/es/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/es/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/fr/errors/index.ts b/packages/phrases/src/locales/fr/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/fr/errors/index.ts +++ b/packages/phrases/src/locales/fr/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/fr/errors/jwt-customizer.ts b/packages/phrases/src/locales/fr/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/fr/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/it/errors/index.ts b/packages/phrases/src/locales/it/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/it/errors/index.ts +++ b/packages/phrases/src/locales/it/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/it/errors/jwt-customizer.ts b/packages/phrases/src/locales/it/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/it/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/ja/errors/index.ts b/packages/phrases/src/locales/ja/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/ja/errors/index.ts +++ b/packages/phrases/src/locales/ja/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/ja/errors/jwt-customizer.ts b/packages/phrases/src/locales/ja/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/ja/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/ko/errors/index.ts b/packages/phrases/src/locales/ko/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/ko/errors/index.ts +++ b/packages/phrases/src/locales/ko/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/ko/errors/jwt-customizer.ts b/packages/phrases/src/locales/ko/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/ko/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/pl-pl/errors/index.ts b/packages/phrases/src/locales/pl-pl/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/pl-pl/errors/index.ts +++ b/packages/phrases/src/locales/pl-pl/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/pl-pl/errors/jwt-customizer.ts b/packages/phrases/src/locales/pl-pl/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/pl-pl/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/pt-br/errors/index.ts b/packages/phrases/src/locales/pt-br/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/pt-br/errors/index.ts +++ b/packages/phrases/src/locales/pt-br/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/pt-br/errors/jwt-customizer.ts b/packages/phrases/src/locales/pt-br/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/pt-br/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/pt-pt/errors/index.ts b/packages/phrases/src/locales/pt-pt/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/pt-pt/errors/index.ts +++ b/packages/phrases/src/locales/pt-pt/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/pt-pt/errors/jwt-customizer.ts b/packages/phrases/src/locales/pt-pt/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/pt-pt/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/ru/errors/index.ts b/packages/phrases/src/locales/ru/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/ru/errors/index.ts +++ b/packages/phrases/src/locales/ru/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/ru/errors/jwt-customizer.ts b/packages/phrases/src/locales/ru/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/ru/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/tr-tr/errors/index.ts b/packages/phrases/src/locales/tr-tr/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/tr-tr/errors/index.ts +++ b/packages/phrases/src/locales/tr-tr/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/tr-tr/errors/jwt-customizer.ts b/packages/phrases/src/locales/tr-tr/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/tr-tr/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/zh-cn/errors/index.ts b/packages/phrases/src/locales/zh-cn/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/zh-cn/errors/index.ts +++ b/packages/phrases/src/locales/zh-cn/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/zh-cn/errors/jwt-customizer.ts b/packages/phrases/src/locales/zh-cn/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/zh-cn/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/zh-hk/errors/index.ts b/packages/phrases/src/locales/zh-hk/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/zh-hk/errors/index.ts +++ b/packages/phrases/src/locales/zh-hk/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/zh-hk/errors/jwt-customizer.ts b/packages/phrases/src/locales/zh-hk/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/zh-hk/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer); diff --git a/packages/phrases/src/locales/zh-tw/errors/index.ts b/packages/phrases/src/locales/zh-tw/errors/index.ts index 74995792d..40df6998e 100644 --- a/packages/phrases/src/locales/zh-tw/errors/index.ts +++ b/packages/phrases/src/locales/zh-tw/errors/index.ts @@ -5,6 +5,7 @@ import domain from './domain.js'; import entity from './entity.js'; import guard from './guard.js'; import hook from './hook.js'; +import jwt_customizer from './jwt-customizer.js'; import localization from './localization.js'; import log from './log.js'; import oidc from './oidc.js'; @@ -34,6 +35,7 @@ const errors = { connector, verification_code, sign_in_experiences, + jwt_customizer, localization, swagger, entity, diff --git a/packages/phrases/src/locales/zh-tw/errors/jwt-customizer.ts b/packages/phrases/src/locales/zh-tw/errors/jwt-customizer.ts new file mode 100644 index 000000000..f2ca29554 --- /dev/null +++ b/packages/phrases/src/locales/zh-tw/errors/jwt-customizer.ts @@ -0,0 +1,6 @@ +const jwt_customizer = { + /** UNTRANSLATED */ + general: 'An error occurred while customizing the JWT token. Please try again later.', +}; + +export default Object.freeze(jwt_customizer);