fix(core): Improve handling of invalid objects in cleanupParameterData (no-chanhelog) (#8910)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-03-18 18:35:49 +01:00 committed by GitHub
parent 669bd830e9
commit 33ab781aef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 7 deletions

View file

@ -33,6 +33,7 @@ import { Agent, type AgentOptions } from 'https';
import get from 'lodash/get'; import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import pick from 'lodash/pick'; import pick from 'lodash/pick';
import { DateTime } from 'luxon';
import { extension, lookup } from 'mime-types'; import { extension, lookup } from 'mime-types';
import type { import type {
BinaryHelperFunctions, BinaryHelperFunctions,
@ -2096,7 +2097,7 @@ export async function getCredentials(
* Clean up parameter data to make sure that only valid data gets returned * Clean up parameter data to make sure that only valid data gets returned
* INFO: Currently only converts Luxon Dates as we know for sure it will not be breaking * INFO: Currently only converts Luxon Dates as we know for sure it will not be breaking
*/ */
function cleanupParameterData(inputData: NodeParameterValueType): void { export function cleanupParameterData(inputData: NodeParameterValueType): void {
if (typeof inputData !== 'object' || inputData === null) { if (typeof inputData !== 'object' || inputData === null) {
return; return;
} }
@ -2107,14 +2108,15 @@ function cleanupParameterData(inputData: NodeParameterValueType): void {
} }
if (typeof inputData === 'object') { if (typeof inputData === 'object') {
Object.keys(inputData).forEach((key) => { type Key = keyof typeof inputData;
if (typeof inputData[key as keyof typeof inputData] === 'object') { (Object.keys(inputData) as Key[]).forEach((key) => {
if (inputData[key as keyof typeof inputData]?.constructor.name === 'DateTime') { const value = inputData[key];
if (typeof value === 'object') {
if (value instanceof DateTime) {
// Is a special luxon date so convert to string // Is a special luxon date so convert to string
inputData[key as keyof typeof inputData] = inputData[key] = value.toString();
inputData[key as keyof typeof inputData]?.toString();
} else { } else {
cleanupParameterData(inputData[key as keyof typeof inputData]); cleanupParameterData(value);
} }
} }
}); });

View file

@ -1,4 +1,5 @@
import { import {
cleanupParameterData,
copyInputItems, copyInputItems,
getBinaryDataBuffer, getBinaryDataBuffer,
parseIncomingMessage, parseIncomingMessage,
@ -7,6 +8,7 @@ import {
removeEmptyBody, removeEmptyBody,
setBinaryDataBuffer, setBinaryDataBuffer,
} from '@/NodeExecuteFunctions'; } from '@/NodeExecuteFunctions';
import { DateTime } from 'luxon';
import { mkdtempSync, readFileSync } from 'fs'; import { mkdtempSync, readFileSync } from 'fs';
import type { IncomingMessage } from 'http'; import type { IncomingMessage } from 'http';
import { mock } from 'jest-mock-extended'; import { mock } from 'jest-mock-extended';
@ -18,6 +20,7 @@ import type {
IRequestOptions, IRequestOptions,
ITaskDataConnections, ITaskDataConnections,
IWorkflowExecuteAdditionalData, IWorkflowExecuteAdditionalData,
NodeParameterValue,
Workflow, Workflow,
WorkflowHooks, WorkflowHooks,
} from 'n8n-workflow'; } from 'n8n-workflow';
@ -414,6 +417,29 @@ describe('NodeExecuteFunctions', () => {
}); });
}); });
describe('cleanupParameterData', () => {
it('should stringify Luxon dates in-place', () => {
const input = { x: 1, y: DateTime.now() as unknown as NodeParameterValue };
expect(typeof input.y).toBe('object');
cleanupParameterData(input);
expect(typeof input.y).toBe('string');
});
it('should handle objects with nameless constructors', () => {
const input = { x: 1, y: { constructor: {} } as NodeParameterValue };
expect(typeof input.y).toBe('object');
cleanupParameterData(input);
expect(typeof input.y).toBe('object');
});
it('should handle objects without a constructor', () => {
const input = { x: 1, y: { constructor: undefined } as unknown as NodeParameterValue };
expect(typeof input.y).toBe('object');
cleanupParameterData(input);
expect(typeof input.y).toBe('object');
});
});
describe('copyInputItems', () => { describe('copyInputItems', () => {
it('should pick only selected properties', () => { it('should pick only selected properties', () => {
const output = copyInputItems( const output = copyInputItems(