UNPKG

n8n-nodes-binalyze-air

Version:

Binalyze AIR nodes for automating DFIR with n8n workflows

891 lines 33.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CasesOperations = void 0; exports.extractCaseId = extractCaseId; exports.isValidCase = isValidCase; exports.resolveUserResourceLocator = resolveUserResourceLocator; exports.resolveCaseResourceLocator = resolveCaseResourceLocator; exports.findOrganizationByName = findOrganizationByName; exports.getCases = getCases; exports.getCasesOptions = getCasesOptions; exports.getUsers = getUsers; exports.executeCases = executeCases; const helpers_1 = require("../utils/helpers"); const users_1 = require("./users"); const cases_1 = require("../api/cases/cases"); const organizations_1 = require("../api/organizations/organizations"); exports.CasesOperations = [ { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['cases'], }, }, options: [ { name: 'Change Owner', value: 'changeOwner', description: 'Change the owner of a case', action: 'Change case owner', }, { name: 'Check Name', value: 'checkName', description: 'Check if a case name is available', action: 'Check case name availability', }, { name: 'Close Case', value: 'closeCase', description: 'Close a specific case', action: 'Close a case', }, { name: 'Create', value: 'create', description: 'Create a new case', action: 'Create a case', }, { name: 'Get', value: 'get', description: 'Retrieve a specific case', action: 'Get a case', }, { name: 'Get Activities', value: 'getActivities', description: 'Get activities for a specific case', action: 'Get case activities', }, { name: 'Get Endpoints', value: 'getEndpoints', description: 'Get endpoints for a specific case', action: 'Get case endpoints', }, { name: 'Get Many', value: 'getAll', description: 'Retrieve many cases', action: 'Get many cases', }, { name: 'Get Tasks', value: 'getTasks', description: 'Get tasks for a specific case', action: 'Get case tasks', }, { name: 'Get Users', value: 'getUsers', description: 'Get users for a specific case', action: 'Get case users', }, ], default: 'getAll', }, { displayName: 'Case', name: 'caseId', type: 'resourceLocator', default: { mode: 'id', value: '' }, placeholder: 'Select a case...', displayOptions: { show: { resource: ['cases'], operation: [ 'get', ], }, }, modes: [ { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid case ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter case ID', }, ], required: true, description: 'The ID of the case to retrieve', }, { displayName: 'Organization', name: 'organizationId', type: 'resourceLocator', default: { mode: 'id', value: '0' }, placeholder: 'Select organization...', displayOptions: { show: { resource: ['cases'], operation: [ 'getActivities', 'getEndpoints', 'getTasks', 'getUsers', 'changeOwner', 'closeCase', ], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select an organization...', typeOptions: { searchListMethod: 'getOrganizations', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[0-9,\\s]+$', errorMessage: 'Organization IDs must be comma-separated numbers. Use "0" for all organizations.', }, }, ], placeholder: 'Enter organization IDs (comma-separated) or "0" for all', }, { displayName: 'By Name', name: 'name', type: 'string', placeholder: 'Enter organization name', }, ], required: true, description: 'Organization to filter cases', }, { displayName: 'Case', name: 'caseId', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select a case...', displayOptions: { show: { resource: ['cases'], operation: [ 'getActivities', 'getEndpoints', 'getTasks', 'getUsers', 'changeOwner', 'closeCase' ], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select a case...', typeOptions: { searchListMethod: 'getCases', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid case ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter case ID', }, ], required: true, description: 'The case to operate on', }, { displayName: 'Case Name', name: 'caseName', type: 'string', default: '', placeholder: 'Enter case name', displayOptions: { show: { resource: ['cases'], operation: ['create', 'checkName'], }, }, required: true, description: 'The name of the case', }, { displayName: 'Organization', name: 'organizationId', type: 'resourceLocator', default: { mode: 'id', value: '0' }, placeholder: 'Select organization...', displayOptions: { show: { resource: ['cases'], operation: ['create', 'getAll'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select an organization...', typeOptions: { searchListMethod: 'getOrganizations', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[0-9,\\s]+$', errorMessage: 'Organization IDs must be comma-separated numbers. Use "0" for all organizations.', }, }, ], placeholder: 'Enter organization IDs (comma-separated) or "0" for all', }, { displayName: 'By Name', name: 'name', type: 'string', placeholder: 'Enter organization name', }, ], required: true, description: 'Organization for the case. For getAll operation, use "0" for all organizations.', }, { displayName: 'Owner User', name: 'ownerUserId', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select a user...', displayOptions: { show: { resource: ['cases'], operation: ['create'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select a user...', typeOptions: { searchListMethod: 'getUsers', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid user ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter user ID (alphanumeric or GUID)', }, { displayName: 'By Username', name: 'username', type: 'string', placeholder: 'Enter username or email', }, ], required: true, description: 'The user who will own the case', }, { displayName: 'New Owner User', name: 'newOwnerUserId', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select a user...', displayOptions: { show: { resource: ['cases'], operation: ['changeOwner'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select a user...', typeOptions: { searchListMethod: 'getUsers', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid user ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter user ID (alphanumeric or GUID)', }, { displayName: 'By Username', name: 'username', type: 'string', placeholder: 'Enter username or email', }, ], required: true, description: 'The new owner user for the case', }, { displayName: 'Visibility', name: 'visibility', type: 'options', default: 'public-to-organization', displayOptions: { show: { resource: ['cases'], operation: ['create'], }, }, options: [ { name: 'Public to Organization', value: 'public-to-organization', }, { name: 'Private to Users', value: 'private-to-users', }, ], required: true, description: 'The visibility of the case', }, { displayName: 'Assigned User IDs', name: 'assignedUserIds', type: 'string', default: '', placeholder: 'Enter comma-separated user IDs (optional)', displayOptions: { show: { resource: ['cases'], operation: ['create'], visibility: ['private-to-users'], }, }, description: 'Comma-separated list of user IDs to assign to the case (required for private cases)', }, { displayName: 'Additional Fields', name: 'additionalFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { resource: ['cases'], operation: ['getAll'], }, }, options: [ { displayName: 'Page Number', name: 'pageNumber', type: 'number', default: 1, description: 'The page number to retrieve', }, { displayName: 'Page Size', name: 'pageSize', type: 'number', default: 20, description: 'The number of items per page', }, { displayName: 'Search Term', name: 'searchTerm', type: 'string', default: '', description: 'Search term to filter cases', }, { displayName: 'Filter By Status', name: 'status', type: 'options', default: '', options: [ { name: 'All', value: '', }, { name: 'Open', value: 'open', }, { name: 'Closed', value: 'closed', }, { name: 'Archived', value: 'archived', }, ], description: 'Filter cases by status', }, ], }, ]; function extractCaseId(caseItem) { return (0, helpers_1.extractEntityId)(caseItem, '_id'); } function isValidCase(caseItem) { return (0, helpers_1.isValidEntity)(caseItem, ['_id']); } async function resolveUserResourceLocator(context, credentials, userResource, itemIndex, organizationIds) { if (!userResource || typeof userResource !== 'object') { throw new Error('Invalid user resource locator'); } let userId; if (userResource.mode === 'list' || userResource.mode === 'id') { userId = userResource.value; } else if (userResource.mode === 'username') { try { const orgIds = organizationIds || '0'; userId = await (0, users_1.findUserByUsername)(context, credentials, userResource.value, orgIds); } catch (error) { throw new Error(`Failed to find user by username: ${error instanceof Error ? error.message : String(error)}`); } } else { throw new Error('Invalid user selection mode'); } return (0, helpers_1.normalizeAndValidateId)(userId, 'User ID'); } async function resolveCaseResourceLocator(context, caseResource, itemIndex) { if (!caseResource || typeof caseResource !== 'object') { throw new Error('Invalid case resource locator'); } let caseId; if (caseResource.mode === 'list' || caseResource.mode === 'id') { caseId = caseResource.value; } else { throw new Error('Invalid case selection mode'); } return (0, helpers_1.normalizeAndValidateId)(caseId, 'Case ID'); } function getOrganizationIdFromContext(context) { try { const currentParams = context.getCurrentNodeParameters(); if (currentParams && currentParams.organizationId) { const orgResource = currentParams.organizationId; if (typeof orgResource === 'object') { if (orgResource.mode === 'id' || orgResource.mode === 'list') { return orgResource.value || '0'; } return '0'; } else if (typeof orgResource === 'string') { return orgResource; } } } catch (error) { } return '0'; } async function findOrganizationByName(context, credentials, organizationName) { try { const organizations = await organizations_1.api.getOrganizations(context, credentials, { pageSize: 100, searchTerm: organizationName }); if (!organizations.success || !organizations.result || !organizations.result.entities) { throw new Error('Failed to fetch organizations or invalid response structure'); } const matchingOrg = organizations.result.entities.find((org) => org.name && org.name.toLowerCase() === organizationName.toLowerCase()); if (!matchingOrg) { throw new Error(`Organization with name "${organizationName}" not found`); } return String(matchingOrg._id); } catch (error) { throw new Error(`Failed to find organization by name: ${error instanceof Error ? error.message : String(error)}`); } } async function getCases(filter) { var _a; const credentials = await (0, helpers_1.getAirCredentials)(this); try { let organizationIds = '0'; try { const currentParams = this.getCurrentNodeParameters(); if (currentParams && currentParams.organizationId) { const organizationId = currentParams.organizationId; if (typeof organizationId === 'string') { organizationIds = organizationId; } else if (organizationId && typeof organizationId === 'object') { if (organizationId.mode === 'id' || organizationId.mode === 'list') { organizationIds = organizationId.value || '0'; } else if (organizationId.mode === 'name' && organizationId.value) { try { organizationIds = await findOrganizationByName(this, credentials, organizationId.value); } catch (error) { organizationIds = '0'; } } } } } catch (error) { } const response = await cases_1.api.getCases(this, credentials, organizationIds, { pageSize: 100, searchTerm: filter }); (0, helpers_1.validateApiResponse)(response, 'Failed to fetch cases'); if (!((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities)) { return { results: [] }; } return (0, helpers_1.createListSearchResults)(response.result.entities, isValidCase, (caseItem) => ({ name: caseItem.name || 'Unnamed Case', value: extractCaseId(caseItem), }), filter); } catch (error) { if (error instanceof Error) { throw error; } throw new Error('Failed to fetch cases for selection'); } } async function getCasesOptions() { var _a; const credentials = await (0, helpers_1.getAirCredentials)(this); try { let organizationIds = '0'; try { const currentParams = this.getCurrentNodeParameters(); if (currentParams && currentParams.organizationId) { const organizationId = currentParams.organizationId; if (typeof organizationId === 'string') { organizationIds = organizationId; } else if (organizationId && typeof organizationId === 'object') { if (organizationId.mode === 'id' || organizationId.mode === 'list') { organizationIds = organizationId.value || '0'; } else if (organizationId.mode === 'name' && organizationId.value) { try { organizationIds = await findOrganizationByName(this, credentials, organizationId.value); } catch (error) { organizationIds = '0'; } } } } } catch (error) { } const response = await cases_1.api.getCases(this, credentials, organizationIds, { pageSize: 100 }); (0, helpers_1.validateApiResponse)(response, 'Failed to fetch cases'); if (!((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities)) { return []; } return (0, helpers_1.createLoadOptions)(response.result.entities, isValidCase, (caseItem) => ({ name: caseItem.name || 'Unnamed Case', value: extractCaseId(caseItem), })); } catch (error) { if (error instanceof Error) { throw error; } throw new Error('Failed to fetch cases options'); } } async function getUsers(filter) { try { const credentials = await (0, helpers_1.getAirCredentials)(this); const organizationIds = getOrganizationIdFromContext(this); const allUsers = await (0, users_1.fetchAllUsers)(this, credentials, organizationIds, filter); return (0, helpers_1.createListSearchResults)(allUsers, users_1.isValidUser, (user) => ({ name: user.username || user.email || `User ${(0, users_1.extractUserId)(user)}`, value: (0, users_1.extractUserId)(user), url: user.url || '', }), filter); } catch (error) { if (error instanceof Error) { throw error; } throw new Error('Failed to fetch users for selection'); } } async function executeCases() { var _a; const items = this.getInputData(); const returnData = []; const operation = this.getNodeParameter('operation', 0); const credentials = await (0, helpers_1.getAirCredentials)(this); for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { try { let responseData; switch (operation) { case 'getAll': responseData = await executeGetAllCases.call(this, credentials, itemIndex); break; case 'get': responseData = await executeGetCase.call(this, credentials, itemIndex); break; case 'create': responseData = await executeCreateCase.call(this, credentials, itemIndex); break; case 'closeCase': responseData = await executeCloseCase.call(this, credentials, itemIndex); break; case 'changeOwner': responseData = await executeChangeOwner.call(this, credentials, itemIndex); break; case 'checkName': responseData = await executeCheckName.call(this, credentials, itemIndex); break; case 'getActivities': responseData = await executeGetActivities.call(this, credentials, itemIndex); break; case 'getEndpoints': responseData = await executeGetEndpoints.call(this, credentials, itemIndex); break; case 'getTasks': responseData = await executeGetTasks.call(this, credentials, itemIndex); break; case 'getUsers': responseData = await executeGetUsers.call(this, credentials, itemIndex); break; default: throw new Error(`Unknown operation: ${operation}`); } if (operation === 'getAll' || operation === 'getActivities' || operation === 'getEndpoints' || operation === 'getTasks' || operation === 'getUsers') { const entities = ((_a = responseData.result) === null || _a === void 0 ? void 0 : _a.entities) || []; const paginationInfo = (0, helpers_1.extractPaginationInfo)(responseData.result); (0, helpers_1.processApiResponseEntities)(entities, returnData, itemIndex, { includePagination: true, paginationData: paginationInfo, excludeFields: ['sortables', 'filters'], }); } else if (operation === 'checkName') { returnData.push({ json: responseData, pairedItem: { item: itemIndex }, }); } else { const jsonData = responseData.result || responseData; returnData.push({ json: jsonData, pairedItem: { item: itemIndex }, }); } } catch (error) { (0, helpers_1.handleExecuteError)(this, error, itemIndex, returnData); } } return [returnData]; } async function executeGetAllCases(credentials, itemIndex) { const organizationResource = this.getNodeParameter('organizationId', itemIndex); const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}); let organizationIds = '0'; if (organizationResource.mode === 'id') { organizationIds = organizationResource.value; } else if (organizationResource.mode === 'name') { organizationIds = await findOrganizationByName(this, credentials, organizationResource.value); } else if (organizationResource.mode === 'list') { organizationIds = organizationResource.value; } const response = await cases_1.api.getCases(this, credentials, organizationIds, additionalFields); (0, helpers_1.validateApiResponse)(response, 'Failed to fetch cases'); return response; } async function executeGetCase(credentials, itemIndex) { var _a; const caseResource = this.getNodeParameter('caseId', itemIndex); const caseId = await resolveCaseResourceLocator(this, caseResource, itemIndex); const response = await cases_1.api.getCase(this, credentials, caseId); if (!response.success) { const errorMessage = ((_a = response.errors) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'API request failed'; throw new Error(`Failed to get case: ${errorMessage}`); } if (!response.result) { throw new Error('Case not found'); } return response; } async function executeCreateCase(credentials, itemIndex) { var _a; const caseName = this.getNodeParameter('caseName', itemIndex); const organizationResource = this.getNodeParameter('organizationId', itemIndex); const ownerUserResource = this.getNodeParameter('ownerUserId', itemIndex); const visibility = this.getNodeParameter('visibility', itemIndex); const assignedUserIdsParam = this.getNodeParameter('assignedUserIds', itemIndex, ''); let organizationId; if (organizationResource.mode === 'id') { organizationId = parseInt(organizationResource.value); } else if (organizationResource.mode === 'name') { const orgId = await findOrganizationByName(this, credentials, organizationResource.value); organizationId = parseInt(orgId); } else if (organizationResource.mode === 'list') { organizationId = parseInt(organizationResource.value); } else { throw new Error('Invalid organization selection'); } const ownerUserId = await resolveUserResourceLocator(this, credentials, ownerUserResource, itemIndex, organizationId.toString()); let assignedUserIds = []; if (assignedUserIdsParam.trim()) { assignedUserIds = assignedUserIdsParam.split(',').map(id => id.trim()).filter(id => id); } if (visibility === 'private-to-users' && assignedUserIds.length === 0) { throw new Error('Assigned User IDs are required when visibility is set to "private-to-users"'); } const caseData = { organizationId, name: caseName, ownerUserId, visibility, assignedUserIds }; const response = await cases_1.api.createCase(this, credentials, caseData); if (!response.success) { const errorMessage = ((_a = response.errors) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'API request failed'; throw new Error(`Failed to create case: ${errorMessage}`); } return response; } async function executeCloseCase(credentials, itemIndex) { var _a; const caseResource = this.getNodeParameter('caseId', itemIndex); const caseId = await resolveCaseResourceLocator(this, caseResource, itemIndex); const response = await cases_1.api.closeCase(this, credentials, caseId); if (!response.success) { const errorMessage = ((_a = response.errors) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'API request failed'; throw new Error(`Failed to close case: ${errorMessage}`); } return response; } async function executeChangeOwner(credentials, itemIndex) { var _a; const caseResource = this.getNodeParameter('caseId', itemIndex); const caseId = await resolveCaseResourceLocator(this, caseResource, itemIndex); const newOwnerUserResource = this.getNodeParameter('newOwnerUserId', itemIndex); const newOwnerUserId = await resolveUserResourceLocator(this, credentials, newOwnerUserResource, itemIndex, '0'); const response = await cases_1.api.changeOwner(this, credentials, caseId, newOwnerUserId); if (!response.success) { const errorMessage = ((_a = response.errors) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'API request failed'; throw new Error(`Failed to change case owner: ${errorMessage}`); } return response; } async function executeCheckName(credentials, itemIndex) { var _a; const caseName = this.getNodeParameter('caseName', itemIndex); const response = await cases_1.api.checkCaseName(this, credentials, caseName); if (!response.success) { const errorMessage = ((_a = response.errors) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'API request failed'; throw new Error(`Failed to check case name: ${errorMessage}`); } return response; } async function executeGetActivities(credentials, itemIndex) { const caseResource = this.getNodeParameter('caseId', itemIndex); const caseId = await resolveCaseResourceLocator(this, caseResource, itemIndex); const response = await cases_1.api.getCaseActivities(this, credentials, caseId); (0, helpers_1.validateApiResponse)(response, 'Failed to fetch case activities'); return response; } async function executeGetEndpoints(credentials, itemIndex) { const caseResource = this.getNodeParameter('caseId', itemIndex); const caseId = await resolveCaseResourceLocator(this, caseResource, itemIndex); const response = await cases_1.api.getCaseEndpoints(this, credentials, caseId, '0'); (0, helpers_1.validateApiResponse)(response, 'Failed to fetch case endpoints'); return response; } async function executeGetTasks(credentials, itemIndex) { const caseResource = this.getNodeParameter('caseId', itemIndex); const caseId = await resolveCaseResourceLocator(this, caseResource, itemIndex); const response = await cases_1.api.getCaseTasksById(this, credentials, caseId, '0'); (0, helpers_1.validateApiResponse)(response, 'Failed to fetch case tasks'); return response; } async function executeGetUsers(credentials, itemIndex) { const caseResource = this.getNodeParameter('caseId', itemIndex); const caseId = await resolveCaseResourceLocator(this, caseResource, itemIndex); const response = await cases_1.api.getCaseUsers(this, credentials, caseId, '0'); (0, helpers_1.validateApiResponse)(response, 'Failed to fetch case users'); return response; } //# sourceMappingURL=cases.js.map