n8n-nodes-binalyze-air
Version:
Binalyze AIR nodes for automating DFIR with n8n workflows
483 lines • 19.4 kB
JavaScript
;
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