Fix: Enable multi-vendor support for CVE entries
- Changed CVEs table constraint from UNIQUE(cve_id) to UNIQUE(cve_id, vendor) - Added vendor column to documents table for proper file organization - Updated backend INSERT statements to include vendor field in both CVE and document creation - Fixed document retrieval to filter by vendor - Created corrected setup.js that includes multi-vendor support from initial setup - Added migration scripts for existing databases Resolves #1: Users can now add the same CVE-ID with multiple different vendors, each maintaining separate document storage organized as CVE-ID/Vendor/files
This commit is contained in:
@@ -11,9 +11,15 @@ const fs = require('fs');
|
||||
const app = express();
|
||||
const PORT = 3001;
|
||||
|
||||
// Log all incoming requests
|
||||
app.use((req, res, next) => {
|
||||
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
|
||||
next();
|
||||
});
|
||||
|
||||
// Middleware
|
||||
app.use(cors({
|
||||
origin: ['http://localhost:3000', 'http://71.85.90.6:3000'],
|
||||
origin: ['http://localhost:3000', 'http://192.168.2.117:3000'],
|
||||
credentials: true
|
||||
}));
|
||||
app.use(express.json());
|
||||
@@ -163,15 +169,24 @@ app.get('/api/cves/:cveId/vendors', (req, res) => {
|
||||
|
||||
// Create new CVE entry - ALLOW MULTIPLE VENDORS
|
||||
app.post('/api/cves', (req, res) => {
|
||||
const { cve_id, vendor, severity, description, published_date } = req.body;
|
||||
console.log('=== ADD CVE REQUEST ===');
|
||||
console.log('Body:', req.body);
|
||||
console.log('=======================');
|
||||
|
||||
const { cve_id, vendor, severity, description, published_date } = req.body;
|
||||
|
||||
const query = `
|
||||
INSERT INTO cves (cve_id, vendor, severity, description, published_date)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`;
|
||||
|
||||
|
||||
console.log('Query:', query);
|
||||
console.log('Values:', [cve_id, vendor, severity, description, published_date]);
|
||||
|
||||
db.run(query, [cve_id, vendor, severity, description, published_date], function(err) {
|
||||
if (err) {
|
||||
console.error('DATABASE ERROR:', err); // Make sure this is here
|
||||
// ... rest of error handling
|
||||
// Check if it's a duplicate CVE_ID + Vendor combination
|
||||
if (err.message.includes('UNIQUE constraint failed')) {
|
||||
return res.status(409).json({
|
||||
@@ -196,7 +211,8 @@ app.patch('/api/cves/:cveId/status', (req, res) => {
|
||||
|
||||
const query = `UPDATE cves SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE cve_id = ?`;
|
||||
|
||||
db.run(query, [status, cveId], function(err) {
|
||||
db.run(query, [
|
||||
vendor,status, cveId], function(err) {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: err.message });
|
||||
}
|
||||
@@ -229,66 +245,82 @@ app.get('/api/cves/:cveId/documents', (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
// Upload document
|
||||
app.post('/api/cves/:cveId/documents', upload.single('file'), (req, res) => {
|
||||
const { cveId } = req.params;
|
||||
const { type, notes, vendor } = req.body;
|
||||
const file = req.file;
|
||||
|
||||
if (!file) {
|
||||
return res.status(400).json({ error: 'No file uploaded' });
|
||||
}
|
||||
|
||||
if (!vendor) {
|
||||
return res.status(400).json({ error: 'Vendor is required' });
|
||||
}
|
||||
|
||||
// Move file from temp to proper location
|
||||
const finalDir = path.join('uploads', cveId, vendor);
|
||||
if (!fs.existsSync(finalDir)) {
|
||||
fs.mkdirSync(finalDir, { recursive: true });
|
||||
}
|
||||
|
||||
const finalPath = path.join(finalDir, file.filename);
|
||||
|
||||
// Move file from temp to final location
|
||||
fs.renameSync(file.path, finalPath);
|
||||
|
||||
const query = `
|
||||
INSERT INTO documents (cve_id, name, type, file_path, file_size, mime_type, notes)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
|
||||
const fileSizeKB = (file.size / 1024).toFixed(2) + ' KB';
|
||||
|
||||
db.run(query, [
|
||||
cveId,
|
||||
file.originalname,
|
||||
type,
|
||||
finalPath,
|
||||
fileSizeKB,
|
||||
file.mimetype,
|
||||
notes
|
||||
], function(err) {
|
||||
// Upload document - ADD ERROR HANDLING FOR MULTER
|
||||
app.post('/api/cves/:cveId/documents', (req, res, next) => {
|
||||
upload.single('file')(req, res, (err) => {
|
||||
if (err) {
|
||||
// If database insert fails, delete the file
|
||||
if (fs.existsSync(finalPath)) {
|
||||
fs.unlinkSync(finalPath);
|
||||
}
|
||||
return res.status(500).json({ error: err.message });
|
||||
console.error('MULTER ERROR:', err);
|
||||
return res.status(500).json({ error: 'File upload failed: ' + err.message });
|
||||
}
|
||||
res.json({
|
||||
id: this.lastID,
|
||||
message: 'Document uploaded successfully',
|
||||
file: {
|
||||
name: file.originalname,
|
||||
path: finalPath,
|
||||
size: fileSizeKB
|
||||
|
||||
console.log('=== UPLOAD REQUEST RECEIVED ===');
|
||||
console.log('CVE ID:', req.params.cveId);
|
||||
console.log('Body:', req.body);
|
||||
console.log('File:', req.file);
|
||||
console.log('================================');
|
||||
|
||||
const { cveId } = req.params;
|
||||
const { type, notes, vendor } = req.body;
|
||||
const file = req.file;
|
||||
|
||||
if (!file) {
|
||||
console.error('ERROR: No file uploaded');
|
||||
return res.status(400).json({ error: 'No file uploaded' });
|
||||
}
|
||||
|
||||
if (!vendor) {
|
||||
console.error('ERROR: Vendor is required');
|
||||
return res.status(400).json({ error: 'Vendor is required' });
|
||||
}
|
||||
|
||||
// Move file from temp to proper location
|
||||
const finalDir = path.join('uploads', cveId, vendor);
|
||||
if (!fs.existsSync(finalDir)) {
|
||||
fs.mkdirSync(finalDir, { recursive: true });
|
||||
}
|
||||
|
||||
const finalPath = path.join(finalDir, file.filename);
|
||||
|
||||
// Move file from temp to final location
|
||||
fs.renameSync(file.path, finalPath);
|
||||
|
||||
const query = `
|
||||
INSERT INTO documents (cve_id, vendor, name, type, file_path, file_size, mime_type, notes)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
|
||||
const fileSizeKB = (file.size / 1024).toFixed(2) + ' KB';
|
||||
|
||||
db.run(query, [
|
||||
cveId,
|
||||
vendor,
|
||||
file.originalname,
|
||||
type,
|
||||
finalPath,
|
||||
fileSizeKB,
|
||||
file.mimetype,
|
||||
notes
|
||||
], function(err) {
|
||||
if (err) {
|
||||
console.error('DATABASE ERROR:', err);
|
||||
// If database insert fails, delete the file
|
||||
if (fs.existsSync(finalPath)) {
|
||||
fs.unlinkSync(finalPath);
|
||||
}
|
||||
return res.status(500).json({ error: err.message });
|
||||
}
|
||||
res.json({
|
||||
id: this.lastID,
|
||||
message: 'Document uploaded successfully',
|
||||
file: {
|
||||
name: file.originalname,
|
||||
path: finalPath,
|
||||
size: fileSizeKB
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Delete document
|
||||
app.delete('/api/documents/:id', (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
Reference in New Issue
Block a user