const express = require('express'); const router = express.Router(); const fs = require('fs'); const path = require('path'); const { db, logAttivita } = require('../activityDb'); const pool = require('../db'); const baseDir = process.pkg ? path.dirname(process.execPath) : path.resolve(__dirname, '..'); const envPath = fs.existsSync(path.resolve(baseDir, '.env')) ? path.resolve(baseDir, '.env') : path.resolve(__dirname, '..', '.env'); // Helper to resolve agent name from DB async function resolveAgentName(agentId) { try { const r = await pool.query( `SELECT first_name, last_name, login FROM users WHERE id = $1`, [agentId] ); if (r.rows.length > 0) { const u = r.rows[0]; return (u.first_name || '') + ' ' + (u.last_name || '') || u.login || `Agent #${agentId}`; } } catch (_) { /* ignore */ } return `Agent #${agentId}`; } // GET /api/config/env — Read current .env file and history router.get('/env', async (req, res) => { try { let content = ''; if (fs.existsSync(envPath)) { content = fs.readFileSync(envPath, 'utf8'); } const history = db.prepare(` SELECT * FROM env_history ORDER BY id DESC LIMIT 100 `).all(); res.json({ content, history }); } catch (err) { console.error('Error reading env config:', err); res.status(500).json({ error: 'Errore durante la lettura del file .env', message: err.message }); } }); // POST /api/config/env — Save updated .env content and create snapshot in SQLite router.post('/env', async (req, res) => { try { const { content, note } = req.body; const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10); const agentName = await resolveAgentName(operatorId); if (typeof content !== 'string') { return res.status(400).json({ error: 'Il contenuto del file .env è obbligatorio' }); } // If history is empty and current .env exists, create an initial baseline snapshot const countRow = db.prepare('SELECT COUNT(*) AS count FROM env_history').get(); if (countRow.count === 0 && fs.existsSync(envPath)) { const initialContent = fs.readFileSync(envPath, 'utf8'); db.prepare(` INSERT INTO env_history (agent_id, agent_name, content, note) VALUES (?, ?, ?, ?) `).run(operatorId, agentName, initialContent, 'Baseline iniziale preesistente'); } // Write updated content to disk fs.writeFileSync(envPath, content, 'utf8'); try { require('dotenv').config({ path: envPath, override: true }); } catch (_) {} // Save snapshot in history table const info = db.prepare(` INSERT INTO env_history (agent_id, agent_name, content, note) VALUES (?, ?, ?, ?) `).run(operatorId, agentName, content, note || 'Modifica manuale .env'); logAttivita({ agente_id: operatorId, agente_nome: agentName, titolo_azione: 'Modifica .env', azione: { note: note || 'Modifica manuale .env', history_id: info.lastInsertRowid }, esito: 'successo', }); const history = db.prepare(` SELECT * FROM env_history ORDER BY id DESC LIMIT 100 `).all(); res.json({ success: true, message: 'File .env aggiornato e salvato nello storico locale con successo!', history_id: info.lastInsertRowid, history, }); } catch (err) { console.error('Error saving .env config:', err); res.status(500).json({ error: 'Errore durante il salvataggio del file .env', message: err.message }); } }); // POST /api/config/env/restore/:history_id — Restore a previous .env snapshot router.post('/env/restore/:history_id', async (req, res) => { try { const { history_id } = req.params; const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10); const agentName = await resolveAgentName(operatorId); const record = db.prepare('SELECT * FROM env_history WHERE id = ?').get(history_id); if (!record) { return res.status(404).json({ error: 'Versione di storico non trovata' }); } // Write snapshot content to disk fs.writeFileSync(envPath, record.content, 'utf8'); try { require('dotenv').config({ path: envPath, override: true }); } catch (_) {} // Insert new history record documenting the restore operation const restoreNote = `Ripristinato alla versione #${record.id} del ${record.created_at}`; const info = db.prepare(` INSERT INTO env_history (agent_id, agent_name, content, note) VALUES (?, ?, ?, ?) `).run(operatorId, agentName, record.content, restoreNote); logAttivita({ agente_id: operatorId, agente_nome: agentName, titolo_azione: 'Ripristino .env', azione: { restored_from_id: record.id, new_history_id: info.lastInsertRowid }, esito: 'successo', }); const history = db.prepare(` SELECT * FROM env_history ORDER BY id DESC LIMIT 100 `).all(); res.json({ success: true, message: `Versione #${record.id} ripristinata con successo!`, content: record.content, history, }); } catch (err) { console.error('Error restoring .env version:', err); res.status(500).json({ error: 'Errore durante il ripristino della versione .env', message: err.message }); } }); // DELETE /api/config/env/history/:id — Delete a specific .env history entry router.delete('/env/history/:id', async (req, res) => { try { const { id } = req.params; const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10); const agentName = await resolveAgentName(operatorId); const record = db.prepare('SELECT * FROM env_history WHERE id = ?').get(id); if (!record) { return res.status(404).json({ error: 'Versione di storico non trovata' }); } db.prepare('DELETE FROM env_history WHERE id = ?').run(id); logAttivita({ agente_id: operatorId, agente_nome: agentName, titolo_azione: 'Eliminazione Storico .env', azione: { deleted_history_id: id }, esito: 'successo', }); const history = db.prepare(` SELECT * FROM env_history ORDER BY id DESC LIMIT 100 `).all(); res.json({ success: true, message: `Versione #${id} dello storico eliminata con successo!`, history, }); } catch (err) { console.error('Error deleting .env history entry:', err); res.status(500).json({ error: 'Errore durante l\'eliminazione della versione dello storico', message: err.message }); } }); module.exports = router;