UNPKG

n8n-nodes-binalyze-air

Version:

Binalyze AIR nodes for automating DFIR with n8n workflows

412 lines 15.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAirCredentials = getAirCredentials; exports.buildRequestOptions = buildRequestOptions; exports.validateApiResponse = validateApiResponse; exports.makeApiRequestWithErrorHandling = makeApiRequestWithErrorHandling; exports.buildRequestOptionsWithErrorHandling = buildRequestOptionsWithErrorHandling; exports.extractEntityId = extractEntityId; exports.normalizeAndValidateId = normalizeAndValidateId; exports.isValidEntity = isValidEntity; exports.validateAndExtractOrganizationId = validateAndExtractOrganizationId; exports.createListSearchResults = createListSearchResults; exports.createLoadOptions = createLoadOptions; exports.handleExecuteError = handleExecuteError; exports.extractEntitiesFromResponse = extractEntitiesFromResponse; exports.hasResponsePagination = hasResponsePagination; exports.extractPaginationInfo = extractPaginationInfo; exports.processApiResponseEntities = processApiResponseEntities; exports.catchAndFormatError = catchAndFormatError; const n8n_workflow_1 = require("n8n-workflow"); async function getAirCredentials(context) { const credentials = await context.getCredentials('airApi'); if (!credentials) { throw new Error('No credentials provided for Binalyze AIR'); } const instanceUrl = credentials.instanceUrl; const token = credentials.token; if (!instanceUrl || !token) { throw new Error('Missing instanceUrl or token in Binalyze AIR credentials'); } const normalizedInstanceUrl = instanceUrl.replace(/\/+$/, ''); return { instanceUrl: normalizedInstanceUrl, token, }; } function buildRequestOptions(credentials, method, endpoint, queryParams) { const options = { method, url: `${credentials.instanceUrl}${endpoint}`, headers: { 'Authorization': `Bearer ${credentials.token}`, 'Accept': 'application/json', 'Content-Type': 'application/json', }, json: true, }; if (queryParams && Object.keys(queryParams).length > 0) { options.qs = queryParams; } return options; } function validateApiResponse(responseData, context) { var _a; if (!responseData.success) { const errorMessage = ((_a = responseData.errors) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'API request failed'; const fullMessage = context ? `${context}: ${errorMessage}` : errorMessage; throw new Error(fullMessage); } } function handleApiError(context, error, operation, itemIndex) { var _a; let errorMessage = 'Unknown error occurred'; let statusCode = 500; let errors = []; let httpDetails = []; if ((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) { const responseData = error.response.data; statusCode = error.response.status || statusCode; httpDetails.push(`HTTP Status: ${statusCode}`); if (error.response.statusText) { httpDetails.push(`Status Text: ${error.response.statusText}`); } if (responseData.message) { if (Array.isArray(responseData.message)) { errors = responseData.message; errorMessage = errors.join(', '); } else { errorMessage = responseData.message; errors = [errorMessage]; } } else if (responseData.errors && Array.isArray(responseData.errors)) { errors = responseData.errors; errorMessage = errors.join(', '); } else if (responseData.error) { errorMessage = responseData.error; errors = [errorMessage]; if (responseData.error !== errorMessage) { httpDetails.push(`Error Type: ${responseData.error}`); } } else { errorMessage = `API request failed with status ${statusCode}`; errors = [errorMessage]; } if (responseData.statusCode) { httpDetails.push(`API Status Code: ${responseData.statusCode}`); } httpDetails.push(`Response Body: ${JSON.stringify(responseData, null, 2)}`); } else if (error.message) { errorMessage = error.message; errors = [errorMessage]; httpDetails.push(`Network/Connection Error: ${error.message}`); } const fullMessage = `Failed to ${operation}: ${errorMessage}`; const allDetails = [...errors]; if (httpDetails.length > 0) { allDetails.push('', 'HTTP Response Details:', ...httpDetails); } if (context && 'getNode' in context && itemIndex !== undefined) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), fullMessage, { itemIndex, description: allDetails.join('\n'), }); } else if (context && 'getNode' in context) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), fullMessage, { description: allDetails.join('\n'), }); } else { const detailedError = new Error(fullMessage); detailedError.details = allDetails.join('\n'); throw detailedError; } } async function makeApiRequestWithErrorHandling(context, requestOptions, operation, itemIndex) { try { const response = await context.helpers.httpRequest(requestOptions); if (response && typeof response === 'object' && response.statusCode && response.statusCode >= 400) { const httpError = { response: { status: response.statusCode, statusText: response.error || 'HTTP Error', data: response } }; handleApiError(context, httpError, operation, itemIndex); } if (response && typeof response === 'object' && 'success' in response) { if (!response.success) { const errors = response.errors || ['API request failed']; const errorMessage = errors.join(', '); const fullMessage = `Failed to ${operation}: ${errorMessage}`; const responseDetails = [ '', 'API Response Details:', `Success: ${response.success}`, `Response Body: ${JSON.stringify(response, null, 2)}` ]; if (context && 'getNode' in context && itemIndex !== undefined) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), fullMessage, { itemIndex, description: [...errors, ...responseDetails].join('\n'), }); } else if (context && 'getNode' in context) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), fullMessage, { description: [...errors, ...responseDetails].join('\n'), }); } else { throw new Error(fullMessage); } } } else if (!response) { const errorMessage = `Failed to ${operation}: No response data received`; if (context && 'getNode' in context && itemIndex !== undefined) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), errorMessage, { itemIndex }); } else if (context && 'getNode' in context) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), errorMessage); } else { throw new Error(errorMessage); } } return response; } catch (error) { if (error instanceof n8n_workflow_1.NodeOperationError) { throw error; } handleApiError(context, error, operation, itemIndex); } } function buildRequestOptionsWithErrorHandling(credentials, method, endpoint, queryParams) { const options = { method, url: `${credentials.instanceUrl}${endpoint}`, headers: { 'Authorization': `Bearer ${credentials.token}`, 'Accept': 'application/json', 'Content-Type': 'application/json', }, json: true, ignoreHttpStatusErrors: true, }; if (queryParams && Object.keys(queryParams).length > 0) { options.qs = queryParams; } return options; } function extractEntityId(entity, entityType = 'entity') { const entityId = entity._id || entity.id; if (entityId === undefined || entityId === null || entityId === '') { throw new Error(`${entityType.charAt(0).toUpperCase() + entityType.slice(1)} has no valid _id. ID value: ${entityId}, ID type: ${typeof entityId}. ` + `Available fields: ${Object.keys(entity).join(', ')}`); } return String(entityId); } function normalizeId(id) { if (id === null || id === undefined) { return null; } const stringId = String(id).trim(); if (stringId === '') { return null; } const numericId = Number(stringId); if (!isNaN(numericId)) { return stringId; } const guidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; if (guidPattern.test(stringId)) { return stringId; } const alphanumericPattern = /^[a-zA-Z0-9-_]+$/; if (alphanumericPattern.test(stringId)) { return stringId; } return null; } function normalizeAndValidateId(id, fieldName = 'ID') { const normalizedId = normalizeId(id); if (normalizedId === null) { throw new Error(`${fieldName} cannot be empty or invalid. Received: ${id} (type: ${typeof id})`); } return normalizedId; } function isValidEntity(entity, requiredFields = ['name']) { if (!entity) return false; try { extractEntityId(entity); return requiredFields.every(field => !!entity[field]); } catch { return false; } } async function validateAndExtractOrganizationId(context, credentials, organizationResource, itemIndex, findOrganizationByNameFn) { let organizationId; if (organizationResource.mode === 'list' || organizationResource.mode === 'id') { organizationId = organizationResource.value; if (!organizationId || String(organizationId).trim() === '' || organizationId === '__search_hint__') { throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Please select a valid organization from the list or enter a valid organization ID', { itemIndex, }); } } else if (organizationResource.mode === 'name') { const organizationName = organizationResource.value; if (!organizationName || String(organizationName).trim() === '') { throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Please enter a valid organization name', { itemIndex, }); } try { organizationId = await findOrganizationByNameFn(context, credentials, organizationName); } catch (error) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), error.message, { itemIndex }); } } else { throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Invalid organization selection mode', { itemIndex, }); } try { organizationId = normalizeAndValidateId(organizationId, 'Organization ID'); } catch (error) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), error.message, { itemIndex, }); } return organizationId; } function createListSearchResults(entities, validationFn, mapFn, filter) { const results = entities .filter(validationFn) .map(mapFn) .filter((item) => !filter || item.name.toLowerCase().includes(filter.toLowerCase()) || item.value === filter) .sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())); return { results }; } function createLoadOptions(entities, validationFn, mapFn) { return entities .filter(validationFn) .map(mapFn); } function handleExecuteError(context, error, itemIndex, returnData) { if (context.continueOnFail()) { let errorMessage = 'Unknown error occurred'; let errorDetails = undefined; if (error) { if (error instanceof Error) { errorMessage = error.message; if (error instanceof n8n_workflow_1.NodeOperationError) { errorDetails = { type: 'NodeOperationError', cause: error.cause, }; } } else if (typeof error === 'string') { errorMessage = error; } else if (typeof error === 'object') { errorMessage = error.message || error.error || JSON.stringify(error); } } returnData.push({ json: { error: errorMessage, errorDetails: errorDetails, }, pairedItem: itemIndex, }); } else { if (!error) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'An unknown error occurred', { itemIndex, }); } throw error instanceof n8n_workflow_1.NodeOperationError ? error : new n8n_workflow_1.NodeOperationError(context.getNode(), error, { itemIndex, }); } } function extractEntitiesFromResponse(responseData) { if (!responseData.result) { return []; } if (Array.isArray(responseData.result)) { return responseData.result; } if (responseData.result.entities && Array.isArray(responseData.result.entities)) { return responseData.result.entities; } return []; } function hasResponsePagination(responseData) { if (!responseData.result || Array.isArray(responseData.result)) { return false; } return responseData.result.totalEntityCount !== undefined; } function extractPaginationInfo(source) { let result; if (source && typeof source === 'object' && 'success' in source) { result = source.result; } else { result = source; } if (!result || Array.isArray(result)) { return null; } if (result.totalEntityCount !== undefined) { return { totalEntityCount: result.totalEntityCount, pageSize: result.pageSize, currentPage: result.currentPage, totalPageCount: result.totalPageCount, }; } return null; } function processApiResponseEntities(entities, returnData, itemIndex, options) { entities.forEach((entity) => { const jsonData = { ...entity }; if ((options === null || options === void 0 ? void 0 : options.includePagination) && options.paginationData) { let paginationToInclude = { ...options.paginationData }; if (options.excludeFields) { options.excludeFields.forEach(field => { delete paginationToInclude[field]; }); } jsonData._pagination = paginationToInclude; } returnData.push({ json: jsonData, pairedItem: itemIndex, }); }); } function catchAndFormatError(error, operation) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return new Error(`Failed to ${operation}: ${errorMessage}`); } //# sourceMappingURL=helpers.js.map