Files
cve-dashboard/backend/migrations/add_fp_submission_editing.js
jramos df30430956 feat: add FP submission editing with lifecycle tracking, clickable workflow badges, and edit modal
- Add migration for lifecycle_status, batch UUID, updated_at columns and submission history table
- Add backend endpoints: GET/PUT/POST/PATCH for viewing, editing, adding findings/attachments, and status changes
- Add pure helpers: validateLifecycleTransition, mergeFindings, buildSubmissionHistoryEntry
- Add FpEditModal with tabbed UI (Details, Findings, Attachments, History)
- Make workflow badges clickable for Reworked/Rejected/Expired states with pencil icon
- Add submissions list section to QueuePanel with lifecycle status badges
- Wire state and data flow in ReportingPage for submissions fetch and edit callbacks
2026-04-13 12:27:56 -06:00

95 lines
3.6 KiB
JavaScript

// Migration: Add FP submission editing support (lifecycle status, batch UUID, history table)
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 FP submission editing migration...');
db.serialize(() => {
// Add lifecycle_status column to ivanti_fp_submissions
// Wrapped in try/catch style via callback — SQLite throws if column already exists
db.run(
`ALTER TABLE ivanti_fp_submissions ADD COLUMN lifecycle_status TEXT NOT NULL DEFAULT 'submitted' CHECK(lifecycle_status IN ('submitted', 'approved', 'rejected', 'rework', 'resubmitted'))`,
(err) => {
if (err) {
if (err.message.includes('duplicate column')) {
console.log('✓ lifecycle_status column already exists');
} else {
console.error('Error adding lifecycle_status column:', err.message);
}
} else {
console.log('✓ lifecycle_status column added');
}
}
);
// Add ivanti_workflow_batch_uuid column
db.run(
`ALTER TABLE ivanti_fp_submissions ADD COLUMN ivanti_workflow_batch_uuid TEXT`,
(err) => {
if (err) {
if (err.message.includes('duplicate column')) {
console.log('✓ ivanti_workflow_batch_uuid column already exists');
} else {
console.error('Error adding ivanti_workflow_batch_uuid column:', err.message);
}
} else {
console.log('✓ ivanti_workflow_batch_uuid column added');
}
}
);
// Add updated_at column
db.run(
`ALTER TABLE ivanti_fp_submissions ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP`,
(err) => {
if (err) {
if (err.message.includes('duplicate column')) {
console.log('✓ updated_at column already exists');
} else {
console.error('Error adding updated_at column:', err.message);
}
} else {
console.log('✓ updated_at column added');
}
}
);
// Create submission history table
db.run(`
CREATE TABLE IF NOT EXISTS ivanti_fp_submission_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
submission_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
username TEXT NOT NULL,
change_type TEXT NOT NULL CHECK(change_type IN (
'created', 'fields_updated', 'findings_added',
'attachments_added', 'status_changed'
)),
change_details_json TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (submission_id) REFERENCES ivanti_fp_submissions(id) ON DELETE CASCADE
)
`, (err) => {
if (err) console.error('Error creating history table:', err.message);
else console.log('✓ ivanti_fp_submission_history table created');
});
// Create index on submission_id for history lookups
db.run(
`CREATE INDEX IF NOT EXISTS idx_fp_history_submission ON ivanti_fp_submission_history(submission_id)`,
(err) => {
if (err) console.error('Error creating history index:', err.message);
else console.log('✓ idx_fp_history_submission index created');
}
);
console.log('✓ Migration statements queued');
});
db.close(() => {
console.log('Migration complete!');
});