feat: Implementación completa de Soft Delete para apps

- Agregados campos deleted, deleted_at, deleted_reason a MonitoredApp
- Implementado soft_delete_app() y restore_app() en ConfigManager
- Modificado get_apps() para filtrar apps eliminadas por defecto
- Agregados métodos get_all_apps() y get_deleted_apps()
- Actualizado unregister_app() para usar soft delete en lugar de hard delete
- Creados endpoints:
  * GET /api/apps/deleted - Ver historial de apps eliminadas
  * POST /api/apps/:name/restore - Restaurar app eliminada
- Agregada sección de Historial en index.html con UI completa
- Botón de restaurar para cada app eliminada
- El servicio systemd se elimina físicamente, solo el JSON mantiene historial
- Permite auditoría y recuperación de apps eliminadas accidentalmente
This commit is contained in:
2026-01-19 19:40:47 -05:00
parent 60f38be957
commit 13b36dda5f
6 changed files with 365 additions and 7 deletions

View File

@@ -88,6 +88,9 @@ impl AppManager {
mode,
service_file_path,
registered_at,
deleted: false,
deleted_at: None,
deleted_reason: None,
systemd_service: None,
created_at: None,
};
@@ -104,7 +107,7 @@ impl AppManager {
pub fn unregister_app(&self, app_name: &str) -> Result<()> {
let logger = get_logger();
logger.info("AppManager", &format!("Desregistrando aplicación: {}", app_name));
logger.info("AppManager", &format!("Desregistrando aplicación (soft delete): {}", app_name));
// Obtener configuración
let config = self.apps.get(app_name)
@@ -119,7 +122,7 @@ impl AppManager {
// Deshabilitar el servicio
let _ = SystemCtl::disable(&service_name);
// Eliminar archivo de servicio
// Eliminar archivo de servicio (físicamente)
ServiceGenerator::delete_service_file(&service_name)?;
// Recargar daemon
@@ -128,13 +131,14 @@ impl AppManager {
// Eliminar de memoria
self.apps.remove(app_name);
// Eliminar de monitored_apps.json
// SOFT DELETE en monitored_apps.json (mantener historial)
let config_manager = get_config_manager();
if let Err(e) = config_manager.remove_app(app_name) {
logger.warning("AppManager", "No se pudo eliminar de monitored_apps.json", Some(&e));
let delete_reason = Some("Eliminada desde el panel de control".to_string());
if let Err(e) = config_manager.soft_delete_app(app_name, delete_reason) {
logger.warning("AppManager", "No se pudo hacer soft delete en monitored_apps.json", Some(&e));
}
logger.info("AppManager", &format!("Aplicación {} desregistrada exitosamente", app_name));
logger.info("AppManager", &format!("Aplicación {} desregistrada exitosamente (soft delete)", app_name));
Ok(())
}