diff --git a/MEMORY.md b/MEMORY.md index f9313cd..a6d13ba 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -1,218 +1,43 @@ -# UrBackup Plugin - Memoria di Sviluppo +# MEMORY.md - Stato del Plugin UrBackup -## Informazioni Plugin -- **Nome**: UrBackup -- **Versione**: 0.5.0 -- **Compatibilità**: GLPI 11.0.6+, PHP 8.3+ -- **Namespace**: `GlpiPlugin\Urbackup` +## Ultima modifica: 22/05/2026 -## Struttura File -``` -plugin_urbackup/ -├── setup.php # Hook init, menu, tab, versione, prerequisiti -├── hook.php # Install/uninstall, massive actions, class list -├── composer.json # PSR-4 autoloading -├── src/ -│ ├── Config.php # Configurazione plugin (Computer sempre attivo, capacità) -│ ├── Profile.php # Diritti utente -│ ├── Server.php # CRUD server UrBackup -│ ├── ServerAsset.php # Linking asset-server -│ ├── AssetTab.php # Tab UrBackup su asset GLPI -│ ├── MassiveAction.php # Azioni massive connect/disconnect -│ ├── UrbackupApiClient.php # Client API UrBackup -│ ├── LocationHelper.php # Helper assegnazione server per location -│ ├── Capacity/ -│ │ └── UrBackupCapacity.php # Capacity per Asset Definition GLPI 11 -│ ├── Controller/ -│ │ ├── ServerController.php -│ │ ├── AssetController.php -│ │ └── ConfigController.php -│ └── Command/ -│ └── TestApiCommand.php -├── install/ -│ ├── install.php # Schema DB, migrazioni, capacity migration -│ ├── uninstall.php # Drop tabelle, pulizia diritti -│ └── mysql/ -│ └── plugin_urbackup-empty.sql # Schema iniziale -├── front/ -│ ├── config.form.php # Config plugin (Computer info) -│ ├── server.php # Lista server -│ ├── server.form.php # Form server con tab laterali -│ └── asset.form.php # Azioni asset (connect/disconnect/backup) -├── ajax/ -│ └── server_test.php # Test connessione API -├── templates/ -│ └── config/ -│ └── config.html.twig # Config page Twig -├── locales/ # Traduzioni (it, en, de) -├── css/ & js/ # Asset frontend -└── MEMORY.md # Questo file -``` +## Performance - Asset Definition vs Computer -## Classi Principali -| Classe | Descrizione | -|--------|-------------| -| `Config` | Configurazione plugin, isItemtypeEnabled | -| `Profile` | Diritti utente, permessi | -| `Server` | CRUD server UrBackup | -| `ServerAsset` | Linking asset-server | -| `AssetTab` | Tab UrBackup su asset | -| `MassiveAction` | Azioni massive connect/disconnect | -| `UrbackupApiClient` | Client API UrBackup (PBKDF2 auth) | -| `LocationHelper` | Assegnazione server per location | -| `Capacity/UrBackupCapacity` | Capacity per Asset Definition (cleanup + tracking) | -| `Controller/ServerController` | Route Symfony per server | -| `Controller/AssetController` | Route Symfony per azioni asset | -| `Command/TestApiCommand` | CLI test API | +### Problema +Gli Asset Definition custom (GLPI 11) sono 2-5x più lenti dei Computer nativi nel caricamento del tab UrBackup. -## Interfacce GLPI -- Menu: Amministrazione → Server UrBackup -- Tab UrBackup su Computer (sempre) + tutti gli Asset Definition -- Config: Computer sempre attivo; Asset Definition gestiti via native Capacities UI +### Causa +L'overhead è in GLPI 11 core, non nel plugin: +1. **`Asset::__construct()`** — itera 30+ Capacity classi per ogni istanza +2. **`Asset::post_getFromDB()`** — decodifica JSON custom fields e li processa +3. **`eval()` autoloading** — le classi concrete sono definite via `eval()` a runtime -## Architettura Capacities (v0.5.0) +### Ottimizzazioni applicate +1. **`AssetTab.php::loadApiData()`** — letto `$item->fields['name']` direttamente invece di chiamare `ServerAsset::getAssetName()` che faceva una seconda `getFromDB()` ridondante +2. **`AssetTab.php::startBackup()`, `saveInternetMode()`, `saveDefaultDirs()`, `showServerLinkedBlock()`** — stesso pattern, `$item->fields['name']` al posto di `getAssetName()` +3. **`Server.php::showMissingClientsTab()`** — batch loading IP e gruppi: `batchLoadIps()` (1 query per itemtype vs 1 per riga) + `batchLoadGroups()` (1 query per itemtype vs 1 per riga) -### Flusso -``` -Kernel boot: PostBootEvent -├── (110) InitializePlugins → plugin_init_urbackup() -│ ├── Plugin::registerClass(AssetTab, ['Computer']) ← Computer legacy -│ └── AssetDefinitionManager::registerCapacity() ← UrBackupCapacity registrata -│ -├── (100) CustomObjectsBoot → bootDefinitions() -│ └── foreach definition con UrBackupCapacity abilitata: -│ └── UrBackupCapacity::onClassBootstrap($classname) -│ └── CommonGLPI::registerStandardTab($classname, AssetTab::class) -│ ↑ Tab registrato QUI, dopo che le definizioni sono caricate dal DB -│ -Config::isItemtypeEnabled($itemtype) -├── '' → false -├── 'Computer' → true -├── Asset subclass → true ← SEMPRE visibile -└── altro → false -│ -UrBackupCapacity -├── onClassBootstrap() → registra AssetTab sul definition classname -├── onCapacityDisabled() → pulisce ServerAsset entries -├── isUsed() / getCapacityUsageDescription() → UI Capacities -``` +## Architettura +- `src/Capacity/UrBackupCapacity.php` — registra `AssetTab` via `CommonGLPI::registerStandardTab()` in `onClassBootstrap()` +- `setup.php` — registra capacità, CSS, JS, hook +- `src/AssetTab.php` — display tab content + tab interni (Stato/Azioni/Info-Log) +- `src/ServerAsset.php` — gestione collegamenti asset-server +- `src/Config.php` — itemtype enabled check +- `src/UrbackupApiClient.php` — client API con caching in-memory (per istanza) e sessione +- `src/LocationHelper.php` — risoluzione location radice +- `src/Server.php` — CRUD server, tab missing clients, form -### Separazione responsabilità -- **Registrazione tab**: `UrBackupCapacity::onClassBootstrap()` — chiamata da `bootDefinitions()` per ogni definizione con capacità abilitata -- **Visibilità tab**: `Config::isItemtypeEnabled()` — sempre true per Asset subclasses -- **Pulizia**: `UrBackupCapacity::onCapacityDisabled()` — quando admin disabilita la capacità -- **Config**: Computer sempre attivo; Capacities gestite dalla UI nativa GLPI +## Asset Tab Interni +- 3 sub-tab: Stato, Azioni (solo UPDATE/CREATE), Info/Log +- CSS: tab con tonalità di grigio differenti (scuro/medio/chiaro) +- Caricamento dati API con caching sessione 30s +- Dati caricati: status, settings, authkey, backup recenti (10), log (50) -### Bug risolto: tab non registrato su Asset Definition nuovi -- **Causa**: `setup.php` iterava `getDefinitions()` durante `plugin_init_urbackup()`, ma `bootDefinitions()` (che carica le definizioni dal DB) gira DOPO (priority 100 vs 110), quindi `getDefinitions()` tornava sempre array vuoto -- **Fix**: La registrazione del tab è stata spostata in `UrBackupCapacity::onClassBootstrap()`, chiamata da `bootstrapDefinition()` durante `bootDefinitions()`, quando le definizioni sono già caricate e la classe dinamica è disponibile -- **Rimosso**: loop `foreach ($defs ...)` e debug logging da `setup.php` -- **Rimosso**: debug logging da `AssetTab.php` +## Cache +- `UrbackupApiClient`: cache in-memory per `getStatus()` e `getClientSettings()` +- `AssetTab::loadApiData()`: cache sessione 30s (chiave: server_id + client_name) +- API timeout: 30s, connect timeout: 5s -## Tabella glpi_plugin_urbackup_assettypes -- Colonna `is_default` rimossa (non serve più con capacities) -- Tabella vestigiale — non più usata per la logica applicativa -- Migrazione: `plugin_urbackup_install_convert_assettypes_to_capacities()` abilita capacità su tutte le definizioni - -## Comandi Utili -```bash -# Installare il plugin -php bin/console glpi:plugin:install urbackup - -# Attivare -php bin/console glpi:plugin:activate urbackup - -# Disinstallare -echo "yes" | php bin/console glpi:plugin:uninstall urbackup - -# Verificare syntax PHP -php -l plugins/urbackup/src/*.php plugins/urbackup/front/*.php plugins/urbackup/*.php -``` - -## Checklist Pre-Consegna -- [x] `declare(strict_types=1);` in ogni file PHP -- [x] Namespace `GlpiPlugin\Urbackup\` e PSR-4 corretto -- [x] Check versione GLPI 11.0.6+ in `setup.php` -- [x] CSRF e permessi su ogni POST/AJAX -- [x] Query parametrizzate o `$DB->request()` -- [x] Output escaped e loggato -- [x] Nessun uso di API deprecate GLPI 11 -- [x] Compatibilità PHP 8.3 verificata - -## Da Completare -1. Test funzionalità lista server e form -2. AJAX endpoint comunicazione API - -### Verifiche Post-Migrazione Capacity -- [x] Tab UrBackup appare su Asset Definition nuovo (Computer + Asset) -- [ ] Upgrade da v0.4.x converte righe attive -- [ ] Colonna `is_default` droppata -- [ ] Disabilitazione capacità pulisce ServerAsset (onCapacityDisabled) - -## API UrBackup - Riferimenti - -### Endpoint API -| Metodo | Descrizione | -|--------|-------------| -| `login` | Autenticazione username/password | -| `get_status` | Lista client con stato backup | -| `get_backups` | Lista backup per client | -| `start_backup` | Avvia backup (file/image) | -| `get_progress` | Monitora progresso backup | -| `get_clients` | Lista clienti | -| `get_groups` | Lista gruppi | - -### Problemi Noti -- JSON Parse Error: API restituisce HTML invece di JSON con credenziali errate -- Timeout: Verificare raggiungibilità server UrBackup -- SSL: Se `ignore_ssl` attivo, accettare certificati self-signed -- AJAX 403: Funziona solo da browser con sessione GLPI attiva - -## Cronologia Modifiche - -### v0.4.2 — Refactoring server.form.php e tab laterali -- Side tabs a sinistra con nav-pills -- 4 tab: Server, Linked, Unlinked, Missing clients -- Missing clients con search/sort, location/AIP/group/state -- Navigazione server sopra i tab, indipendente -- Breadcrumb admin -- Fix namespace `getCachedName()`, Gruppo da `glpi_groups_items` -- Permessi: READ per accesso form, Connect/API nascosti per READ -- i18n: 17 stringhe nuove (it, en, de) -- Bug fix: ServerAsset colonne, asset.form.php disconnectAsset(), strict_types in 11 file - -### v0.4.6 — Funzionalità API completate -- Salvataggio Internet Mode su server UrBackup -- Salvataggio Default Dirs -- Backup file (incremental/full) -- Backup immagine (incremental/full) -- Recupero version client da API - -### v0.4.5 — Tabella semplificata serverassets -- Rimossi campi: client_name, client_ip, client_version, is_active, last_file_backup, last_image_backup, last_sync, date_creation, date_mod, urbackup_client_id -- Solo: id, plugin_urbackup_servers_id, itemtype, items_id - -### v0.4.4 — Tab Linked/Unlinked Clients -- Dati da API UrBackup invece che da DB -- Nome tabella corretto: `glpi_plugin_urbackup_serverassets` -- Campo: `plugin_urbackup_servers_id` - -### v0.4.3 — Test API Connection automatico -- Rimosso pulsante manuale -- Rimosse righe last status/message/check -- Stati: verde OK, rosso fallito, giallo irraggiungibile - -### v0.5.0 — Capacity System per Asset Definition GLPI 11 -- Rimpiazzata tabella custom `glpi_plugin_urbackup_assettypes` con Capacities native -- Computer: legacy (sempre attivo, fuori capacities) -- Asset Definition: tab sempre registrato, capacità gestisce cleanup -- `isItemtypeEnabled()` = true per tutti gli Asset -- `onClassBootstrap()` rimosso (poi reintrodotto in v0.5.1) -- File: `src/Capacity/UrBackupCapacity.php` -- Migration: auto-enable capacità su tutte le definizioni + drop is_default - -### v0.5.1 — Fix registrazione tab su Asset Definition nuovi -- **Bug**: Tab UrBackup non appariva su Asset Definition nuovi (es. `testnas`) -- **Causa**: `getDefinitions()` tornava 0 in `plugin_init_urbackup()` perché `bootDefinitions()` gira dopo (priority 100 vs 110) -- **Fix**: Spostata registrazione tab in `UrBackupCapacity::onClassBootstrap()` — chiamata durante `bootDefinitions()` per ogni definizione con capacità abilitata -- Rimossi debug logging superflui da `setup.php` e `AssetTab.php` +## Versione +- 0.6.0 diff --git a/public/css/urbackup.css b/public/css/urbackup.css index d700831..a4196a7 100644 --- a/public/css/urbackup.css +++ b/public/css/urbackup.css @@ -10,3 +10,46 @@ color: #b00; font-weight: bold; } + +#urbackupTabs .nav-link { + font-weight: 600; + border-width: 2px; + padding: 8px 18px; + margin-right: 4px; +} + +#urbackupTabs .nav-link#state-tab { + color: #fff; + background-color: #4a4a4a; + border-color: #4a4a4a; +} + +#urbackupTabs .nav-link#state-tab.active { + color: #fff; + background-color: #2d2d2d; + border-color: #2d2d2d; +} + +#urbackupTabs .nav-link#actions-tab { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +#urbackupTabs .nav-link#actions-tab.active { + color: #fff; + background-color: #495057; + border-color: #495057; +} + +#urbackupTabs .nav-link#logs-tab { + color: #fff; + background-color: #adb5bd; + border-color: #adb5bd; +} + +#urbackupTabs .nav-link#logs-tab.active { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} diff --git a/setup.php b/setup.php index f1b7c70..69f32cd 100644 --- a/setup.php +++ b/setup.php @@ -25,7 +25,7 @@ use GlpiPlugin\Urbackup\Server; use GlpiPlugin\Urbackup\ServerAsset; use GlpiPlugin\Urbackup\MassiveAction as PluginUrbackupMassiveAction; -define('PLUGIN_URBACKUP_VERSION', '0.5.0'); +define('PLUGIN_URBACKUP_VERSION', '0.6.0'); define('PLUGIN_URBACKUP_MIN_GLPI', '11.0.0'); define('PLUGIN_URBACKUP_MAX_GLPI', '11.99.99'); diff --git a/src/AssetTab.php b/src/AssetTab.php index 7037760..c6bf0b7 100644 --- a/src/AssetTab.php +++ b/src/AssetTab.php @@ -232,7 +232,7 @@ class AssetTab extends CommonDBTM echo "" . htmlspecialchars(__('UrBackup server version', 'urbackup')) . ""; echo "" . htmlspecialchars((string) ($server->fields['server_version'] ?? '')) . ""; echo "" . htmlspecialchars(__('Client name', 'urbackup')) . ""; - echo "" . htmlspecialchars(ServerAsset::getAssetName($item::class, (int) $item->fields['id'])) . ""; + echo "" . htmlspecialchars((string) ($item->fields['name'] ?? '')) . ""; echo ""; echo ""; @@ -263,9 +263,14 @@ class AssetTab extends CommonDBTM */ private static function loadApiData(CommonDBTM $item, Server $server, array $link): array { - $client_name = ServerAsset::getAssetName($item::class, (int) $item->fields['id']); + $client_name = (string) ($item->fields['name'] ?? ''); $asset_ip = ServerAsset::extractAssetIp($item); + $cache_key = 'urbackup_data_' . $server->fields['id'] . '_' . $client_name; + if (isset($_SESSION[$cache_key]) && $_SESSION[$cache_key]['time'] > time() - 30) { + return $_SESSION[$cache_key]['data']; + } + $data = [ 'client_found' => false, 'client_status' => [], @@ -309,6 +314,11 @@ class AssetTab extends CommonDBTM $data['error'] = $e->getMessage(); } + $_SESSION[$cache_key] = [ + 'time' => time(), + 'data' => $data, + ]; + return $data; } @@ -332,19 +342,19 @@ class AssetTab extends CommonDBTM $canWrite = Session::haveRight(self::$rightname, UPDATE) || Session::haveRight(self::$rightname, CREATE); - echo '