"""Welche Pfade darf die API anfassen — und wo ist „oben"? ## Warum diese Grenze verschiebbar sein muss (Befund 28.08.2026) `MEDIA_ROOT = "/app/media"` war zugleich Vorgabe UND Pfadgrenze. Im Container ist beides richtig. Auf dem Windows-PC des Commanders war beides falsch, und die Folge war eine Oberflaeche, die stillschweigend nichts konnte: * `/storage-targets` lieferte `[]` (der Ordner existiert dort nicht), * `/browse` antwortete auf JEDEN Pfad mit 422, * im Auswahlfeld fuer das Arbeitsverzeichnis stand genau ein Eintrag. Sein Befund dazu: „Wäre es möglich das Arbeitsverzeichnis zu ändern? momentan geht das nicht." Die Grenze faellt aber NICHT einfach weg. Im Container haengt die API im Netz — eine Weboberflaeche, die jeden Pfad des Wirts ausliefern kann, ist ein Loch. Sie gilt nur dort nicht, wo Rippy den Menschen bedient, der vor dem Rechner sitzt. Diese Tests halten beide Haelften fest. """ import main # ── Die Grenze gilt, wo zugehoert wird ────────────────────────────────── def test_im_container_gilt_die_wurzel_weiter(): """Der Docker-Weg darf sich durch die Reparatur NICHT lockern.""" assert main.pfad_erlaubt("/app/media/movies", "/app/media", frei=False) assert not main.pfad_erlaubt("/etc/passwd", "/app/media", frei=False) # Der Klassiker: beginnt mit der Wurzel, liegt aber ausserhalb. assert not main.pfad_erlaubt("/app/media-boese/x", "/app/media", frei=False) def test_nativ_ist_auch_eine_freigabe_erlaubt(): """Sein Ziel ist `\\\\192.168.179.62\\rippy\\movies` — das liegt unter gar keiner lokalen Wurzel. Mit der alten Regel war es unerreichbar.""" assert main.pfad_erlaubt(r"\\192.168.179.62\rippy\movies", "/app/media", frei=True) assert main.pfad_erlaubt(r"D:\Rippy-Arbeit", "/app/media", frei=True) def test_ein_leerer_pfad_ist_nie_erlaubt(): """Sonst wuerde aus einem vergessenen Feld ein Zugriff auf `/`.""" assert not main.pfad_erlaubt("", "/app/media", frei=True) assert not main.pfad_erlaubt("", "/app/media", frei=False) # ── Wo ist oben ───────────────────────────────────────────────────────── def test_an_der_wurzel_ist_schluss(): """Im Container. `None` heisst: kein Knopf „nach oben".""" assert main.eltern_von("/app/media", "/app/media", frei=False) is None assert main.eltern_von("/app/media/movies", "/app/media", frei=False) == "/app/media" def test_ueber_der_laufwerkswurzel_steht_die_laufwerksliste(): """Zwei Fallen auf einmal. `os.path.dirname("C:\\\\")` ist wieder `"C:\\\\"` — ein Knopf „nach oben", der auf denselben Ordner zeigt, sieht aus wie ein Fehler. Und ueber der Laufwerkswurzel steht nicht *nichts*, sondern die Liste der Laufwerke: Sonst kaeme man von `D:\\` nie zu `C:\\`, und genau dort ist Platz fuer 100 GB Rohdaten. """ import ntpath import os echt = os.path.dirname os.path.dirname = ntpath.dirname # Windows-Pfade auch auf Linux try: assert main.eltern_von("C:\\", "D:\\Rippy", frei=True) == "" assert main.eltern_von("C:\\Users\\Tobi", "D:\\Rippy", frei=True) == "C:\\Users" finally: os.path.dirname = echt def test_die_wurzel_kommt_aus_dem_betrieb_und_ist_nie_leer(): """Eine leere Wurzel wuerde jede Pruefung durchwinken.""" assert main.medien_wurzel()