76 lines
3.0 KiB
JavaScript
76 lines
3.0 KiB
JavaScript
|
|
// Migration: Add ivanti_finding_archives and ivanti_archive_transitions tables
|
||
|
|
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 finding archive tables migration...');
|
||
|
|
|
||
|
|
db.serialize(() => {
|
||
|
|
// Archive records — one row per finding that has entered the archive lifecycle
|
||
|
|
db.run(`
|
||
|
|
CREATE TABLE IF NOT EXISTS ivanti_finding_archives (
|
||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
|
finding_id TEXT NOT NULL UNIQUE,
|
||
|
|
finding_title TEXT NOT NULL DEFAULT '',
|
||
|
|
host_name TEXT NOT NULL DEFAULT '',
|
||
|
|
ip_address TEXT NOT NULL DEFAULT '',
|
||
|
|
current_state TEXT NOT NULL CHECK(current_state IN ('ACTIVE', 'ARCHIVED', 'RETURNED', 'CLOSED')),
|
||
|
|
last_severity REAL NOT NULL DEFAULT 0,
|
||
|
|
first_archived_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
last_transition_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
|
|
)
|
||
|
|
`, (err) => {
|
||
|
|
if (err) console.error('Error creating ivanti_finding_archives table:', err);
|
||
|
|
else console.log('✓ ivanti_finding_archives table created');
|
||
|
|
});
|
||
|
|
|
||
|
|
// Transition history — one row per state change on an archive record
|
||
|
|
db.run(`
|
||
|
|
CREATE TABLE IF NOT EXISTS ivanti_archive_transitions (
|
||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
|
archive_id INTEGER NOT NULL,
|
||
|
|
from_state TEXT NOT NULL,
|
||
|
|
to_state TEXT NOT NULL,
|
||
|
|
severity_at_transition REAL NOT NULL DEFAULT 0,
|
||
|
|
reason TEXT NOT NULL DEFAULT '',
|
||
|
|
transitioned_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
FOREIGN KEY (archive_id) REFERENCES ivanti_finding_archives(id)
|
||
|
|
)
|
||
|
|
`, (err) => {
|
||
|
|
if (err) console.error('Error creating ivanti_archive_transitions table:', err);
|
||
|
|
else console.log('✓ ivanti_archive_transitions table created');
|
||
|
|
});
|
||
|
|
|
||
|
|
// Indexes for query performance
|
||
|
|
db.run(`
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_archive_finding_id
|
||
|
|
ON ivanti_finding_archives(finding_id)
|
||
|
|
`, (err) => {
|
||
|
|
if (err) console.error('Error creating idx_archive_finding_id:', err);
|
||
|
|
else console.log('✓ idx_archive_finding_id index created');
|
||
|
|
});
|
||
|
|
|
||
|
|
db.run(`
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_archive_current_state
|
||
|
|
ON ivanti_finding_archives(current_state)
|
||
|
|
`, (err) => {
|
||
|
|
if (err) console.error('Error creating idx_archive_current_state:', err);
|
||
|
|
else console.log('✓ idx_archive_current_state index created');
|
||
|
|
});
|
||
|
|
|
||
|
|
db.run(`
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_transition_archive_id
|
||
|
|
ON ivanti_archive_transitions(archive_id)
|
||
|
|
`, (err) => {
|
||
|
|
if (err) console.error('Error creating idx_transition_archive_id:', err);
|
||
|
|
else console.log('✓ idx_transition_archive_id index created');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
db.close(() => {
|
||
|
|
console.log('Migration complete!');
|
||
|
|
});
|