feat: version 2.15.0 -- menu Equipos (inventario de TI con agente GLPI)
Ingesta POST /api/inventory (JSON/XML, token de instalacion), upsert por deviceid, historial de cambios, pestañas Resumen/Equipos/Software/Agentes, detalle con buscador por pestaña y casilla para ocultar actualizaciones/drivers/componentes del software. Migraciones 023 y 024. Diseño en docs/ARQUITECTURA-INVENTARIO.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# Arquitectura de inventario — menú "Equipos"
|
||||
|
||||
Diseño del módulo Equipos de Project. Se trajo de `linkedtrack.linkedcorp.net` (que sigue como
|
||||
producto aparte, sin cambios) y se reescribió siguiendo las reglas de Project: mismo login, roles,
|
||||
auditoría, UI Fluent y una sola base `project_linkedcorp`.
|
||||
|
||||
## Decisión de fondo
|
||||
|
||||
| Opción | Veredicto |
|
||||
|---|---|
|
||||
| Servidor GLPI completo | Descartado: demasiada administración para solo inventariar. |
|
||||
| Agente 100% propio | Descartado: reescribir el sondeo de hardware (WMI, EDID, SNMP) es frágil y caro. |
|
||||
| **Agente GLPI oficial + colector propio dentro de Project** | **Elegido.** El agente recolecta; Project recibe, guarda y muestra. |
|
||||
|
||||
## Flujo
|
||||
|
||||
```
|
||||
GLPI Agent (cada PC/servidor) --POST inventario--> https://project.linkedcorp.net/api/inventory
|
||||
(ingest.js: token -> inflar -> parsear JSON/XML
|
||||
-> normalizer.js -> upsert por deviceid
|
||||
-> diff en device_changes)
|
||||
Navegador (superadmin/admin/it_manager) --JWT--> /api/devices -> menú "Equipos"
|
||||
```
|
||||
|
||||
- **Handshake:** el agente primero manda un `contact` (JSON) o `PROLOG` (XML). Se responde sin
|
||||
guardar nada (`{"status":"ok","expiration":"24"}` o `<REPLY><RESPONSE>SEND</RESPONSE>…`).
|
||||
- **Ingesta autenticada por token**, no por JWT: tabla `inventory_tokens` (solo hash sha256). El
|
||||
agente lo manda como contraseña Basic (`user`/`password` del `agent.cfg`), `Bearer`,
|
||||
`X-Ingest-Token` o `?token=`. Sin token válido → `401`.
|
||||
- **Rutas:** `POST /api/inventory` (propia; pasa por el Custom Location `/api` de NPM sin cambios)
|
||||
y alias `POST /front/inventory.php` (ruta nativa de GLPI). Se montan ANTES de `express.json`
|
||||
porque usan cuerpo crudo.
|
||||
- **Límites:** cuerpo máx. 15 MB (`INVENTORY_MAX_BYTES`), inflado máx. 4× (anti zip-bomb).
|
||||
- **Upsert por `deviceid`** (estable), nunca por hostname. Componentes se reemplazan completos en
|
||||
una transacción; el diff (RAM, disco agregado/retirado, software instalado/desinstalado, SO,
|
||||
hostname) queda en `device_changes`.
|
||||
- **Baja lógica:** `status = retired`; un reporte nuevo NO reactiva un equipo dado de baja.
|
||||
- **Crudo para depurar:** último reporte por equipo en `storage/inventories/<hash>.json|xml`
|
||||
(se sobrescribe; descarga `GET /api/devices/:id/raw`).
|
||||
|
||||
## Normalización
|
||||
|
||||
`backend/src/modules/devices/normalizer.js`: el JSON nativo y el XML (en mayúsculas) comparten
|
||||
nombres de campo, así que el XML se pasa a minúsculas y ambos usan el mismo mapeo. Todo campo
|
||||
ausente queda `null` (el formato varía por versión del agente y SO). Tipo de equipo
|
||||
(`desktop/laptop/server/virtual/printer/network/other`) se infiere de `chassis_type`, `vmsystem`,
|
||||
nombre del SO e `itemtype`. Lo que no tiene columna (impresoras/red SNMP, antivirus, video,
|
||||
batería) se guarda en `devices.extra_json`.
|
||||
|
||||
## Instalar el agente en un equipo
|
||||
|
||||
1. Superadmin/admin: menú **Equipos → Agentes → Generar token** (se muestra una sola vez).
|
||||
2. En el equipo, instalar GLPI Agent (MSI en Windows; `.deb`/`.rpm`/tarball en Linux) con:
|
||||
```
|
||||
server = https://project.linkedcorp.net/api/inventory
|
||||
user = project
|
||||
password = <token>
|
||||
tag = <opcional>
|
||||
```
|
||||
Windows (instalador): `SERVER=… USER=project PASSWORD=<token>`.
|
||||
3. Forzar un envío: `glpi-agent --force` (Linux) / "Forzar inventario" en la página del agente
|
||||
(`http://localhost:62354`) en Windows. El equipo aparece en **Equipos** al primer POST.
|
||||
|
||||
## Pendientes / por verificar con un agente real
|
||||
|
||||
- Confirmar que el agente acepta la respuesta del handshake tal cual (si no, ajustar `ingest.js`).
|
||||
- Capturar un JSON real (`glpi-agent --local=/tmp/inv --json`) y contrastar campos con
|
||||
`normalizer.js` (hoy basado en el formato documentado del agente).
|
||||
- Impresoras/red por SNMP (`netinventory`): solo se guarda lo básico + `extra_json`; falta una
|
||||
vista propia cuando haya un caso real.
|
||||
- Panel de impresoras con contador de páginas/tóner y export CSV: fase 2.
|
||||
Reference in New Issue
Block a user