fix: block non-string data in xlsx textarea fields (#7049)

* fix: prevent non-string data insertion in textarea interface
This commit is contained in:
ajie 2025-06-12 10:04:39 +08:00 committed by GitHub
parent 4de557c386
commit e9718b67b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 79 additions and 0 deletions

View File

@ -16,3 +16,4 @@ export * from './datetime-no-tz-interface';
export * from './boolean-interface';
export * from './date-interface';
export * from './time-interface';
export * from './textarea-interface';

View File

@ -0,0 +1,28 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import _ from 'lodash';
import { BaseInterface } from './base-interface';
export class TextareaInterface extends BaseInterface {
toValue(value) {
if (value === null || value === undefined || typeof value === 'string') {
return value;
}
if (this.validate(value)) {
return value.toString();
}
throw new Error(`Invalid value ${value}, expected textarea value`);
}
validate(value): boolean {
return _.isString(value) || _.isNumber(value);
}
}

View File

@ -16,6 +16,7 @@ import {
MultipleSelectInterface,
PercentInterface,
SelectInterface,
TextareaInterface,
TimeInterface,
} from './index';
import { ManyToOneInterface } from './many-to-one-interface';
@ -54,6 +55,7 @@ const interfaces = {
m2m: ManyToManyInterface,
time: TimeInterface,
input: InputInterface,
textarea: TextareaInterface,
};
export function registerInterfaces(db: Database) {

View File

@ -2274,4 +2274,52 @@ describe('xlsx importer', () => {
const count = await TimeCollection.repository.count();
expect(count).toBe(1);
});
it('should throw error when import textarea field, value is date', async () => {
const TextareaCollection = app.db.collection({
name: 'textarea_tests',
fields: [
{
interface: 'textarea',
type: 'text',
name: 'long_text',
},
],
});
await app.db.sync();
const templateCreator = new TemplateCreator({
collection: TextareaCollection,
explain: 'test',
columns: [
{
dataIndex: ['long_text'],
defaultTitle: '多行文本',
},
],
});
const template = (await templateCreator.run({ returnXLSXWorkbook: true })) as XLSX.WorkBook;
const worksheet = template.Sheets[template.SheetNames[0]];
XLSX.utils.sheet_add_aoa(worksheet, [[new Date()]], {
origin: 'A3',
});
const importer = new XlsxImporter({
collectionManager: app.mainDataSource.collectionManager,
collection: TextareaCollection,
explain: 'test',
columns: [
{
dataIndex: ['long_text'],
defaultTitle: '多行文本',
},
],
workbook: template,
});
expect(importer.run()).rejects.toThrow();
});
});