update search command to use FTS5 SQLite table for complex searches

This commit is contained in:
Charlotte Croce 2025-04-18 14:51:43 -04:00
parent d839089153
commit 167829704a
8 changed files with 1359 additions and 267 deletions

View file

@ -1,14 +1,15 @@
/**
* sigma_search_service.js
*
* This service provides functionality for searching Sigma rules by keywords.
* This service provides functionality for searching Sigma rules by keywords and complex queries.
* It processes search results and returns them in a structured format.
* Supports pagination for large result sets.
*/
const { searchRules } = require('../../sigma_db/sigma_db_queries');
const { searchRules, searchRulesComplex } = require('../../sigma_db/sigma_db_queries');
const { parseComplexQuery } = require('../../lang/query_parser');
const logger = require('../../utils/logger');
const { convertSigmaRule } = require('./sigma_converter_service');
const { getFileName } = require('../../utils/file_utils');
const FILE_NAME = getFileName(__filename);
@ -153,6 +154,109 @@ async function searchSigmaRules(keyword, page = 1, pageSize = 10) {
}
}
/**
* Searches for Sigma rules using complex query conditions
* Supports filtering by title, logsource, tags, dates, and more
*
* @param {string} queryString - The complex query string to parse
* @param {number} page - Page number (1-based index, default: 1)
* @param {number} pageSize - Number of results per page (default: 10)
* @returns {Promise<Object>} Result object with success flag and processed results
*/
async function searchSigmaRulesComplex(queryString, page = 1, pageSize = 10) {
if (!queryString || typeof queryString !== 'string') {
logger.warn(`${FILE_NAME}: Cannot perform complex search: Missing or invalid query string`);
return {
success: false,
message: 'Missing or invalid complex query'
};
}
// Validate pagination parameters
if (typeof page !== 'number' || page < 1) {
logger.warn(`${FILE_NAME}: Invalid page number: ${page}, defaulting to 1`);
page = 1;
}
if (typeof pageSize !== 'number' || pageSize < 1 || pageSize > 100) {
logger.warn(`${FILE_NAME}: Invalid page size: ${pageSize}, defaulting to 10`);
pageSize = 10;
}
// Calculate the offset based on page number
const offset = (page - 1) * pageSize;
logger.info(`${FILE_NAME}: Performing complex search with query: "${queryString}" (page ${page}, size ${pageSize})`);
try {
// Parse the complex query string
const parsedQuery = parseComplexQuery(queryString);
if (!parsedQuery.valid) {
logger.warn(`${FILE_NAME}: Invalid complex query: ${parsedQuery.error}`);
return {
success: false,
message: `Invalid query: ${parsedQuery.error}`
};
}
// Perform the database search with the parsed query
const searchResult = await searchRulesComplex(parsedQuery, pageSize, offset);
// Defensive handling of possible return formats
let allResults = [];
let totalCount = 0;
// Handle search results
if (searchResult) {
if (Array.isArray(searchResult.results)) {
allResults = searchResult.results;
totalCount = searchResult.totalCount || 0;
}
}
if (allResults.length === 0) {
return {
success: true,
results: [],
message: `No rules found matching the complex query criteria`,
pagination: {
currentPage: page,
pageSize: pageSize,
totalPages: Math.ceil(totalCount / pageSize),
totalResults: totalCount,
hasMore: false
}
};
}
// Calculate pagination info
const totalPages = Math.ceil(totalCount / pageSize);
const hasMore = (offset + pageSize) < totalCount;
return {
success: true,
results: allResults,
count: allResults.length,
query: parsedQuery,
pagination: {
currentPage: page,
pageSize: pageSize,
totalPages: totalPages,
totalResults: totalCount,
hasMore: hasMore
}
};
} catch (error) {
logger.error(`${FILE_NAME}: Error in complex search: ${error.message}`);
logger.debug(`${FILE_NAME}: Error stack: ${error.stack}`);
return {
success: false,
message: `Error performing complex search: ${error.message}`
};
}
}
/**
* Enhanced search that returns fully converted rule objects with pagination support
* This is a more expensive operation than basic search
@ -210,5 +314,6 @@ async function searchAndConvertRules(keyword, page = 1, pageSize = 10) {
module.exports = {
searchSigmaRules,
searchSigmaRulesComplex,
searchAndConvertRules
};