fix: validate conversation variable description length to prevent varchar(255) truncation error (#33038)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: 非法操作 <hjlarry@163.com>
Co-authored-by: -LAN- <laipz8200@outlook.com>
This commit is contained in:
Novice
2026-06-10 07:28:12 +00:00
committed by GitHub
co-authored by autofix-ci[bot] 非法操作 -LAN-
parent 09bfbf386e
commit 4fb3210f9a
31 changed files with 206 additions and 26 deletions
@@ -195,6 +195,34 @@ describe('useVariableModalState', () => {
expect(onClose).not.toHaveBeenCalled()
})
it('should notify and stop saving when description exceeds the limit', () => {
const notify = vi.fn()
const onSave = vi.fn()
const onClose = vi.fn()
const { result } = renderHook(() => useVariableModalState(createOptions({
notify,
onClose,
onSave,
})))
act(() => {
result.current.handleVarNameChange({ target: { value: 'greeting' } } as ChangeEvent<HTMLInputElement>)
result.current.handleStringOrNumberChange(['hello'])
result.current.setDescription('a'.repeat(256))
})
act(() => {
result.current.handleSave()
})
expect(notify).toHaveBeenCalledWith({
type: 'error',
message: 'chatVariable.modal.descriptionTooLong',
})
expect(onSave).not.toHaveBeenCalled()
expect(onClose).not.toHaveBeenCalled()
})
it('should save a new variable and close when state is valid', () => {
const onSave = vi.fn()
const onClose = vi.fn()
@@ -24,6 +24,7 @@ describe('variable-modal sections', () => {
/>
<DescriptionSection
description="original description"
maxLength={255}
onChange={onDescriptionChange}
placeholder="description-placeholder"
title="Description"
@@ -43,6 +44,20 @@ describe('variable-modal sections', () => {
expect(onDescriptionChange).toHaveBeenCalledWith('updated-description')
})
it('should show description length against the configured limit', () => {
render(
<DescriptionSection
description="abc"
maxLength={255}
onChange={vi.fn()}
placeholder="description-placeholder"
title="Description"
/>,
)
expect(screen.getByText('3/255')).toBeInTheDocument()
})
it('renders type and value sections and forwards toggle and value changes', async () => {
const onSelect = vi.fn()
const onArrayChange = vi.fn()
@@ -11,6 +11,7 @@ import {
getEditorMinHeight,
getPlaceholderByType,
getTypeChangeState,
MAX_DESCRIPTION_LENGTH,
parseEditorContent,
validateVariableName,
} from './variable-modal.helpers'
@@ -196,6 +197,17 @@ export const useVariableModalState = ({
return
}
if (state.description.length > MAX_DESCRIPTION_LENGTH) {
notify({
type: 'error',
message: t('chatVariable.modal.descriptionTooLong', {
maxLength: MAX_DESCRIPTION_LENGTH,
ns: 'workflow',
}),
})
return
}
onSave({
description: state.description,
id: chatVar ? chatVar.id : uuid4(),
@@ -29,6 +29,8 @@ export type ToastPayload = {
customComponent?: ReactNode
}
export const MAX_DESCRIPTION_LENGTH = 255
export const typeList = [
ChatVarTypeEnum.String,
ChatVarTypeEnum.Number,
@@ -1,6 +1,7 @@
import type { ReactNode } from 'react'
import type { ObjectValueItem } from './variable-modal.helpers'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { RiDraftLine, RiInputField } from '@remixicon/react'
import Input from '@/app/components/base/input'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
@@ -195,6 +196,7 @@ export const ValueSection = ({
type DescriptionSectionProps = {
description: string
maxLength: number
onChange: (value: string) => void
placeholder: string
title: string
@@ -202,6 +204,7 @@ type DescriptionSectionProps = {
export const DescriptionSection = ({
description,
maxLength,
onChange,
placeholder,
title,
@@ -216,5 +219,10 @@ export const DescriptionSection = ({
onChange={e => onChange(e.target.value)}
/>
</div>
<div className={cn('mt-1 text-right system-xs-regular', description.length > maxLength ? 'text-text-destructive' : 'text-text-quaternary')}>
{description.length}
/
{maxLength}
</div>
</div>
)
@@ -12,6 +12,7 @@ import { replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var'
import { useVariableModalState } from './use-variable-modal-state'
import {
getEditorToggleLabelKey,
MAX_DESCRIPTION_LENGTH,
typeList,
validateVariableName,
} from './variable-modal.helpers'
@@ -72,6 +73,7 @@ const ChatVariableModal = ({
return
handleVarNameChange(e)
}
return (
<div
className={cn('flex h-full w-[360px] flex-col rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-2xl', type === ChatVarType.Object && 'w-[480px]')}
@@ -127,6 +129,7 @@ const ChatVariableModal = ({
/>
<DescriptionSection
description={description}
maxLength={MAX_DESCRIPTION_LENGTH}
onChange={setDescription}
placeholder={t('chatVariable.modal.descriptionPlaceholder', { ns: 'workflow' }) || ''}
title={t('chatVariable.modal.description', { ns: 'workflow' })}
+1
View File
@@ -90,6 +90,7 @@
"chatVariable.modal.arrayValue": "Value",
"chatVariable.modal.description": "Description",
"chatVariable.modal.descriptionPlaceholder": "Describe the variable",
"chatVariable.modal.descriptionTooLong": "Description must be {{maxLength}} characters or less",
"chatVariable.modal.editInForm": "Edit in Form",
"chatVariable.modal.editInJSON": "Edit in JSON",
"chatVariable.modal.editTitle": "Edit Conversation Variable",
+1
View File
@@ -90,6 +90,7 @@
"chatVariable.modal.arrayValue": "值",
"chatVariable.modal.description": "描述",
"chatVariable.modal.descriptionPlaceholder": "变量的描述",
"chatVariable.modal.descriptionTooLong": "描述不能超过 {{maxLength}} 个字符",
"chatVariable.modal.editInForm": "在表单中编辑",
"chatVariable.modal.editInJSON": "在 JSON 中编辑",
"chatVariable.modal.editTitle": "编辑会话变量",