# Server UI — File Explorer **Data:** 2026-07-05 **Status:** wdrożone Zakładka **Pliki** w panelu Server UI (`:8091`) — przeglądanie systemu plików, edycja tekstu, pełny CRUD. ## UI - Zakładka **Pliki** (druga, po CLI) - Hash URL: `http://:8091/#files` - Wymaga `X-API-Key` (ten sam co reszta panelu przy bind LAN) ## API Wszystkie endpointy: nagłówek `X-API-Key` (gdy `API_KEY` ustawiony i bind LAN). | Metoda | Ścieżka | Opis | |--------|---------|------| | GET | `/api/files?path=/` | Lista katalogu | | GET | `/api/files/read?path=...` | Odczyt pliku (UTF-8 lub base64 dla binarnych) | | PUT | `/api/files/write` | `{"path","content"}` — zapis tekstu | | POST | `/api/files/mkdir` | `{"path"}` — nowy folder | | POST | `/api/files/rename` | `{"old_path","new_path"}` | | DELETE | `/api/files?path=...` | Usuń plik lub pusty katalog | ### Przykłady curl ```bash API_KEY=$(sudo grep ^API_KEY= /opt/control-plane/.env | cut -d= -f2) curl -s "http://127.0.0.1:8091/api/files?path=/tmp" \ -H "X-API-Key: ${API_KEY}" curl -s "http://127.0.0.1:8091/api/files/read?path=/tmp/test.txt" \ -H "X-API-Key: ${API_KEY}" curl -s -X PUT "http://127.0.0.1:8091/api/files/write" \ -H "X-API-Key: ${API_KEY}" \ -H "Content-Type: application/json" \ -d '{"path":"/tmp/test.txt","content":"hello"}' ``` ## Konfiguracja W [`/opt/control-plane/.env`](/opt/control-plane/.env) (opcjonalnie): | Zmienna | Domyślnie | Opis | |---------|-----------|------| | `FILE_EXPLORER_ROOT` | `/` | Korzeń przeglądania | | `FILE_EXPLORER_MAX_BYTES` | `2097152` | Limit odczytu/zapisu (2 MiB) | ## Uprawnienia POSIX Server UI działa jako użytkownik **`tomasz-syn-grzegorza`** (`server-ui.service`). Explorer **nie omija** uprawnień systemowych: - `/home/...`, repo, `/data/apps/...` — zwykle OK - `/opt/control-plane/.env` (root 600) — odmowa w UI - pliki root-only — komunikat „Brak uprawnień” ## Kod | Plik | Rola | |------|------| | [`stacks/server-ui/file_explorer.py`](../stacks/server-ui/file_explorer.py) | Logika FS | | [`stacks/server-ui/app.py`](../stacks/server-ui/app.py) | Endpointy `/api/files*` | | [`stacks/server-ui/static/index.html`](../stacks/server-ui/static/index.html) | Zakładka Pliki | ## Bezpieczeństwo - Path traversal: `Path.resolve()` + sprawdzenie względem `FILE_EXPLORER_ROOT` - Pliki binarne: podgląd base64, zapis zablokowany (415) - Usuwanie: potwierdzenie w UI (`confirm()`) - Katalog niepusty: 409 przy DELETE ## Deploy ```bash sudo bash stacks/server-ui/scripts/install.sh # lub tylko restart po rsync: sudo systemctl restart server-ui ``` Tutorial użytkownika: [`manual-tutorial/09-file-explorer.md`](../manual-tutorial/09-file-explorer.md)