363 lines
12 KiB
JavaScript
363 lines
12 KiB
JavaScript
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 });
|
|
}
|
|
});
|
|
|
|
// Helper handler for deleting a specific .env history entry
|
|
async function handleDeleteHistory(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 });
|
|
}
|
|
}
|
|
|
|
// DELETE & POST /api/config/env/history/:id — Delete a specific .env history entry
|
|
router.delete('/env/history/:id', handleDeleteHistory);
|
|
router.post('/env/history/:id/delete', handleDeleteHistory);
|
|
|
|
// GET /api/config/user-signatures — Fetch all user signature images
|
|
router.get('/user-signatures', (req, res) => {
|
|
try {
|
|
const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10);
|
|
const signatures = db.prepare(`
|
|
SELECT * FROM user_signatures WHERE agent_id = ? ORDER BY id DESC
|
|
`).all(operatorId);
|
|
res.json(signatures);
|
|
} catch (err) {
|
|
console.error('Error fetching user signatures:', err);
|
|
res.status(500).json({ error: 'Errore durante il recupero delle firme utente', message: err.message });
|
|
}
|
|
});
|
|
|
|
// POST /api/config/user-signatures — Add new user signature image
|
|
router.post('/user-signatures', (req, res) => {
|
|
try {
|
|
const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10);
|
|
const { name, image_data } = req.body;
|
|
|
|
if (!name || !image_data) {
|
|
return res.status(400).json({ error: 'Nome e dati immagine sono obbligatori' });
|
|
}
|
|
|
|
const info = db.prepare(`
|
|
INSERT INTO user_signatures (agent_id, name, image_data)
|
|
VALUES (?, ?, ?)
|
|
`).run(operatorId, name.trim(), image_data);
|
|
|
|
const signatures = db.prepare(`
|
|
SELECT * FROM user_signatures WHERE agent_id = ? ORDER BY id DESC
|
|
`).all(operatorId);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Immagine/Firma salvata nel database con successo!',
|
|
id: info.lastInsertRowid,
|
|
signatures
|
|
});
|
|
} catch (err) {
|
|
console.error('Error saving user signature:', err);
|
|
res.status(500).json({ error: 'Errore durante il salvataggio della firma', message: err.message });
|
|
}
|
|
});
|
|
|
|
// DELETE /api/config/user-signatures/:id — Delete user signature image
|
|
router.delete('/user-signatures/:id', (req, res) => {
|
|
try {
|
|
const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10);
|
|
const { id } = req.params;
|
|
|
|
db.prepare(`DELETE FROM user_signatures WHERE id = ? AND agent_id = ?`).run(id, operatorId);
|
|
|
|
const signatures = db.prepare(`
|
|
SELECT * FROM user_signatures WHERE agent_id = ? ORDER BY id DESC
|
|
`).all(operatorId);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Firma eliminata con successo!',
|
|
signatures
|
|
});
|
|
} catch (err) {
|
|
console.error('Error deleting user signature:', err);
|
|
res.status(500).json({ error: 'Errore durante l\'eliminazione della firma', message: err.message });
|
|
}
|
|
});
|
|
|
|
// GET /api/config/user-shapes — List custom user shapes
|
|
router.get('/user-shapes', (req, res) => {
|
|
try {
|
|
const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10);
|
|
const shapes = db.prepare(`
|
|
SELECT * FROM user_shapes WHERE agent_id = ? ORDER BY id DESC
|
|
`).all(operatorId);
|
|
res.json(shapes);
|
|
} catch (err) {
|
|
console.error('Error fetching user shapes:', err);
|
|
res.status(500).json({ error: 'Errore durante il recupero delle forme utente', message: err.message });
|
|
}
|
|
});
|
|
|
|
// POST /api/config/user-shapes — Create a new custom shape
|
|
router.post('/user-shapes', (req, res) => {
|
|
try {
|
|
const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10);
|
|
const { name, shape_type, fill_color, border_color, border_width, is_favorite } = req.body;
|
|
|
|
if (!name) {
|
|
return res.status(400).json({ error: 'Il nome della forma è obbligatorio' });
|
|
}
|
|
|
|
const info = db.prepare(`
|
|
INSERT INTO user_shapes (agent_id, name, shape_type, fill_color, border_color, border_width, is_favorite)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
`).run(
|
|
operatorId,
|
|
name.trim(),
|
|
shape_type || 'rectangle',
|
|
fill_color || '#3b82f6',
|
|
border_color || '#1e3a8a',
|
|
parseInt(border_width || 3, 10),
|
|
is_favorite !== undefined ? (is_favorite ? 1 : 0) : 1
|
|
);
|
|
|
|
const shapes = db.prepare(`
|
|
SELECT * FROM user_shapes WHERE agent_id = ? ORDER BY id DESC
|
|
`).all(operatorId);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Forma salvata nei preferiti con successo!',
|
|
id: info.lastInsertRowid,
|
|
shapes
|
|
});
|
|
} catch (err) {
|
|
console.error('Error saving user shape:', err);
|
|
res.status(500).json({ error: 'Errore durante il salvataggio della forma', message: err.message });
|
|
}
|
|
});
|
|
|
|
// PUT /api/config/user-shapes/:id/toggle-favorite — Toggle favorite status
|
|
router.put('/user-shapes/:id/toggle-favorite', (req, res) => {
|
|
try {
|
|
const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10);
|
|
const { id } = req.params;
|
|
|
|
const shape = db.prepare(`SELECT * FROM user_shapes WHERE id = ? AND agent_id = ?`).get(id, operatorId);
|
|
if (!shape) {
|
|
return res.status(404).json({ error: 'Forma non trovata' });
|
|
}
|
|
|
|
const newFav = shape.is_favorite ? 0 : 1;
|
|
db.prepare(`UPDATE user_shapes SET is_favorite = ? WHERE id = ? AND agent_id = ?`).run(newFav, id, operatorId);
|
|
|
|
const shapes = db.prepare(`
|
|
SELECT * FROM user_shapes WHERE agent_id = ? ORDER BY id DESC
|
|
`).all(operatorId);
|
|
|
|
res.json({
|
|
success: true,
|
|
shapes
|
|
});
|
|
} catch (err) {
|
|
console.error('Error toggling shape favorite status:', err);
|
|
res.status(500).json({ error: 'Errore durante l\'aggiornamento dei preferiti', message: err.message });
|
|
}
|
|
});
|
|
|
|
// DELETE /api/config/user-shapes/:id — Delete a custom shape
|
|
router.delete('/user-shapes/:id', (req, res) => {
|
|
try {
|
|
const operatorId = parseInt(req.headers['x-agent-id'] || '1', 10);
|
|
const { id } = req.params;
|
|
|
|
db.prepare(`DELETE FROM user_shapes WHERE id = ? AND agent_id = ?`).run(id, operatorId);
|
|
|
|
const shapes = db.prepare(`
|
|
SELECT * FROM user_shapes WHERE agent_id = ? ORDER BY id DESC
|
|
`).all(operatorId);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Forma eliminata con successo!',
|
|
shapes
|
|
});
|
|
} catch (err) {
|
|
console.error('Error deleting user shape:', err);
|
|
res.status(500).json({ error: 'Errore durante l\'eliminazione della forma', message: err.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|