diff --git a/backend/migrations/add_todo_queue_ip_address.js b/backend/migrations/add_todo_queue_ip_address.js new file mode 100644 index 0000000..711f667 --- /dev/null +++ b/backend/migrations/add_todo_queue_ip_address.js @@ -0,0 +1,25 @@ +// Migration: Add ip_address column to ivanti_todo_queue +const sqlite3 = require('sqlite3').verbose(); +const path = require('path'); + +const dbPath = path.join(__dirname, '..', 'cve_database.db'); +const db = new sqlite3.Database(dbPath); + +console.log('Starting add_todo_queue_ip_address migration...'); + +db.run( + 'ALTER TABLE ivanti_todo_queue ADD COLUMN ip_address TEXT', + (err) => { + if (err) { + // Column may already exist if migration was run before + if (err.message.includes('duplicate column name')) { + console.log('✓ ip_address column already exists, skipping'); + } else { + console.error('Error adding column:', err); + } + } else { + console.log('✓ ip_address column added'); + } + db.close(() => console.log('Migration complete!')); + } +); diff --git a/backend/routes/ivantiTodoQueue.js b/backend/routes/ivantiTodoQueue.js index e18395b..3d4adf1 100644 --- a/backend/routes/ivantiTodoQueue.js +++ b/backend/routes/ivantiTodoQueue.js @@ -37,7 +37,7 @@ function createIvantiTodoQueueRouter(db, requireAuth) { // POST /api/ivanti/todo-queue // Add a finding to the queue router.post('/', requireAuth(db), (req, res) => { - const { finding_id, finding_title, cves, vendor, workflow_type } = req.body; + const { finding_id, finding_title, cves, ip_address, vendor, workflow_type } = req.body; if (!finding_id || typeof finding_id !== 'string' || finding_id.trim().length === 0) { return res.status(400).json({ error: 'finding_id is required.' }); @@ -55,15 +55,16 @@ function createIvantiTodoQueueRouter(db, requireAuth) { const vendorVal = workflow_type === 'CARD' ? '' : vendor.trim(); const cvesJson = Array.isArray(cves) ? JSON.stringify(cves) : null; + const ipVal = ip_address && typeof ip_address === 'string' ? ip_address.trim().slice(0, 64) : null; const title = finding_title && typeof finding_title === 'string' ? finding_title.slice(0, 500) : null; db.run( `INSERT INTO ivanti_todo_queue - (user_id, finding_id, finding_title, cves_json, vendor, workflow_type) - VALUES (?, ?, ?, ?, ?, ?)`, - [req.user.id, finding_id.trim(), title, cvesJson, vendorVal, workflow_type], + (user_id, finding_id, finding_title, cves_json, ip_address, vendor, workflow_type) + VALUES (?, ?, ?, ?, ?, ?, ?)`, + [req.user.id, finding_id.trim(), title, cvesJson, ipVal, vendorVal, workflow_type], function (err) { if (err) { console.error('Error adding to queue:', err); diff --git a/backend/server.js b/backend/server.js index e74e12d..0cd3059 100644 --- a/backend/server.js +++ b/backend/server.js @@ -138,6 +138,7 @@ const db = new sqlite3.Database('./cve_database.db', (err) => { finding_id TEXT NOT NULL, finding_title TEXT, cves_json TEXT, + ip_address TEXT, vendor TEXT NOT NULL, workflow_type TEXT NOT NULL CHECK(workflow_type IN ('FP', 'Archer', 'CARD')), status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'complete')), diff --git a/frontend/src/components/pages/ReportingPage.js b/frontend/src/components/pages/ReportingPage.js index 0b32740..1d3b95c 100644 --- a/frontend/src/components/pages/ReportingPage.js +++ b/frontend/src/components/pages/ReportingPage.js @@ -1361,6 +1361,7 @@ function QueuePanel({ open, items, onClose, onUpdate, onDelete, onClearCompleted const cveDisplay = cves.length > 0 ? cves.slice(0, 3).join(', ') + (cves.length > 3 ? ` +${cves.length - 3}` : '') : '—'; + const isCardItem = item.workflow_type === 'CARD'; return (