added stop start files and testing multivendor support
This commit is contained in:
128
backend/migrate_multivendor.js
Normal file
128
backend/migrate_multivendor.js
Normal file
@@ -0,0 +1,128 @@
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
const db = new sqlite3.Database('./cve_database.db');
|
||||
|
||||
console.log('🔄 Starting database migration for multi-vendor support...\n');
|
||||
|
||||
db.serialize(() => {
|
||||
// Backup existing data
|
||||
console.log('📦 Creating backup tables...');
|
||||
db.run(`CREATE TABLE IF NOT EXISTS cves_backup AS SELECT * FROM cves`, (err) => {
|
||||
if (err) console.error('Backup error:', err);
|
||||
else console.log('✓ CVEs backed up');
|
||||
});
|
||||
|
||||
db.run(`CREATE TABLE IF NOT EXISTS documents_backup AS SELECT * FROM documents`, (err) => {
|
||||
if (err) console.error('Backup error:', err);
|
||||
else console.log('✓ Documents backed up');
|
||||
});
|
||||
|
||||
// Drop old table
|
||||
console.log('\n🗑️ Dropping old cves table...');
|
||||
db.run(`DROP TABLE IF EXISTS cves`, (err) => {
|
||||
if (err) {
|
||||
console.error('Drop error:', err);
|
||||
return;
|
||||
}
|
||||
console.log('✓ Old table dropped');
|
||||
|
||||
// Create new table with UNIQUE(cve_id, vendor) instead of UNIQUE(cve_id)
|
||||
console.log('\n🏗️ Creating new cves table with multi-vendor support...');
|
||||
db.run(`
|
||||
CREATE TABLE cves (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
cve_id VARCHAR(20) NOT NULL,
|
||||
vendor VARCHAR(100) NOT NULL,
|
||||
severity VARCHAR(20) NOT NULL,
|
||||
description TEXT,
|
||||
published_date DATE,
|
||||
status VARCHAR(50) DEFAULT 'Open',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(cve_id, vendor)
|
||||
)
|
||||
`, (err) => {
|
||||
if (err) {
|
||||
console.error('Create error:', err);
|
||||
return;
|
||||
}
|
||||
console.log('✓ New table created with UNIQUE(cve_id, vendor)');
|
||||
|
||||
// Restore data
|
||||
console.log('\n📥 Restoring data...');
|
||||
db.run(`INSERT INTO cves SELECT * FROM cves_backup`, (err) => {
|
||||
if (err) {
|
||||
console.error('Restore error:', err);
|
||||
return;
|
||||
}
|
||||
console.log('✓ Data restored');
|
||||
|
||||
// Recreate indexes
|
||||
console.log('\n🔍 Creating indexes...');
|
||||
db.run(`CREATE INDEX idx_cve_id ON cves(cve_id)`, () => {
|
||||
console.log('✓ Index: idx_cve_id');
|
||||
});
|
||||
db.run(`CREATE INDEX idx_vendor ON cves(vendor)`, () => {
|
||||
console.log('✓ Index: idx_vendor');
|
||||
});
|
||||
db.run(`CREATE INDEX idx_severity ON cves(severity)`, () => {
|
||||
console.log('✓ Index: idx_severity');
|
||||
});
|
||||
db.run(`CREATE INDEX idx_status ON cves(status)`, () => {
|
||||
console.log('✓ Index: idx_status');
|
||||
});
|
||||
|
||||
// Update view
|
||||
console.log('\n👁️ Updating cve_document_status view...');
|
||||
db.run(`DROP VIEW IF EXISTS cve_document_status`, (err) => {
|
||||
if (err) console.error('Drop view error:', err);
|
||||
|
||||
db.run(`
|
||||
CREATE VIEW cve_document_status AS
|
||||
SELECT
|
||||
c.id as record_id,
|
||||
c.cve_id,
|
||||
c.vendor,
|
||||
c.severity,
|
||||
c.status,
|
||||
COUNT(DISTINCT d.id) as total_documents,
|
||||
COUNT(DISTINCT CASE WHEN d.type = 'advisory' THEN d.id END) as advisory_count,
|
||||
COUNT(DISTINCT CASE WHEN d.type = 'email' THEN d.id END) as email_count,
|
||||
COUNT(DISTINCT CASE WHEN d.type = 'screenshot' THEN d.id END) as screenshot_count,
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT CASE WHEN d.type = 'advisory' THEN d.id END) > 0
|
||||
THEN 'Complete'
|
||||
ELSE 'Missing Required Docs'
|
||||
END as compliance_status
|
||||
FROM cves c
|
||||
LEFT JOIN documents d ON c.cve_id = d.cve_id AND c.vendor = d.vendor
|
||||
GROUP BY c.id, c.cve_id, c.vendor, c.severity, c.status
|
||||
`, (err) => {
|
||||
if (err) {
|
||||
console.error('Create view error:', err);
|
||||
} else {
|
||||
console.log('✓ View recreated');
|
||||
}
|
||||
|
||||
console.log('\n✅ Migration complete!');
|
||||
console.log('\n📊 Summary:');
|
||||
|
||||
db.get('SELECT COUNT(*) as count FROM cves', (err, row) => {
|
||||
if (!err) console.log(` Total CVE entries: ${row.count}`);
|
||||
|
||||
db.get('SELECT COUNT(DISTINCT cve_id) as count FROM cves', (err, row) => {
|
||||
if (!err) console.log(` Unique CVE IDs: ${row.count}`);
|
||||
|
||||
console.log('\n💡 Next steps:');
|
||||
console.log(' 1. Restart backend: pkill -f "node server.js" && node server.js &');
|
||||
console.log(' 2. Replace frontend/src/App.js with multi-vendor version');
|
||||
console.log(' 3. Test by adding same CVE with multiple vendors\n');
|
||||
|
||||
db.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -13,7 +13,7 @@ const PORT = 3001;
|
||||
|
||||
// Middleware
|
||||
app.use(cors({
|
||||
origin: ['http://localhost:3000', 'http://192.168.2.117:3000'],
|
||||
origin: ['http://localhost:3000', 'http://71.85.90.6:3000'],
|
||||
credentials: true
|
||||
}));
|
||||
app.use(express.json());
|
||||
@@ -94,7 +94,7 @@ app.get('/api/cves', (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
// Check if CVE exists and get its status
|
||||
// Check if CVE exists and get its status - UPDATED FOR MULTI-VENDOR
|
||||
app.get('/api/cves/check/:cveId', (req, res) => {
|
||||
const { cveId } = req.params;
|
||||
|
||||
@@ -105,37 +105,63 @@ app.get('/api/cves/check/:cveId', (req, res) => {
|
||||
COUNT(CASE WHEN d.type = 'email' THEN 1 END) as has_email,
|
||||
COUNT(CASE WHEN d.type = 'screenshot' THEN 1 END) as has_screenshot
|
||||
FROM cves c
|
||||
LEFT JOIN documents d ON c.cve_id = d.cve_id
|
||||
LEFT JOIN documents d ON c.cve_id = d.cve_id AND c.vendor = d.vendor
|
||||
WHERE c.cve_id = ?
|
||||
GROUP BY c.id
|
||||
`;
|
||||
|
||||
db.get(query, [cveId], (err, row) => {
|
||||
db.all(query, [cveId], (err, rows) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: err.message });
|
||||
}
|
||||
if (!row) {
|
||||
if (!rows || rows.length === 0) {
|
||||
return res.json({
|
||||
exists: false,
|
||||
message: 'CVE not found - not yet addressed'
|
||||
});
|
||||
}
|
||||
|
||||
// Return all vendor entries for this CVE
|
||||
res.json({
|
||||
exists: true,
|
||||
cve: row,
|
||||
vendors: rows.map(row => ({
|
||||
vendor: row.vendor,
|
||||
severity: row.severity,
|
||||
status: row.status,
|
||||
total_documents: row.total_documents,
|
||||
compliance: {
|
||||
advisory: row.has_advisory > 0,
|
||||
email: row.has_email > 0,
|
||||
screenshot: row.has_screenshot > 0
|
||||
}
|
||||
})),
|
||||
addressed: true,
|
||||
has_required_docs: row.has_advisory > 0,
|
||||
compliance: {
|
||||
advisory: row.has_advisory > 0,
|
||||
email: row.has_email > 0,
|
||||
screenshot: row.has_screenshot > 0
|
||||
}
|
||||
has_required_docs: rows.some(row => row.has_advisory > 0)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Create new CVE entry
|
||||
// NEW ENDPOINT: Get all vendors for a specific CVE
|
||||
app.get('/api/cves/:cveId/vendors', (req, res) => {
|
||||
const { cveId } = req.params;
|
||||
|
||||
const query = `
|
||||
SELECT vendor, severity, status, description, published_date
|
||||
FROM cves
|
||||
WHERE cve_id = ?
|
||||
ORDER BY vendor
|
||||
`;
|
||||
|
||||
db.all(query, [cveId], (err, rows) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: err.message });
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Create new CVE entry - ALLOW MULTIPLE VENDORS
|
||||
app.post('/api/cves', (req, res) => {
|
||||
const { cve_id, vendor, severity, description, published_date } = req.body;
|
||||
|
||||
@@ -146,16 +172,23 @@ app.post('/api/cves', (req, res) => {
|
||||
|
||||
db.run(query, [cve_id, vendor, severity, description, published_date], function(err) {
|
||||
if (err) {
|
||||
// Check if it's a duplicate CVE_ID + Vendor combination
|
||||
if (err.message.includes('UNIQUE constraint failed')) {
|
||||
return res.status(409).json({
|
||||
error: 'This CVE already exists for this vendor. Choose a different vendor or update the existing entry.'
|
||||
});
|
||||
}
|
||||
return res.status(500).json({ error: err.message });
|
||||
}
|
||||
res.json({
|
||||
id: this.lastID,
|
||||
cve_id,
|
||||
message: 'CVE created successfully'
|
||||
message: `CVE created successfully for vendor: ${vendor}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Update CVE status
|
||||
app.patch('/api/cves/:cveId/status', (req, res) => {
|
||||
const { cveId } = req.params;
|
||||
@@ -173,13 +206,22 @@ app.patch('/api/cves/:cveId/status', (req, res) => {
|
||||
|
||||
// ========== DOCUMENT ENDPOINTS ==========
|
||||
|
||||
// Get documents for a CVE
|
||||
// Get documents for a CVE - FILTER BY VENDOR
|
||||
app.get('/api/cves/:cveId/documents', (req, res) => {
|
||||
const { cveId } = req.params;
|
||||
const { vendor } = req.query; // NEW: Optional vendor filter
|
||||
|
||||
const query = `SELECT * FROM documents WHERE cve_id = ? ORDER BY uploaded_at DESC`;
|
||||
let query = `SELECT * FROM documents WHERE cve_id = ?`;
|
||||
let params = [cveId];
|
||||
|
||||
db.all(query, [cveId], (err, rows) => {
|
||||
if (vendor) {
|
||||
query += ` AND vendor = ?`;
|
||||
params.push(vendor);
|
||||
}
|
||||
|
||||
query += ` ORDER BY uploaded_at DESC`;
|
||||
|
||||
db.all(query, params, (err, rows) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: err.message });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user