mirror of
https://github.com/n8n-io/n8n.git
synced 2026-08-29 01:39:24 +08:00
fix(TheHive Node): Normalize analyzers when expression returns a string (#32472)
Co-authored-by: Elias Meire <elias@meire.dev>
This commit is contained in:
@@ -67,6 +67,25 @@ export function splitTags(tags: string): string[] {
|
||||
return tags.split(',').filter((tag) => tag !== ' ' && tag);
|
||||
}
|
||||
|
||||
// The "Analyzers" field is a multiOptions parameter, so it normally resolves to
|
||||
// an array of "analyzerId::cortexId" entries. When its value comes from an
|
||||
// expression wrapped in surrounding text/whitespace, n8n switches to string
|
||||
// interpolation and the array is coerced to a comma-joined string. Normalize
|
||||
// both shapes so the operation does not throw "(...).map is not a function".
|
||||
export function parseAnalyzers(value: string | string[]) {
|
||||
const entries = Array.isArray(value)
|
||||
? value
|
||||
: value
|
||||
.split(',')
|
||||
.map((entry) => entry.trim())
|
||||
.filter((entry) => entry);
|
||||
|
||||
return entries.map((analyzer) => {
|
||||
const [analyzerId, cortexId] = analyzer.split('::');
|
||||
return { analyzerId, cortexId };
|
||||
});
|
||||
}
|
||||
|
||||
export function prepareOptional(optionals: IDataObject): IDataObject {
|
||||
const response: IDataObject = {};
|
||||
for (const key in optionals) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import { taskFields, taskOperations } from './descriptions/TaskDescription';
|
||||
import {
|
||||
buildCustomFieldSearch,
|
||||
mapResource,
|
||||
parseAnalyzers,
|
||||
prepareCustomFields,
|
||||
prepareOptional,
|
||||
prepareRangeQuery,
|
||||
@@ -752,14 +753,8 @@ export class TheHive implements INodeType {
|
||||
|
||||
if (operation === 'executeAnalyzer') {
|
||||
const observableId = this.getNodeParameter('id', i);
|
||||
const analyzers = (this.getNodeParameter('analyzers', i) as string[]).map(
|
||||
(analyzer) => {
|
||||
const parts = analyzer.split('::');
|
||||
return {
|
||||
analyzerId: parts[0],
|
||||
cortexId: parts[1],
|
||||
};
|
||||
},
|
||||
const analyzers = parseAnalyzers(
|
||||
this.getNodeParameter('analyzers', i) as string | string[],
|
||||
);
|
||||
let response: any;
|
||||
let body: IDataObject;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { parseAnalyzers } from '../GenericFunctions';
|
||||
|
||||
describe('Test TheHive, parseAnalyzers', () => {
|
||||
it('should map an array of "analyzerId::cortexId" entries', () => {
|
||||
const result = parseAnalyzers(['analyzer-1::cortex-1', 'analyzer-2::cortex-2']);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ analyzerId: 'analyzer-1', cortexId: 'cortex-1' },
|
||||
{ analyzerId: 'analyzer-2', cortexId: 'cortex-2' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should map a comma-joined string (expression coercion case)', () => {
|
||||
const result = parseAnalyzers('analyzer-1::cortex-1, analyzer-2::cortex-2');
|
||||
|
||||
expect(result).toEqual([
|
||||
{ analyzerId: 'analyzer-1', cortexId: 'cortex-1' },
|
||||
{ analyzerId: 'analyzer-2', cortexId: 'cortex-2' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle a single analyzer provided as a string', () => {
|
||||
const result = parseAnalyzers('analyzer-1::cortex-1');
|
||||
|
||||
expect(result).toEqual([{ analyzerId: 'analyzer-1', cortexId: 'cortex-1' }]);
|
||||
});
|
||||
|
||||
it('should drop empty entries from a comma-joined string', () => {
|
||||
const result = parseAnalyzers('analyzer-1::cortex-1,, analyzer-2::cortex-2,');
|
||||
|
||||
expect(result).toEqual([
|
||||
{ analyzerId: 'analyzer-1', cortexId: 'cortex-1' },
|
||||
{ analyzerId: 'analyzer-2', cortexId: 'cortex-2' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return an empty array for an empty string', () => {
|
||||
expect(parseAnalyzers('')).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user