mirror of
https://github.com/logto-io/logto.git
synced 2025-01-27 21:39:16 -05:00
fix(console): should parse to json before using zod safeParse
This commit is contained in:
parent
8df08d9671
commit
ec674ecd77
11 changed files with 44 additions and 24 deletions
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
arbitraryObjectGuard,
|
||||
Connector,
|
||||
ConnectorDto,
|
||||
ConnectorMetadata,
|
||||
ConnectorType,
|
||||
} from '@logto/schemas';
|
||||
import { Connector, ConnectorDto, ConnectorMetadata, ConnectorType } from '@logto/schemas';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -15,6 +9,7 @@ import FormField from '@/components/FormField';
|
|||
import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import * as detailsStyles from '@/scss/details.module.scss';
|
||||
import { safeParseJson } from '@/utilities/json';
|
||||
|
||||
import * as styles from '../index.module.scss';
|
||||
import SenderTester from './SenderTester';
|
||||
|
@ -66,10 +61,10 @@ const ConnectorContent = ({ isDeleted, connectorData, onConnectorUpdated }: Prop
|
|||
return;
|
||||
}
|
||||
|
||||
const configJson = arbitraryObjectGuard.safeParse(config);
|
||||
const result = safeParseJson(config);
|
||||
|
||||
if (!configJson.success) {
|
||||
toast.error(t('connector_details.save_error_json_parse_error'));
|
||||
if (!result.success) {
|
||||
toast.error(result.error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -77,7 +72,7 @@ const ConnectorContent = ({ isDeleted, connectorData, onConnectorUpdated }: Prop
|
|||
setIsSubmitting(true);
|
||||
|
||||
const { metadata, ...reset } = await api
|
||||
.patch(`/api/connectors/${connectorData.id}`, { json: { config: configJson.data } })
|
||||
.patch(`/api/connectors/${connectorData.id}`, { json: { config: result.data } })
|
||||
.json<Connector & { metadata: ConnectorMetadata }>();
|
||||
|
||||
onConnectorUpdated({ ...reset, ...metadata });
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, arbitraryObjectGuard } from '@logto/schemas';
|
||||
import { ConnectorType } from '@logto/schemas';
|
||||
import { phoneRegEx, emailRegEx } from '@logto/shared';
|
||||
import classNames from 'classnames';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
@ -11,6 +11,7 @@ import FormField from '@/components/FormField';
|
|||
import TextInput from '@/components/TextInput';
|
||||
import Tooltip from '@/components/Tooltip';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import { safeParseJson } from '@/utilities/json';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -56,10 +57,10 @@ const SenderTester = ({ connectorId, connectorType, config, className }: Props)
|
|||
|
||||
const onSubmit = handleSubmit(async (formData) => {
|
||||
const { sendTo } = formData;
|
||||
const result = arbitraryObjectGuard.safeParse(config);
|
||||
const result = safeParseJson(config);
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(t('connector_details.save_error_json_parse_error'));
|
||||
toast.error(result.error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorDto, ConnectorType, arbitraryObjectGuard } from '@logto/schemas';
|
||||
import { ConnectorDto, ConnectorType } from '@logto/schemas';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import i18next from 'i18next';
|
||||
import { Controller, FormProvider, useForm } from 'react-hook-form';
|
||||
|
@ -16,6 +16,7 @@ import Close from '@/icons/Close';
|
|||
import Step from '@/mdx-components/Step';
|
||||
import SenderTester from '@/pages/ConnectorDetails/components/SenderTester';
|
||||
import { GuideForm } from '@/types/guide';
|
||||
import { safeParseJson } from '@/utilities/json';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -49,10 +50,10 @@ const Guide = ({ connector, onClose }: Props) => {
|
|||
return;
|
||||
}
|
||||
|
||||
const result = arbitraryObjectGuard.safeParse(connectorConfigJson);
|
||||
const result = safeParseJson(connectorConfigJson);
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(t('connector_details.save_error_json_parse_error'));
|
||||
toast.error(result.error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import TextInput from '@/components/TextInput';
|
|||
import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import * as detailsStyles from '@/scss/details.module.scss';
|
||||
import { safeParseJson } from '@/utilities/json';
|
||||
import { uriValidator } from '@/utilities/validator';
|
||||
|
||||
import * as styles from '../index.module.scss';
|
||||
|
@ -63,9 +64,17 @@ const UserSettings = ({ userData, userFormData, isDeleted, onUserUpdated }: Prop
|
|||
|
||||
const { customData: inputCustomData, name, avatar, roleNames } = formData;
|
||||
|
||||
const result = arbitraryObjectGuard.safeParse(inputCustomData);
|
||||
const parseResult = safeParseJson(inputCustomData);
|
||||
|
||||
if (!result.success) {
|
||||
if (!parseResult.success) {
|
||||
toast.error(parseResult.error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const guardResult = arbitraryObjectGuard.safeParse(parseResult.data);
|
||||
|
||||
if (!guardResult.success) {
|
||||
toast.error(t('user_details.custom_data_invalid'));
|
||||
|
||||
return;
|
||||
|
@ -75,7 +84,7 @@ const UserSettings = ({ userData, userFormData, isDeleted, onUserUpdated }: Prop
|
|||
name,
|
||||
avatar,
|
||||
roleNames,
|
||||
customData: result.data,
|
||||
customData: guardResult.data,
|
||||
};
|
||||
|
||||
const updatedUser = await api
|
||||
|
|
14
packages/console/src/utilities/json.ts
Normal file
14
packages/console/src/utilities/json.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { t } from 'i18next';
|
||||
|
||||
export const safeParseJson = (
|
||||
jsonString: string
|
||||
): { success: true; data: unknown } | { success: false; error: string } => {
|
||||
try {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const data = JSON.parse(jsonString) as unknown;
|
||||
|
||||
return { success: true, data };
|
||||
} catch {
|
||||
return { success: false, error: t('admin_console.errors.invalid_json_format') };
|
||||
}
|
||||
};
|
|
@ -2,7 +2,6 @@ const connector_details = {
|
|||
back_to_connectors: 'Back to Connectors',
|
||||
check_readme: 'Check README',
|
||||
save_error_empty_config: 'Please enter config',
|
||||
save_error_json_parse_error: 'Please enter valid JSON',
|
||||
send: 'Send',
|
||||
send_error_invalid_format: 'Invalid input',
|
||||
edit_config_label: 'Enter your json here',
|
||||
|
|
|
@ -6,6 +6,7 @@ const errors = {
|
|||
missing_total_number: 'Unable to find Total-Number in response headers',
|
||||
invalid_uri_format: 'Invalid URI format',
|
||||
invalid_origin_format: 'Invalid URI origin format',
|
||||
invalid_json_format: 'Invalid JSON format',
|
||||
invalid_error_message_format: 'The error message format is invalid.',
|
||||
required_field_missing: 'Please enter {{field}}',
|
||||
required_field_missing_plural: 'You have to enter at least one {{field}}',
|
||||
|
|
|
@ -25,7 +25,7 @@ const user_details = {
|
|||
field_custom_data_tip:
|
||||
'Additional user info not listed in the pre-defined user properties, such as user-preferred color and language.',
|
||||
field_connectors: 'Social connections',
|
||||
custom_data_invalid: 'Custom data must be a valid JSON',
|
||||
custom_data_invalid: 'Custom data must be a valid JSON object',
|
||||
connectors: {
|
||||
connectors: 'Connectors',
|
||||
user_id: 'User ID',
|
||||
|
|
|
@ -2,7 +2,6 @@ const connector_details = {
|
|||
back_to_connectors: '返回连接器',
|
||||
check_readme: '查看 README',
|
||||
save_error_empty_config: '请输入配置内容',
|
||||
save_error_json_parse_error: '请输入符合 JSON 格式的配置',
|
||||
send: '发送',
|
||||
send_error_invalid_format: '无效输入',
|
||||
edit_config_label: '请在此输入你的 JSON 配置',
|
||||
|
|
|
@ -6,6 +6,7 @@ const errors = {
|
|||
missing_total_number: '无法从返回的头部信息中找到 Total-Number',
|
||||
invalid_uri_format: '无效的 URI 格式',
|
||||
invalid_origin_format: '无效的 URI origin 格式',
|
||||
invalid_json_format: '无效的 JSON 格式',
|
||||
invalid_error_message_format: '非法的错误信息格式',
|
||||
required_field_missing: '请输入{{field}}',
|
||||
required_field_missing_plural: '至少需要输入一个{{field}}',
|
||||
|
|
|
@ -24,7 +24,7 @@ const user_details = {
|
|||
field_custom_data: '自定义数据',
|
||||
field_custom_data_tip: '预定义属性之外的用户信息,例如用户偏好的颜色和语言。',
|
||||
field_connectors: '社交帐号',
|
||||
custom_data_invalid: '自定义数据必须是有效的 JSON',
|
||||
custom_data_invalid: '自定义数据必须是有效的 JSON 对象',
|
||||
connectors: {
|
||||
connectors: '连接器',
|
||||
user_id: '用户ID',
|
||||
|
|
Loading…
Add table
Reference in a new issue