UNPKG

n8n-nodes-binalyze-air

Version:

Binalyze AIR nodes for automating DFIR with n8n workflows

483 lines 19.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RepositoriesOperations = void 0; exports.buildRepositoryQueryParams = buildRepositoryQueryParams; exports.isValidRepository = isValidRepository; exports.extractRepositoryId = extractRepositoryId; exports.fetchAllRepositories = fetchAllRepositories; exports.getRepositoryById = getRepositoryById; exports.getRepositoryByName = getRepositoryByName; exports.getRepositories = getRepositories; exports.getRepositoriesOptions = getRepositoriesOptions; exports.executeRepositories = executeRepositories; const n8n_workflow_1 = require("n8n-workflow"); const helpers_1 = require("../utils/helpers"); const organizations_1 = require("./organizations"); exports.RepositoriesOperations = [ { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['repositories'], }, }, options: [ { name: 'Get', value: 'get', description: 'Get a repository by name', action: 'Get a repository', }, { name: 'Get Many', value: 'getAll', description: 'Get many repositories', action: 'Get many repositories', }, ], default: 'get', }, { displayName: 'Repository', name: 'repositoryId', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select a repository...', displayOptions: { show: { resource: ['repositories'], operation: ['get'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select a repository...', typeOptions: { searchListMethod: 'getRepositories', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid repository ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter repository ID (numeric or GUID)', }, { displayName: 'By Name', name: 'name', type: 'string', placeholder: 'Enter repository name', }, ], required: true, description: 'The repository to retrieve', }, { displayName: 'Organization', name: 'organizationId', type: 'resourceLocator', default: { mode: 'id', value: '0' }, placeholder: 'Select organization...', displayOptions: { show: { resource: ['repositories'], operation: ['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(s) to filter repositories. Use "0" for all organizations, specific IDs for multiple organizations, or search by name for a single organization.', }, { displayName: 'Additional Fields', name: 'additionalFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { resource: ['repositories'], operation: ['getAll'], }, }, options: [ { displayName: 'All Organizations', name: 'allOrganizations', type: 'boolean', default: false, description: 'Whether to include all organizations in the search', }, { displayName: 'Filter By Host', name: 'host', type: 'string', default: '', description: 'Filter repositories by host', }, { displayName: 'Filter By Name', name: 'name', type: 'string', default: '', description: 'Filter repositories by name (exact match)', }, { displayName: 'Filter By Path', name: 'path', type: 'string', default: '', description: 'Filter repositories by path', }, { displayName: 'Filter By Type', name: 'type', type: 'multiOptions', default: [], description: 'Filter repositories by type (multiple selection supported)', options: [ { name: 'Amazon S3', value: 'amazon-s3', }, { name: 'Azure Storage', value: 'azure-storage', }, { name: 'FTPS', value: 'ftps', }, { name: 'SFTP', value: 'sftp', }, { name: 'SMB', value: 'smb', }, ], }, { displayName: 'Filter By Username', name: 'username', type: 'string', default: '', description: 'Filter repositories by username', }, { displayName: 'Page Number', name: 'pageNumber', type: 'number', default: 1, description: 'Which page of results to return', typeOptions: { minValue: 1, }, }, { displayName: 'Page Size', name: 'pageSize', type: 'number', default: 100, description: 'How many results to return per page', typeOptions: { minValue: 1, }, }, { displayName: 'Search Term', name: 'searchTerm', type: 'string', default: '', description: 'Search repositories by name (supports partial matches)', }, ], }, ]; function buildRepositoryQueryParams(organizationId, additionalFields) { const queryParams = { 'filter[organizationIds]': organizationId, }; if (additionalFields.pageNumber !== undefined) { queryParams.pageNumber = additionalFields.pageNumber; } if (additionalFields.pageSize !== undefined) { queryParams.pageSize = additionalFields.pageSize; } if (additionalFields.type && additionalFields.type.length > 0) { queryParams['filter[type]'] = additionalFields.type; } if (additionalFields.searchTerm) { queryParams['filter[searchTerm]'] = additionalFields.searchTerm; } if (additionalFields.path) { queryParams['filter[path]'] = additionalFields.path; } if (additionalFields.username) { queryParams['filter[username]'] = additionalFields.username; } if (additionalFields.host) { queryParams['filter[host]'] = additionalFields.host; } if (additionalFields.name) { queryParams['filter[name]'] = additionalFields.name; } if (additionalFields.allOrganizations) { queryParams['filter[allOrganizations]'] = 'true'; } return queryParams; } function isValidRepository(repository) { return (0, helpers_1.isValidEntity)(repository, ['name', 'type']); } function extractRepositoryId(repository) { return (0, helpers_1.extractEntityId)(repository, 'repository'); } async function fetchAllRepositories(context, credentials, organizationId, filter, pageSize = 100) { var _a; const allRepositories = []; let currentPage = 1; let hasMorePages = true; while (hasMorePages) { const queryParams = { 'filter[organizationIds]': organizationId, pageNumber: currentPage, pageSize, }; if (filter) { queryParams['filter[searchTerm]'] = filter; } const options = (0, helpers_1.buildRequestOptions)(credentials, 'GET', '/api/public/evidences/repositories', queryParams); const responseData = await context.helpers.httpRequest(options); (0, helpers_1.validateApiResponse)(responseData, 'Failed to fetch repositories'); const repositories = ((_a = responseData.result) === null || _a === void 0 ? void 0 : _a.entities) || []; allRepositories.push(...repositories); const result = responseData.result; if (result && result.currentPage && result.totalPageCount && result.currentPage < result.totalPageCount) { currentPage++; } else { hasMorePages = false; } } return allRepositories; } async function getRepositoryById(context, credentials, organizationId, repositoryId) { var _a; const queryParams = { 'filter[organizationIds]': organizationId, 'filter[id]': repositoryId, pageSize: 1, }; const options = (0, helpers_1.buildRequestOptions)(credentials, 'GET', '/api/public/evidences/repositories', queryParams); const responseData = await context.helpers.httpRequest(options); (0, helpers_1.validateApiResponse)(responseData, 'Failed to fetch repository'); const repositories = ((_a = responseData.result) === null || _a === void 0 ? void 0 : _a.entities) || []; return repositories.length > 0 ? repositories[0] : null; } async function getRepositoryByName(context, credentials, organizationId, repositoryName) { var _a; const queryParams = { 'filter[organizationIds]': organizationId, 'filter[searchTerm]': repositoryName, pageSize: 100, }; const options = (0, helpers_1.buildRequestOptions)(credentials, 'GET', '/api/public/evidences/repositories', queryParams); const responseData = await context.helpers.httpRequest(options); (0, helpers_1.validateApiResponse)(responseData, 'Failed to fetch repository'); const repositories = ((_a = responseData.result) === null || _a === void 0 ? void 0 : _a.entities) || []; const exactMatch = repositories.find((repo) => repo.name && repo.name.toLowerCase() === repositoryName.toLowerCase()); if (exactMatch) { return exactMatch; } if (repositories.length > 0) { return repositories[0]; } return null; } async function getRepositories(filter) { try { const credentials = await (0, helpers_1.getAirCredentials)(this); const organizationId = '0'; const allRepositories = await fetchAllRepositories(this, credentials, organizationId, filter); return (0, helpers_1.createListSearchResults)(allRepositories, isValidRepository, (repository) => ({ name: `${repository.name} (${repository.type})`, value: extractRepositoryId(repository), url: repository.url || '', }), filter); } catch (error) { throw (0, helpers_1.catchAndFormatError)(error, 'load repositories'); } } async function getRepositoriesOptions() { try { const credentials = await (0, helpers_1.getAirCredentials)(this); const organizationId = '0'; const allRepositories = await fetchAllRepositories(this, credentials, organizationId); return (0, helpers_1.createLoadOptions)(allRepositories, isValidRepository, (repository) => { const repoId = extractRepositoryId(repository); const name = repository.name || `Repository ${repoId || 'Unknown'}`; const type = repository.type ? ` (${repository.type})` : ''; return { name: `${name}${type}`, value: repoId, }; }); } catch (error) { throw (0, helpers_1.catchAndFormatError)(error, 'load repositories'); } } async function executeRepositories() { var _a; const items = this.getInputData(); const returnData = []; const credentials = await (0, helpers_1.getAirCredentials)(this); for (let i = 0; i < items.length; i++) { try { const operation = this.getNodeParameter('operation', i); switch (operation) { case 'get': { const organizationId = '0'; const repositoryResource = this.getNodeParameter('repositoryId', i); let repository = null; if (repositoryResource.mode === 'list' || repositoryResource.mode === 'id') { const repositoryId = repositoryResource.value; try { const validatedRepositoryId = (0, helpers_1.normalizeAndValidateId)(repositoryId, 'Repository ID'); repository = await getRepositoryById(this, credentials, organizationId, validatedRepositoryId); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i, }); } } else if (repositoryResource.mode === 'name') { const repositoryName = repositoryResource.value; if (!repositoryName || typeof repositoryName !== 'string' || repositoryName.trim() === '') { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Repository name is required and must be a non-empty string', { itemIndex: i, }); } repository = await getRepositoryByName(this, credentials, organizationId, repositoryName.trim()); } else { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid repository selection mode', { itemIndex: i, }); } if (repository) { returnData.push({ json: repository, pairedItem: { item: i }, }); } else { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No repository found with ${repositoryResource.mode}: ${repositoryResource.value}`, { itemIndex: i, }); } break; } case 'getAll': { const organizationResource = this.getNodeParameter('organizationId', i); const additionalFields = this.getNodeParameter('additionalFields', i); let organizationId; if (organizationResource.mode === 'list' || organizationResource.mode === 'id') { organizationId = organizationResource.value; } else if (organizationResource.mode === 'name') { try { organizationId = await (0, organizations_1.findOrganizationByName)(this, credentials, organizationResource.value); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i }); } } else { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid organization selection mode', { itemIndex: i, }); } if (!organizationId || String(organizationId).trim() === '') { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Organization ID cannot be empty', { itemIndex: i, }); } const queryParams = buildRepositoryQueryParams(organizationId, additionalFields); const options = (0, helpers_1.buildRequestOptions)(credentials, 'GET', '/api/public/evidences/repositories', queryParams); const responseData = await this.helpers.httpRequest(options); (0, helpers_1.validateApiResponse)(responseData); 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, i, { includePagination: true, paginationData: paginationInfo, excludeFields: ['sortables', 'filters'], }); break; } default: throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation "${operation}" is not supported`, { itemIndex: i, }); } } catch (error) { (0, helpers_1.handleExecuteError)(this, error, i, returnData); } } return [returnData]; } //# sourceMappingURL=repositories.js.map