Redesign U-Navigator as modern file browser
This commit is contained in:
@@ -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
@@ -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?>";
|
||||
|
||||
+769
-2492
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
|
||||
+174
-1096
File diff suppressed because it is too large
Load Diff
+5
-4
@@ -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
@@ -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;">
|
||||
|
||||
Reference in New Issue
Block a user