Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | /** * Analytics Command - Security analytics and metrics */ const { Command } = require('commander'); const chalk = require('chalk'); const ora = require('ora'); const { table } = require('table'); const logger = require('../utils/logger'); const APIClient = require('../services/api-client'); const analyticsCommand = new Command('analytics') .description('š View security analytics and metrics'); // Dashboard analytics analyticsCommand .command('dashboard') .description('Show security dashboard metrics') .option('--org <id>', 'organization ID') .option('--timeframe <period>', 'time period (7d|30d|90d|1y)', '30d') .option('--format <type>', 'output format (table|json)', 'table') .action(async (options) => { const spinner = ora('Fetching dashboard analytics...').start(); try { logger.command('analytics dashboard', options, true); const apiClient = new APIClient(); const response = await apiClient.get('/analytics/dashboard', { params: { organization_id: options.org, timeframe: options.timeframe } }); spinner.succeed('Analytics retrieved successfully'); const data = response.data; if (options.format === 'json') { console.log(JSON.stringify(data, null, 2)); return; } // Display formatted dashboard console.log(chalk.bold.cyan('\nš¢ Security Dashboard\n')); const overviewData = [ ['Metric', 'Value', 'Trend'], ['Total Vulnerabilities', data.total_vulnerabilities || 0, data.vuln_trend || 'N/A'], ['Critical Issues', data.critical_count || 0, data.critical_trend || 'N/A'], ['Fixed This Period', data.fixed_count || 0, data.fixed_trend || 'N/A'], ['Security Score', data.security_score || 'N/A', data.score_trend || 'N/A'], ['Scan Coverage', `${data.scan_coverage || 0}%`, data.coverage_trend || 'N/A'] ]; console.log(table(overviewData, { border: { topBody: 'ā', topJoin: 'ā¬', topLeft: 'ā', topRight: 'ā', bottomBody: 'ā', bottomJoin: 'ā“', bottomLeft: 'ā', bottomRight: 'ā', bodyLeft: 'ā', bodyRight: 'ā', bodyJoin: 'ā' } })); if (data.recent_scans && data.recent_scans.length > 0) { console.log(chalk.bold('\nš Recent Scans')); data.recent_scans.slice(0, 5).forEach(scan => { const status = scan.status === 'completed' ? 'ā ' : 'ā³'; console.log(` ${status} ${scan.repository} - ${scan.vulnerabilities_found} issues (${scan.created_at})`); }); } } catch (error) { spinner.fail('Failed to fetch analytics'); logger.error('Analytics dashboard error', { error: error.message }); if (error.response?.status === 401) { console.log(chalk.yellow('\nAuthentication required. Run: vaultace auth login')); } else { console.error(chalk.red(`Error: ${error.message}`)); } process.exit(1); } }); // Risk metrics analyticsCommand .command('risk') .description('Show risk assessment metrics') .option('--org <id>', 'organization ID') .option('--detailed', 'show detailed risk breakdown') .action(async (options) => { const spinner = ora('Calculating risk metrics...').start(); try { logger.command('analytics risk', options, true); const apiClient = new APIClient(); const response = await apiClient.get('/analytics/risk', { params: { organization_id: options.org, detailed: options.detailed } }); spinner.succeed('Risk metrics calculated'); const data = response.data; console.log(chalk.bold.red('\nā ļø Risk Assessment\n')); const riskData = [ ['Risk Category', 'Score', 'Level'], ['Overall Risk', data.overall_risk || 'N/A', data.risk_level || 'Unknown'], ['Code Quality', data.code_quality_risk || 'N/A', data.code_quality_level || 'Unknown'], ['Infrastructure', data.infrastructure_risk || 'N/A', data.infrastructure_level || 'Unknown'], ['Dependencies', data.dependency_risk || 'N/A', data.dependency_level || 'Unknown'], ['Compliance', data.compliance_risk || 'N/A', data.compliance_level || 'Unknown'] ]; console.log(table(riskData)); if (options.detailed && data.risk_factors) { console.log(chalk.bold('\nš Risk Factors')); data.risk_factors.forEach(factor => { const impact = factor.impact === 'high' ? 'š“' : factor.impact === 'medium' ? 'š”' : 'š¢'; console.log(` ${impact} ${factor.description} (Impact: ${factor.impact})`); }); } } catch (error) { spinner.fail('Failed to calculate risk metrics'); logger.error('Risk analytics error', { error: error.message }); console.error(chalk.red(`Error: ${error.message}`)); process.exit(1); } }); // Trends analysis analyticsCommand .command('trends') .description('Show security trends over time') .option('--timeframe <period>', 'time period (30d|90d|1y)', '90d') .option('--metric <type>', 'metric type (vulnerabilities|fixes|scans)', 'vulnerabilities') .action(async (options) => { const spinner = ora('Analyzing trends...').start(); try { logger.command('analytics trends', options, true); const apiClient = new APIClient(); const response = await apiClient.get('/analytics/trends', { params: { timeframe: options.timeframe, metric: options.metric } }); spinner.succeed('Trends analyzed'); const data = response.data; console.log(chalk.bold.blue(`\nš ${options.metric.toUpperCase()} Trends (${options.timeframe})\n`)); if (data.trend_data && data.trend_data.length > 0) { data.trend_data.forEach(point => { const bar = 'ā'.repeat(Math.floor(point.value / (data.max_value || 1) * 20)); console.log(`${point.date}: ${bar} ${point.value}`); }); console.log(`\nTrend: ${data.trend_direction} (${data.trend_percentage}%)`); } else { console.log('No trend data available for the selected period.'); } } catch (error) { spinner.fail('Failed to analyze trends'); logger.error('Trends analytics error', { error: error.message }); console.error(chalk.red(`Error: ${error.message}`)); process.exit(1); } }); module.exports = analyticsCommand; |