Redesign U-Navigator as modern file browser

This commit is contained in:
Mikei386
2026-07-14 16:07:35 +02:00
parent 07cddd64b2
commit 48e83c3f69
9 changed files with 1139 additions and 3597 deletions
+217
View File
@@ -0,0 +1,217 @@
# U-Navigator TODO
Stand: 2026-07-14
Ziel dieser Liste ist eine sichere, testbare und veröffentlichungsfähige Version des Plugins. Schreibzugriff sollte erst empfohlen werden, wenn alle Punkte unter P0 abgeschlossen und auf einer echten Unraid-Installation geprüft sind.
## P0 Sicherheitsblocker
### Geschützte Root-Pfade
- [ ] Eine zentrale Funktion `unav_assert_mutable_path()` einführen.
- [ ] Löschen eines konfigurierten Root-Pfads verbieten.
- [ ] Verschieben und Umbenennen eines konfigurierten Root-Pfads verbieten.
- [ ] Rekursive Rechte- oder Besitzeränderungen direkt am Root-Pfad verbieten.
- [ ] Quelle und Ziel auch im Worker unmittelbar vor der Operation erneut prüfen.
- [ ] API-Tests für Delete, Move und Permissions auf `/mnt/user` beziehungsweise einem Test-Root ergänzen.
Abnahmekriterium: Kein mutierender API-Aufruf kann den erlaubten Root selbst verändern oder entfernen.
### Sichere Symlink-Behandlung
- [ ] Eingabepfad und kanonischen Sicherheitspfad getrennt speichern.
- [ ] Für Dateioperationen `lstat()` statt ausschließlich `realpath()` verwenden.
- [ ] Beim Löschen eines Symlinks ausschließlich den Link entfernen, niemals dessen Ziel.
- [ ] Copy und Move von Symlinks entweder kontrolliert implementieren oder ausdrücklich ablehnen.
- [ ] Symlinks auf Ziele außerhalb erlaubter Roots für Listing, Vorschau und Download weiterhin blockieren.
- [ ] Rekursive Operationen dürfen Symlinks nicht verfolgen.
- [ ] Tests für interne Symlinks, externe Symlinks, kaputte Symlinks und Symlink-Schleifen ergänzen.
Abnahmekriterium: Eine Aktion auf einem Symlink wirkt niemals unerwartet auf dessen Ziel.
### Upload-Pfade härten
- [ ] Relative Pfade vollständig validieren; `..` nicht still entfernen, sondern als Fehler ablehnen.
- [ ] Absolute Pfade, Nullbytes und leere Pfadsegmente ablehnen.
- [ ] Jeden Parent-Pfad prüfen, bevor ein Verzeichnis angelegt wird.
- [ ] Beim Anlegen von Upload-Ordnern keine vorhandenen Symlinks durchlaufen.
- [ ] Zielpfad unmittelbar vor Schreiben beziehungsweise Rename erneut validieren.
- [ ] Temporäre Upload-Dateien in einem privaten Verzeichnis ablegen und zufällige IDs verwenden.
- [ ] Abgebrochene und veraltete Upload-Fragmente automatisch entfernen.
- [ ] Tests für Symlink-Parents und konkurrierende Pfadänderungen ergänzen.
Abnahmekriterium: Ein Upload kann außerhalb der erlaubten Roots weder Dateien noch Verzeichnisse erzeugen.
### CSRF und Request-Schutz
- [ ] Auf einer aktuellen Unraid-7.x-Installation prüfen, ob die WebGUI-Schicht Plugin-PHP-Endpunkte automatisch gegen CSRF schützt.
- [ ] Direkte POST-Requests ohne, mit falschem und mit gültigem `csrf_token` testen.
- [ ] Falls nötig, CSRF-Prüfung zentral in `common.php` implementieren.
- [ ] Mutierende Endpunkte ausschließlich per POST erlauben.
- [ ] Für nicht erlaubte Methoden `405 Method Not Allowed` und einen `Allow`-Header liefern.
- [ ] Für JSON- und Formular-Requests dieselben Schutzregeln anwenden.
- [ ] Authentifizierungsverhalten bei direktem Aufruf aller API-Endpunkte prüfen und dokumentieren.
Abnahmekriterium: Kein mutierender Aufruf funktioniert ohne gültige Unraid-Sitzung und gültigen CSRF-Schutz.
### Ressourcenlimits
- [ ] Maximale Upload-Dateigröße konfigurierbar machen.
- [ ] Maximale Gesamtgröße und Dateianzahl pro Upload begrenzen.
- [ ] Raw-Uploads streamen, statt den gesamten Request in den PHP-Speicher zu laden.
- [ ] Maximale Dateianzahl und Gesamtgröße für ZIP-Downloads festlegen.
- [ ] Vor ZIP-Erstellung freien temporären Speicher prüfen.
- [ ] ZIP-Erstellung als Hintergrundjob ausführen.
- [ ] Laufzeit- und Rekursionstiefenlimits für Size, Copy, Delete und Permissions einführen.
- [ ] Große Verzeichnisse im Listing paginieren oder begrenzen.
Abnahmekriterium: Einzelne Requests können weder PHP-Speicher noch temporären Speicher unkontrolliert erschöpfen.
## P1 Datenintegrität und Jobs
### Robuste Copy-/Move-Operationen
- [ ] Kopien zunächst unter einem temporären Zielnamen erstellen.
- [ ] Ziel erst nach erfolgreicher vollständiger Kopie atomar sichtbar machen.
- [ ] Unvollständige Ziele bei Fehlern zuverlässig entfernen.
- [ ] Quelle bei einem Cross-Filesystem-Move erst nach verifizierter Kopie löschen.
- [ ] Dateigröße und optional Prüfsumme vor dem Löschen der Quelle vergleichen.
- [ ] Rechte, Owner, Gruppe und Zeitstempel erhalten.
- [ ] Verhalten für Sparse Files, Hardlinks und Special Files definieren.
- [ ] Zielkonflikte auch unmittelbar vor dem finalen Rename prüfen.
- [ ] Tests für Fehler mitten in einer Verzeichniskopie ergänzen.
### Job-System
- [ ] Job-Verzeichnis mit `0700` statt `0777` erstellen.
- [ ] Jobdateien atomar über temporäre Datei plus Rename schreiben.
- [ ] Beim Lesen passende Locks beziehungsweise atomare Snapshots verwenden.
- [ ] Kryptografisch zufällige Job-IDs verwenden.
- [ ] Prüfen, ob der Worker wirklich gestartet ist; nicht nur den Shell-Exitcode auswerten.
- [ ] Hängende Jobs nach Timeout als fehlgeschlagen markieren.
- [ ] Abbruch-Endpunkt für laufende Jobs implementieren.
- [ ] Abbruchstatus in rekursiven Operationen regelmäßig prüfen.
- [ ] Abbruchschaltfläche im Transfer-Panel ergänzen.
- [ ] Alte abgeschlossene Jobs automatisch löschen.
- [ ] Gleichzeitige, kollidierende Jobs auf denselben Pfaden erkennen und serialisieren oder ablehnen.
- [ ] Jobfehler mit verständlicher Meldung und technischem Logeintrag trennen.
### Löschschutz
- [ ] Optionalen Papierkorb pro Root implementieren.
- [ ] Direktes permanentes Löschen als gesonderte Aktion behandeln.
- [ ] Anzahl und geschätzte Größe vor rekursivem Löschen anzeigen.
- [ ] Mehrfachauswahl vor dem Start vollständig validieren.
- [ ] Optional eine zweite Bestätigung für sehr große Löschvorgänge verlangen.
## P1 Tests
### PHP-Backend testen
- [ ] Eigenständige Tests für die tatsächlich ausgelieferten PHP-Endpunkte aufbauen.
- [ ] Die Tests in einer Unraid-kompatiblen PHP-Version ausführen.
- [ ] Listing innerhalb und außerhalb erlaubter Roots testen.
- [ ] Upload, Download, Preview, Copy, Move, Delete, Size und Permissions testen.
- [ ] Read-only-Modus für jede mutierende Aktion testen.
- [ ] Zielkonflikte und ungültige Request-Methoden testen.
- [ ] Sonderzeichen, Unicode, sehr lange Namen und versteckte Dateien testen.
- [ ] Mehrere konfigurierte Roots testen.
- [ ] Regressionstests für alle P0-Sicherheitsfälle ergänzen.
### CI und statische Prüfung
- [ ] `php -l` für alle PHP-Dateien in CI ausführen.
- [ ] JavaScript-Syntaxprüfung ausführen.
- [ ] ShellCheck für `build-plugin.sh` aktivieren.
- [ ] XML beziehungsweise PLG-Manifest validieren.
- [ ] Paket bauen und mit den Quellen vergleichen.
- [ ] Manifest-Prüfsumme automatisch verifizieren.
- [ ] Tests bei jedem Push und Pull Request ausführen.
### Test auf echter Unraid-Instanz
- [ ] Installation auf unterstützten Unraid-Versionen testen.
- [ ] Upgrade von einer vorherigen Plugin-Version testen.
- [ ] Deinstallation und Neuinstallation testen.
- [ ] Verhalten bei gestopptem und gestartetem Array prüfen.
- [ ] User Shares, Pools und Disk Shares getrennt prüfen.
- [ ] Große Ordner und große Dateien testen.
- [ ] WebGUI-Neustart und Server-Neustart während laufender Jobs testen.
- [ ] Alle offiziellen Themes und mobile Darstellung prüfen.
## P2 Konfiguration und Bedienung
### Root-Konfiguration
- [ ] Erlaubte Roots in `settings.json` speichern.
- [ ] Einstellungsoberfläche zum Hinzufügen und Entfernen von Roots bauen.
- [ ] Nur existierende absolute Verzeichnisse akzeptieren.
- [ ] Gefährliche Systempfade wie `/`, `/boot`, `/etc`, `/usr`, `/var` und `/root` standardmäßig verbieten.
- [ ] Pro Root einen Anzeigenamen und Read-only-Status erlauben.
- [ ] Änderungen an Roots erst nach erneuter serverseitiger Validierung übernehmen.
- [ ] Root-Auswahl im Explorer anbieten.
### Dateimanager-Funktionen
- [ ] Neuen Ordner anlegen.
- [ ] Leere Datei anlegen.
- [ ] Umbenennen mit serverseitiger Namensvalidierung verbessern.
- [ ] Suche nach Dateiname im aktuellen Ordner implementieren.
- [ ] Optionale rekursive Suche mit Ergebnislimit ergänzen.
- [ ] Sortierung nach Name, Typ, Größe und Änderungsdatum anbieten.
- [ ] Versteckte Dateien ein- und ausblendbar machen.
- [ ] Breadcrumb-Navigation ergänzen.
- [ ] Dateibaum beziehungsweise Share-Navigation ergänzen.
- [ ] Tastaturbedienung für Auswahl, Öffnen, Kopieren, Verschieben und Löschen verbessern.
### Transfer-Oberfläche
- [ ] Reale Fortschrittswerte nach Bytes statt nur nach Top-Level-Einträgen berechnen.
- [ ] Quelle, Ziel, Geschwindigkeit und Restzeit anzeigen.
- [ ] Fehlgeschlagene Jobs wiederholbar machen.
- [ ] Abgeschlossene Einträge einzeln oder gesammelt entfernen.
- [ ] Uploads pausieren und abbrechen können.
### Vorschau und Download
- [ ] MIME-Typ anhand des Dateiinhalts prüfen, nicht nur anhand der Erweiterung.
- [ ] SVG-Vorschau sicher behandeln oder deaktivieren.
- [ ] Medien- und PDF-Vorschau mit geeigneten Sandbox-Headern testen.
- [ ] HTTP-Range-Requests für große Audio- und Videodateien unterstützen.
- [ ] RFC-konforme UTF-8-Dateinamen im `Content-Disposition`-Header verwenden.
- [ ] Einzeldateien streamen, ohne unnötige Pufferung.
## P2 Protokollierung und Betrieb
- [ ] Audit-Log für Upload, Copy, Move, Delete und Permissions einführen.
- [ ] Zeitpunkt, Aktion, Quelle, Ziel, Ergebnis und Fehler protokollieren.
- [ ] Keine CSRF-Tokens oder sensiblen Inhalte ins Debug-Log schreiben.
- [ ] Logrotation und maximale Loggröße definieren.
- [ ] Diagnoseexport für Supportfälle anbieten.
- [ ] Gesundheitsstatus für Job-Worker und temporären Speicher anzeigen.
## P3 Paketierung und Veröffentlichung
- [ ] Version nur an einer Stelle pflegen und beim Build überall einsetzen.
- [ ] `package.json`-Version mit der Plugin-Version synchronisieren.
- [ ] Reproduzierbare TGZ-Pakete mit stabiler Sortierung und Zeitstempeln erzeugen.
- [ ] Nach Möglichkeit SHA-256 zusätzlich zur MD5-Prüfung veröffentlichen.
- [ ] Minimale und getestete Unraid-Version im Plugin-Manifest angeben.
- [ ] Changelog pro Version vollständig pflegen.
- [ ] Release-Build in einer sauberen Working Copy erzeugen.
- [ ] Community-Applications-Metadaten validieren.
- [ ] Installations-, Update- und Rollback-Anleitung ergänzen.
- [ ] Sicherheitsmodell und bekannte Einschränkungen dokumentieren.
- [ ] Read-only als empfohlenen Standard deutlich in README und Oberfläche anzeigen.
## Definition of Done für die erste produktive Version
- [ ] Alle P0-Punkte sind abgeschlossen.
- [ ] PHP-Integrationstests decken alle mutierenden Operationen ab.
- [ ] Keine Root- oder Symlink-Regression ist offen.
- [ ] CSRF und Authentifizierung sind auf echter Unraid-Hardware bestätigt.
- [ ] Große Uploads, Downloads und Verzeichnisse besitzen getestete Limits.
- [ ] Fehlgeschlagene Copy-/Move-Jobs hinterlassen keine unbemerkten Teildaten.
- [ ] Installation, Upgrade, Neustart und Deinstallation wurden getestet.
- [ ] Paketinhalt und Manifest-Prüfsumme stimmen überein.
- [ ] Dokumentation und Changelog entsprechen dem ausgelieferten Funktionsumfang.
+1 -1
View File
@@ -2,7 +2,7 @@
set -eu
PLUGIN="u-navigator"
VERSION="2026.07.04.r007"
VERSION="2026.07.14.r008"
PKG_DIR="packages"
WORK_DIR=".plugin-build"
PKG_NAME="${PLUGIN}-${VERSION}.tgz"
Binary file not shown.
@@ -11,26 +11,7 @@ $plugin = "u-navigator";
$version = "__VERSION__";
?>
<link rel="stylesheet" href="/plugins/<?=$plugin?>/assets/styles.css?v=<?=$version?>">
<div class="u-nav app-shell">
<header class="topbar">
<div>
<h1>U-Navigator</h1>
<p id="statusText">Initialisiere...</p>
</div>
<nav class="toolbar" aria-label="Workspace actions">
<button id="newExplorerButton" title="Explorer oeffnen">Explorer</button>
<button id="newPropertiesButton" title="Eigenschaften oeffnen">Eigenschaften</button>
<button id="newQueueButton" title="Transfers einblenden" aria-expanded="false">Transfers</button>
<button id="settingsButton" class="icon" title="Einstellungen" aria-label="Einstellungen" aria-expanded="false">
<svg class="ui-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z"></path>
<path d="M19.4 15a1.7 1.7 0 0 0 .34 1.88l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06A1.7 1.7 0 0 0 15 19.4a1.7 1.7 0 0 0-1 1.55V21a2 2 0 1 1-4 0v-.08A1.7 1.7 0 0 0 9 19.4a1.7 1.7 0 0 0-1.88.34l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.7 1.7 0 0 0 4.6 15a1.7 1.7 0 0 0-1.55-1H3a2 2 0 1 1 0-4h.08A1.7 1.7 0 0 0 4.6 9a1.7 1.7 0 0 0-.34-1.88l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.7 1.7 0 0 0 9 4.6a1.7 1.7 0 0 0 1-1.55V3a2 2 0 1 1 4 0v.08A1.7 1.7 0 0 0 15 4.6a1.7 1.7 0 0 0 1.88-.34l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.7 1.7 0 0 0 19.4 9a1.7 1.7 0 0 0 1.55 1H21a2 2 0 1 1 0 4h-.08A1.7 1.7 0 0 0 19.4 15Z"></path>
</svg>
</button>
</nav>
</header>
<main id="workspace" class="workspace" aria-label="U-Navigator Workspace"></main>
</div>
<div class="u-nav app-shell"></div>
<script>
window.UNAV_API_BASE = "/plugins/<?=$plugin?>/api";
window.UNAV_VERSION = "<?=$version?>";
+768 -2491
View File
File diff suppressed because it is too large Load Diff
+2 -15
View File
@@ -6,21 +6,8 @@
<title>U-Navigator</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<div class="app-shell">
<header class="topbar">
<div>
<h1>U-Navigator</h1>
<p id="statusText">Initialisiere...</p>
</div>
<nav class="toolbar" aria-label="Workspace actions">
<button id="newExplorerButton" title="Explorer öffnen">Explorer</button>
<button id="newPropertiesButton" title="Eigenschaften öffnen">Eigenschaften</button>
<button id="newQueueButton" title="Transfer-Queue öffnen">Transfers</button>
</nav>
</header>
<main id="workspace" class="workspace" aria-label="U-Navigator Workspace"></main>
</div>
<body style="margin:0">
<div class="u-nav app-shell"></div>
<script src="/app.js" type="module"></script>
</body>
</html>
+177 -1099
View File
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -1,7 +1,7 @@
<!DOCTYPE PLUGIN [
<!ENTITY name "u-navigator">
<!ENTITY author "Michael Roll">
<!ENTITY version "2026.07.04.r007">
<!ENTITY version "2026.07.14.r008">
<!ENTITY package "&name;-&version;.tgz">
<!ENTITY pluginURL "https://git.casaderoll.de/michael/Unraid-Navigator/raw/branch/main/u-navigator.plg">
<!ENTITY support "https://git.casaderoll.de/michael/Unraid-Navigator">
@@ -18,13 +18,14 @@
&description;
### &version;
- Native Dynamix-embedded U-Navigator page.
- Adds PHP API endpoints for listing, upload, move and copy without a separate web server.
- Replaces the floating window manager with a modern full-screen file browser.
- Adds responsive sidebar navigation, breadcrumbs, search, list and grid views, a detail preview and transfer drawer.
- Keeps native Dynamix integration and the existing PHP file APIs.
</CHANGES>
<FILE Name="/boot/config/plugins/&name;/&package;">
<URL>https://git.casaderoll.de/michael/Unraid-Navigator/raw/branch/main/packages/&package;</URL>
<MD5>6b8acde65433cdcd383f647a85dab3d9</MD5>
<MD5>568dd0b4ad993c41bd68d663c875805e</MD5>
</FILE>
<FILE Run="/bin/bash">
+3 -2
View File
@@ -18,8 +18,9 @@
&description;
### &version;
- Native Dynamix-embedded U-Navigator page.
- Adds PHP API endpoints for listing, upload, move and copy without a separate web server.
- Replaces the floating window manager with a modern full-screen file browser.
- Adds responsive sidebar navigation, breadcrumbs, search, list and grid views, a detail preview and transfer drawer.
- Keeps native Dynamix integration and the existing PHP file APIs.
</CHANGES>
<FILE Name="/boot/config/plugins/&name;/&package;">