Doku + Version 1.1.1: die Whitelist-Falle steht jetzt im README [deploy]
All checks were successful
Deploy netdiag / deploy (push) Successful in 13s

Version auf 1.1.1 gezogen — auf Prod lief sonst eine 1.1.0, die nicht der
1.1.0 im Repo entspricht (die vier Bugfixes gingen ohne Versionssprung raus).

ChangeLog 1.1.1 mit allen vier Fehlern, der Rechtelücke im GET-Zweig und den
neuen Monitor-Feldern.

README:
- Neuer Abschnitt "Neue Messart aus der App aufnehmen" mit den DREI Stellen in
  netdiag.lib.php und der Spalte "wenn vergessen". Das ist die Falle, in die
  hier schon zweimal getappt wurde - einmal mit erfundenen Testdaten, einmal
  mit 'typ' statt 'type'. Feldnamen immer aus dem erzeugenden App-Code ablesen.
- Anmeldung laeuft ueber awlauth (stand noch "JWT-Auth")
- Rechteprüfung je Endpunkt dokumentiert, inkl. der Begruendung, warum der
  GET-Zweig auch 'write' akzeptiert
- Hinweis, dass '?jwt=' nur fuer den PDF-Download existiert und in Logs landet
This commit is contained in:
Eduard Wisch 2026-08-16 19:56:10 +02:00
parent 28a7fa9f79
commit 9f07896b05
3 changed files with 92 additions and 2 deletions

View file

@ -1,5 +1,61 @@
# Changelog NetDiag # Changelog NetDiag
## 1.1.1 — 2026-08-16
### Vier stille Fehler im Kundendokument und im Sync
Alle vier waren bereits ausgeliefert und fielen nicht auf, weil das PDF ja
weiterhin erzeugt wurde — nur ohne die betroffene Zeile. Gefunden durch einen
systematischen Abgleich der Whitelist gegen den erzeugenden App-Code.
- **`'typ'` war ein toter Schlüssel.** Kein Werkzeug erzeugt ihn; die App reicht
ein `LinkInfo`-Objekt durch, dort heißt das Feld `'type'`. Folge: im
Abnahmebeleg für eine Netzwerkdose fehlte die Angabe, **ob per LAN oder WLAN
gemessen wurde**. Zusätzlich `'rssi'` aufgenommen — bei einer WLAN-Dose ist
der Empfangspegel der eigentliche Messwert und wurde bisher verworfen.
Die Rohwerte sind englisch; `netdiagKundentext()` bildet sie jetzt ab
(`ethernet` → „LAN (Kabel)"), sonst stünde „Anschlussart: ethernet" im
Abnahmeprotokoll eines deutschen Handwerksbetriebs.
- **Leeres Array druckte „Offene Ports: " ohne Wert.** Die Leerprüfung ist ein
`elseif` hinter dem Array-Zweig und wurde nie erreicht. Betraf ausgerechnet
die *guten* Ergebnisse: Portscan ohne offenen Port, IP-Konflikt ohne Konflikt,
IP-Scan ohne Veränderung. Jetzt „keine" — Weglassen wäre schlechter, weil der
Kunde sonst nicht unterscheiden kann, ob nichts gefunden oder nichts geprüft
wurde.
- **`'error'` fehlte in der Whitelist.** Der IP-Konflikt gibt im Abbruchfall
`{ error: … }` mit roter Ampel zurück — im Kundendokument stand eine rote
Ampel ohne einen Buchstaben Erklärung. Die App vereinheitlicht künftig auf
`'fehler'`, aber Altdaten lassen sich nicht ändern.
- **`tool`/`category`/`label` wurden beim Sync nicht auf die Spaltenlänge
gekürzt** (varchar 64/32/255). Bei striktem SQL-Modus kippt **ein** zu langes
Label den gesamten Sync per `rollback()` — der Techniker steht beim Kunden mit
einem Protokoll da, das sich nicht abschließen lässt, weil eine Beschriftung
zu lang war. Die App setzt Labels durch Verketten zusammen, 255 Zeichen sind
erreichbar. `found_via` wurde 20 Zeilen darüber längst gekappt.
### Rechteprüfung im GET-Zweig der Protokoll-API
Bisher prüfte der GET-Zweig **gar nichts**: jeder angemeldete Benutzer konnte
mit einer geratenen ID ein fremdes Protokoll samt Geräteliste, IP-Adressen und
offenen Ports abrufen (der POST-Zweig verlangte seit jeher `write`). Das ist
beim Kunden erhobene Netzstruktur und gehört hinter ein Recht.
`write` wird bewusst mit akzeptiert: die Rechte sind in Dolibarr einzeln
vergebbar, und ein Techniker mit Schreib- ohne ausdrückliches Leserecht dürfte
nicht ausgesperrt werden — das wäre erst beim Kunden aufgefallen.
### Geräte-Monitor erscheint jetzt im Kundendokument
Die App liefert ab dieser Version eine Auswertung der Dauerüberwachung als
richtige Messung (Verfügbarkeit, Ausfallzeit, Aussetzer je Gerät). Die sechs
neuen Schlüssel sind in der Whitelist ergänzt — ohne sie stünde im PDF nur die
Ampel.
### Kleinigkeit
`netdiagDauerLesbar()`: „1 Tage 0 Std" → „1 Tag". `floor()` liefert in PHP einen
Float, und `1.0 === 1` ist false — die Einzahl hatte deshalb nie gegriffen.
## 1.1.0 — 2026-08-14 ## 1.1.0 — 2026-08-14
### Anmeldung läuft über das zentrale Auth-Modul (awlauth) ### Anmeldung läuft über das zentrale Auth-Modul (awlauth)

View file

@ -8,8 +8,13 @@ Messungen und hängt die Protokolle dauerhaft an **Kunde** und **Auftrag**.
- Datenmodell: Protokoll → Geräte → Messungen (`llx_netdiag_*`) - Datenmodell: Protokoll → Geräte → Messungen (`llx_netdiag_*`)
- Tab **Netzwerk-Diagnose** an Kunde (thirdparty) und Auftrag (commande) - Tab **Netzwerk-Diagnose** an Kunde (thirdparty) und Auftrag (commande)
- JSON-API unter `/custom/netdiag/api/` für die mobile App (JWT-Auth) - JSON-API unter `/custom/netdiag/api/` für die mobile App. Anmeldung seit
v1.1.0 über das zentrale Auth-Modul **awlauth** (Brute-Force-Bremse,
gemeinsame Sitzungsliste, „Gerät abmelden"); der alte modul-eigene JWT-Pfad
bleibt als Rückfall, bis alle Geräte die neue APK haben
- PDF-Protokoll, wird im Dokumentenarchiv (ECM) abgelegt - PDF-Protokoll, wird im Dokumentenarchiv (ECM) abgelegt
- **Zwei Sichten auf dieselben Messdaten:** die Technikeransicht zeigt alles,
das Kunden-PDF nur eine Whitelist (siehe „Neue Messart" unten)
- Rechtesystem: `netdiag → protocol → read/write/delete` - Rechtesystem: `netdiag → protocol → read/write/delete`
- Mehrsprachig (de_DE, en_US) - Mehrsprachig (de_DE, en_US)
- QR-Code zum App-Download in der Modul-Einrichtung - QR-Code zum App-Download in der Modul-Einrichtung
@ -40,6 +45,35 @@ Alle unter `https://<dolibarr>/custom/netdiag/api/`:
| `pdf.php` | GET `?id=&jwt=` | Protokoll-PDF streamen | | `pdf.php` | GET `?id=&jwt=` | Protokoll-PDF streamen |
Authentifizierung per `Authorization: Bearer <token>` oder `?jwt=<token>`. Authentifizierung per `Authorization: Bearer <token>` oder `?jwt=<token>`.
Jeder Endpunkt prüft ein Recht — `protocols.php` im GET-Zweig `protocol read`
**oder** `write`: die Rechte sind in Dolibarr einzeln vergebbar, und ein
Techniker mit Schreib- ohne ausdrückliches Leserecht darf nicht ausgesperrt
werden (das fiele erst beim Kunden auf).
> `?jwt=` in der URL ist nur für den PDF-Download da (der Browser kann dort
> keinen Header setzen). Langzeit-Token in URLs landen in Zugriffs- und
> Proxy-Logs — Ablösung steht in `ROADMAP_UMSETZUNG.md`, Phase L5.
## Neue Messart aus der App aufnehmen
Die App schickt Messergebnisse als freies JSON. Damit ein Feld beim Kunden
ankommt, sind **drei** Stellen in `lib/netdiag.lib.php` zu pflegen:
| Funktion | Zweck | Wenn vergessen |
|----------|-------|----------------|
| `netdiagKundenfelder()` | Whitelist + Beschriftung + Einheit | Feld verschwindet im Kunden-PDF spurlos, übrig bleibt die Ampel |
| `netdiagToolName()` | Klarname des Werkzeugs | beim Kunden steht „[netzwerk] meintool" |
| `netdiagKundentext()` | Rohwerte übersetzen/entschärfen | englische API-Werte im deutschen Abnahmedokument |
Spiegelbildlich dazu `app/src/lib/messfelder.ts` in der App.
**Feldnamen immer aus dem erzeugenden Code der App ablesen** (`types.ts`, die
`run()`-Rümpfe der Werkzeuge), nie aus dem Kopf und nie aus selbst
geschriebenen Testdaten — das ist hier schon zweimal schiefgegangen (KB #1084).
Braucht die Messart eine eigene Tabellendarstellung im PDF, einen Zweig in
`lib/netdiag_pdf.lib.php` ergänzen (Vorbilder: `netdiagPdfStressTest`,
`netdiagPdfWifiKanal`) — sonst wird das Ergebnis zu einer `|`-getrennten Zeile
zusammengeschoben.
## Einrichtung ## Einrichtung

View file

@ -67,7 +67,7 @@ class modNetDiag extends DolibarrModules
$this->editor_url = ''; $this->editor_url = '';
$this->editor_squarred_logo = ''; $this->editor_squarred_logo = '';
$this->version = '1.1.0'; $this->version = '1.1.1';
// Konstanten-Name in llx_const für Modul-Status // Konstanten-Name in llx_const für Modul-Status
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);