27 Commits

Author SHA1 Message Date
patrick 12248afa3a Refactor: Container-Erkennung zentralisiert, SMART-Check auf LXC überspringen
Neues Modul services/platform_info.py prüft systemd-detect-virt einmalig
beim Start (statt pro Request). SMART-Abfragen werden in Containern
übersprungen, da /dev/sdX dort meist nicht verfügbar ist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 20:37:14 +02:00
patrick 8dc4e8d698 Docs: backend/README.md neu geschrieben (PAM-Auth, aktuelle Endpunkte)
auth_service-Referenzen entfernt, Cookie-basierte Auth dokumentiert,
Endpunkt-Tabellen für alle Router ergänzt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:40:15 +02:00
patrick 56b1ab9970 Refactor: Tab-Switching von JavaScript auf HTMX + Jinja2 umgestellt
Shares- und Identities-Seite nutzen jetzt ?tab= Query-Parameter statt
clientseitigem JS. Der Server steuert aktiven Tab via Jinja2, kein
<script>-Block mehr nötig.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:21:29 +02:00
patrick 673c7d2f96 Refactor: Java-Klassen aus Services entfernt + .gitignore aus Repo
shares.py, zfs_runner.py: SharesManager/ZFSRunner → Modul-Funktionen
Backward-compat Shims erhalten (zfs_runner/share_manager bleiben nutzbar)
system_users.py, auth.py.bak: ungenutzte Dateien gelöscht
.gitignore: aus Repo entfernt (enthält interne Pfade/Infos)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:10:06 +02:00
patrick 5ecd143535 Feature: HTMX + Jinja2 Frontend ersetzt Next.js komplett
- Kein Node.js, kein npm, kein Build-Schritt mehr
- HTMX 2.0.4 + PicoCSS 2 vendored in backend/static/
- Jinja2 Templates für alle 9 Seiten (Dashboard, ZFS, Snapshots,
  Shares, Identities, Logs, Services, Navigator, Login)
- HTMX Fragments für Live-Updates (30s Polling Dashboard)
- JWT als httpOnly Cookie statt localStorage
- Disk Usage zeigt TB/PB korrekt (Jinja2 serverseitig formatiert)
- Update-safe: nur Python-Deps, keine npm-Abhängigkeiten

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 18:45:46 +02:00
patrick fd40c2e899 Fix: Samba MacOS toggle deaktivieren löscht fruit: Keys via delparm
net conf setparm kann Keys nicht entfernen. Beim Deaktivieren blieben
fruit:* Keys in der Registry erhalten. Jetzt werden Keys die im neuen
Dict fehlen via net conf delparm gelöscht.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 16:06:46 +02:00
patrick 3632991043 Fix: Samba config PUT 422 + shadow:format setparm dash escaping
Route /samba/{name} was matching before /samba/config, causing 422 on
PUT /samba/config. Moved static routes before parameterized routes.

Values starting with '-' (shadow: format = -%Y-%m-%d-%H%M) were parsed
as CLI flags by net conf setparm. Added '--' separator to escape them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 16:04:06 +02:00
patrick eef4ab09a7 Fix: Disk I/O im LXC-Container ausgeblendet
_is_container() prüft via systemd-detect-virt ob der Prozess in einem
Container läuft. Im LXC gibt get_disk_io() leere Liste zurück, da
/proc/diskstats die Host-Geräte zeigt und nicht dem Container gehören.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:48:19 +02:00
patrick c4454a675a Feature: Disk Usage via df im Dashboard (LXC-kompatibel)
- get_disk_usage() in system_info.py via /usr/bin/df -P
- GET /api/system/disk-usage Endpoint
- getDiskUsage() im API-Client
- Dashboard zeigt Disk Usage Karten mit Balken + Total/Used/Free
  (sichtbar auf LXC wo /proc/diskstats keine Blockgeräte liefert)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:34:18 +02:00
patrick 3bc57ef36b Fix: ZFS-Erkennung via tatsächlichem zpool-Test statt which()
shutil.which() reicht nicht: auf privilegierten LXC-Containern ist
zpool installiert, aber /dev/zfs fehlt → Befehl schlägt fehl.
_probe_zfs() führt zpool list einmal aus und wertet den Exit-Code aus.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:15:55 +02:00
patrick 2b6d508ca4 Fix: ZFS-Fehlerlogs auf LXC/non-ZFS-Systemen unterdrückt
- ZFS_AVAILABLE Flag beim Import gesetzt (shutil.which)
- FileNotFoundError in run_command: ERROR → DEBUG
- list_pools/get_pool_status/list_datasets/list_snapshots: frühzeitiger
  Return wenn kein zpool vorhanden → keine nutzlosen Subprocess-Aufrufe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 15:08:23 +02:00
patrick f49793e6f2 Refactor: Java-Klassen aus Services entfernt + kritische Bugs gefixt
- AuthService, SystemInfo, IdentitiesManager Klassen → Modul-Funktionen
- grp.getall() → grp.getgrall() (Bug: Methode existierte nie)
- open('/proc/loadavg') ohne context manager gefixt (File-Handle-Leak)
- rx_packets/tx_packets null-check im Frontend (toLocaleString auf undefined)
- PoolCard onClick: /pools/{name} → /zfs (Route existierte nicht, löste Seitenreload aus)
- Alle Router-Imports auf Modul-Aliase umgestellt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 14:11:32 +02:00
patrick ce78f0ae95 Feature: Disk-ID Namen + SMART-Daten on demand im VdevTree
- Backend: get_disk_id_map() liest /dev/disk/by-id/ dynamisch aus (ata/nvme/scsi/wwn)
- Backend: _annotate_disk_ids() hängt disk_id an Leaf-Vdevs in get_pool_status()
- Backend: get_smart_info() liest smartctl --json (Modell, Temp, Health, Stunden, Sektoren)
- Backend: GET /api/pools/disks/{disk}/smart Endpoint
- Frontend: DiskRow zeigt Modellname neben sda/sdb, aufklappbar für SMART-Details
- Frontend: Temp-Spalte farbcodiert (grün/gelb/rot), SMART-Spalte zeigt PASSED/FAILED

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 09:36:36 +02:00
patrick 202fdfaaeb Feature: VdevTree rekursiv + Disk-Aktionen (Offline/Online/Detach/Clear)
- VdevTree rendert jetzt alle Ebenen (pool → mirror → sda/sdb)
- Disk-⋮-Menü: Clear Disk Errors, Offline, Online, Detach
- Backend: neue Endpoints /disk/offline, /disk/online, /disk/detach

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 00:51:34 +02:00
patrick 6f6e8555af Feature: ZFS Pool-Aktionen (Scrub, Resilver, Clear Errors) + Product-Spalte fix
- Backend: neue Endpoints POST /api/pools/{name}/clear und /resilver
- Frontend: Pool ⋮-Menü mit Scrub, Resilver, Clear Errors
- Product-Spalte im Status-Tab bricht jetzt korrekt um statt abgeschnitten zu werden

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 00:45:35 +02:00
patrick e3b42caf01 Fix: list_snapshots mit -r statt -d1, Cache-Key pro Dataset
-d 1 begrenzte auf direkte Snapshots des Datasets, tank/share wurde
nicht eingeschlossen. -r (recursive) liefert alle Sub-Datasets.
Cache-Key jetzt dataset-spezifisch um Kollisionen zu vermeiden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:59:40 +02:00
patrick d079d76151 Feature: Snapshot-Tab in Datasets mit Kontextmenü (Clone/Rename/Rollback/Destroy)
- Snapshots direkt im Datasets-Tab ladbar (lazy, per Pool)
- Tabelle: Name, Created, Used, Referenced, Clones
- Kontextmenü (⋮) mit Clone, Rename, Roll Back, Destroy Snapshot
- Backend: /api/snapshots/clone + /api/snapshots/rename Endpoints

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:51:08 +02:00
patrick b85381759b Fix: zpool list Spalten-Indizes für Capacity/Fragmentation
CAP und FRAG wurden um eine Spalte verschoben gelesen (DEDUP statt CAP,
CAP statt FRAG). Korrekt: FRAG=parts[6], CAP=parts[7]. Prozentzeichen
ergänzt, da -p die Werte ohne % liefert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 17:04:36 +02:00
patrick 2fdff0407f Dokumentation: DEVLOG-Updates auf aktuellen Stand
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 14:58:50 +02:00
patrick d9c77e0b46 Konfigurierbares CORS per ZMB_CORS_ORIGINS + dynamische Frontend-URL
- main.py: CORS-Origins aus ZMB_CORS_ORIGINS (kommagetrennt), Default "*"
- allow_credentials automatisch aktiv bei konkreten Origins, aus bei "*"
- Root-Endpoint liefert Frontend-URL dynamisch via request.base_url
- keine hartkodierten IPs mehr im Anwendungscode
- Doku in CLAUDE.md und systemd-Unit ergaenzt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 14:58:50 +02:00
patrick a187b625bc Fix: Identities Group Management - bessere Fehlermeldungen
- add_user_to_group: Exception werfen mit stderr Nachricht
- remove_user_from_group: Exception werfen mit stderr Nachricht
- text=True für subprocess für besseres Error Handling
- Router aktualisiert um Fehlermeldungen an Frontend weiterzugeben
- Benutzer sehen jetzt detaillierte Fehlermeldungen beim Gruppe-Entfernen

Behebt: 'Failed to remove user from group' verschluckt die echte Fehlermeldung

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-04 14:58:50 +02:00
patrick 448026d91a Fix: Navigator Permissions - absolute Pfade für chmod/chown
- /bin/chmod statt chmod (line 435)
- /bin/chown statt chown (line 476)
- /bin/chmod -R statt chmod -R für recursive (line 514)

Behebt: 'Failed to save permissions' Fehler beim Ändern von Dateiberechtigungen

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-04 14:58:50 +02:00
patrick 55ae3b79ae Add editable Samba global configuration with net conf setparm
Backend:
- Use 'net conf setparm' to update individual parameters
- Accept dictionary of key-value pairs in API

Frontend:
- Add Edit/Cancel/Save buttons to Samba Config tab
- Inline editing of configuration values
- Save changes back to registry

Changes are applied immediately via net conf setparm.

Co-Authored-By: Patrick <patrick@perlbach24.de>
2026-04-22 01:31:14 +02:00
patrick dc242d5839 Fix: Use full path for 'net' command in Samba config reading
subprocess needs full path to executable when PATH is not set.
Use /usr/bin/net instead of 'net'.

Co-Authored-By: Patrick <patrick@perlbach24.de>
2026-04-22 01:22:05 +02:00
patrick be8b8cf68c Read Samba config from registry instead of smb.conf
Use 'net conf list' to read global config parameters from Samba registry.
This is more reliable than parsing smb.conf, especially when using
'include = registry' in smb.conf.

Co-Authored-By: Patrick <patrick@perlbach24.de>
2026-04-22 01:08:15 +02:00
patrick eec74626d0 Improve Samba Global Configuration display in WebUI
Backend:
- Parse global config into structured key-value pairs
- Return parameters array instead of raw text
- Better handling of comments and empty lines

Frontend:
- Add 'Samba Config' tab to shares page
- Display config parameters in readable table format
- Color-code parameter names for clarity
- Add getSambaConfig() method to API client

Co-Authored-By: Patrick <patrick@perlbach24.de>
2026-04-22 01:01:58 +02:00
Claude Code 6d74d874b6 ZMB Webui: Complete Project – Rebrand & Initial Clean Commit
ARCHITECTURE
============
Backend: FastAPI + uvicorn (port 8000)
  - JWT authentication with PAM system users
  - ZFS CLI wrapper with caching (30-60s TTL)
  - WebSocket pool status broadcaster (30s interval)
  - Services: auth, zfs_runner, file_manager, shares, identities, system_info
  - Routers: pools, datasets, snapshots, shares, identities, navigator, system

Frontend: Next.js 15 + TypeScript (static export)
  - Incremental Static Regeneration (ISR) for weak hardware
  - Type-safe API client (lib/api.ts)
  - Dark mode + custom Tailwind theme
  - Pages: Dashboard, Login, Snapshots, Datasets, Shares, etc.

DEPLOYMENT
==========
Test Target: 192.168.1.179:8090 (Debian LXC)
Production: 10.66.120.3:9090 (Raspberry Pi 4GB ARM64)
Updater: Automated Gitea-based deployment (update-test.sh, update-pi.sh)

FEATURES COMPLETED
==================
Phase 3a: Dashboard Quick Stats (System, CPU, Memory, Storage)
  - Real-time stats with color-coded progress bars
  - Responsive grid layout (mobile: 1, tablet: 2, desktop: 4 columns)
  - ISR-optimized for fast loads on weak hardware

REBRANDING
==========
Renamed throughout:
  - Project: 'ZFS Manager' → 'ZMB Webui'
  - Services: 'zfs-manager' → 'zmb-webui'
  - Systemd units: zfs-manager-backend → zmb-webui-backend
  - Configuration files and documentation

Co-Authored-By: Patrick <patrick@perlbach24.de>
2026-04-22 00:43:05 +02:00