feat(nextcloud-files): Dateien auflisten, Vorschau, Ordner anlegen, umbenennen, verschieben und löschen
- PROPFIND-Auswertung (mehrere propstat, Kleinbuchstaben-Hex, Speicher -3 = unbegrenzt, nur Zeichenketten) - WebDAV-Schicht mit Zugangsschluessel und Aufrufsperre, Destination immer aus der Basis, Overwrite: F - mapNcFailure als einzige Fehlerabbildung (nie 401/403 an den Browser), sendUpstreamStream prueft vor dem ersten Byte - Dateidienst und Routen files, folders, move, preview im eigenen Konto; zweiter Benutzer bekommt notConnected - Web-API-Funktionen listFolder, createFolder, moveEntry, deleteEntry, previewUrl - e2e-files.sh gegen die Test-Nextcloud Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+127
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env bash
|
||||
# Aufgabe 3: Datei-Schnittstelle gegen die Test-Nextcloud (Liste mit Speicher, Vorschau, Ordner,
|
||||
# Verschieben/Umbenennen, Papierkorb, zweiter Benutzer). Setzt einen laufenden Stack und
|
||||
# nc-test-setup.sh voraus. Nur Testwerte; liest keine .env-Dateien.
|
||||
set -euo pipefail
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/e2e-lib.sh"
|
||||
trap 'rm -rf "$E2E_TMP"' EXIT
|
||||
|
||||
FILES="$API/modules/nextcloud-files"
|
||||
NC_DAV="http://localhost:18080/remote.php/dav"
|
||||
ANNA="anna:User1-Pass-12345"
|
||||
# 1x1-PNG als Base64 (Vorschau)
|
||||
PNG_B64='iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=='
|
||||
UMLAUT_NAME='Ärger & Ölpreis 100%.txt'
|
||||
UMLAUT_ENC='%C3%84rger%20%26%20%C3%96lpreis%20100%25.txt'
|
||||
|
||||
ADMIN="$E2E_TMP/admin.jar"
|
||||
e2e_wait_health
|
||||
e2e_login "$ADMIN"
|
||||
e2e_activate "$ADMIN"
|
||||
e2e_set_address "$ADMIN"
|
||||
code=$(e2e_connect_anna "$ADMIN")
|
||||
e2e_expect 200 "$code" "anna verbinden"
|
||||
|
||||
# GET <jar> <endpoint> <pfad> — Pfad als Query-Parameter, sauber codiert; Status auf stdout.
|
||||
qget() { curl -s -o "$E2E_TMP/body.out" -w '%{http_code}' -b "$1" -G --data-urlencode "path=$3" "$FILES/$2"; }
|
||||
qdel() { curl -s -o "$E2E_TMP/body.out" -w '%{http_code}' -b "$1" -X DELETE -G --data-urlencode "path=$3" "$FILES/$2"; }
|
||||
post() { e2e_status "$1" POST "$FILES/$2" "$3"; }
|
||||
# JSON-Body: die Umlautdatei im Testordner ins Unterverzeichnis Ziel verschieben
|
||||
move_umlaut_json() {
|
||||
python3 -I -c 'import json,sys
|
||||
print(json.dumps({"from": sys.argv[1] + "/" + sys.argv[2], "to": sys.argv[1] + "/Ziel/" + sys.argv[2]}))' "$F" "$UMLAUT_NAME"
|
||||
}
|
||||
|
||||
F="/Tessera-E2E-$(date +%s)"
|
||||
FNAME="${F#/}"
|
||||
|
||||
# --- Vorbereitung direkt in der Nextcloud (mit annas Passwort) --------------------------------
|
||||
nc_put() { curl -s -o /dev/null -w '%{http_code}' -u "$ANNA" -X PUT --data-binary "$2" "$NC_DAV/files/anna$1"; }
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' -u "$ANNA" -X MKCOL "$NC_DAV/files/anna$F"); e2e_expect 201 "$code" "Fixture-Ordner"
|
||||
code=$(nc_put "$F/$UMLAUT_ENC" "hallo"); e2e_expect 201 "$code" "Fixture Umlautdatei"
|
||||
echo "$PNG_B64" | base64 -d > "$E2E_TMP/pixel.png"
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' -u "$ANNA" -X PUT -H 'Content-Type: image/png' \
|
||||
--data-binary "@$E2E_TMP/pixel.png" "$NC_DAV/files/anna$F/pixel.png"); e2e_expect 201 "$code" "Fixture PNG"
|
||||
|
||||
# --- Liste der Wurzel mit Speicherangabe ---------------------------------------------------------
|
||||
code=$(qget "$ADMIN" files "/"); e2e_expect 200 "$code" "Wurzel auflisten"
|
||||
e2e_contains "$E2E_TMP/body.out" '"entries"' "Wurzel: entries"
|
||||
e2e_contains "$E2E_TMP/body.out" '"quota"' "Wurzel: quota"
|
||||
e2e_contains "$E2E_TMP/body.out" "\"name\":\"$FNAME\"" "Wurzel enthaelt den Testordner"
|
||||
|
||||
# --- Liste des Testordners: Umlautname, PNG mit Vorschau -------------------------------------------
|
||||
code=$(qget "$ADMIN" files "$F"); e2e_expect 200 "$code" "Testordner auflisten"
|
||||
e2e_contains "$E2E_TMP/body.out" "\"name\":\"$UMLAUT_NAME\"" "Umlautname exakt"
|
||||
e2e_contains "$E2E_TMP/body.out" '"name":"pixel.png"' "PNG vorhanden"
|
||||
PNG_ID=$(python3 -I -c 'import json,sys
|
||||
for e in json.load(open(sys.argv[1]))["entries"]:
|
||||
if e["name"]=="pixel.png":
|
||||
assert e["hasPreview"] is True, "hasPreview"
|
||||
print(e["fileId"])' "$E2E_TMP/body.out")
|
||||
[ -n "$PNG_ID" ] || e2e_fail "PNG-Kennung fehlt"
|
||||
|
||||
# --- Vorschau ---------------------------------------------------------------------------------------
|
||||
code=$(curl -s -D "$E2E_TMP/prev.hdr" -o "$E2E_TMP/prev.png" -w '%{http_code}' -b "$ADMIN" "$FILES/preview?fileId=$PNG_ID&v=%22x%22")
|
||||
e2e_expect 200 "$code" "Vorschau"
|
||||
grep -qi '^content-type: image/png' "$E2E_TMP/prev.hdr" || e2e_fail "Vorschau: kein image/png"
|
||||
grep -qi '^cache-control: private, max-age=86400' "$E2E_TMP/prev.hdr" || e2e_fail "Vorschau: cache-control"
|
||||
grep -qi '^set-cookie' "$E2E_TMP/prev.hdr" && e2e_fail "Vorschau: set-cookie aus Nextcloud weitergereicht" || true
|
||||
code=$(curl -s -o "$E2E_TMP/body.out" -w '%{http_code}' -b "$ADMIN" "$FILES/preview?fileId=abc")
|
||||
e2e_expect 400 "$code" "Vorschau mit ungueltiger Kennung"
|
||||
code=$(curl -s -o "$E2E_TMP/body.out" -w '%{http_code}' -b "$ADMIN" "$FILES/preview?fileId=99999999")
|
||||
e2e_expect 404 "$code" "Vorschau ohne Datei"
|
||||
|
||||
# --- Neuer Ordner -----------------------------------------------------------------------------------
|
||||
code=$(post "$ADMIN" folders "{\"path\":\"$F/Ziel\"}")
|
||||
case "$code" in 200|201) ;; *) e2e_fail "Ordner anlegen -> $code" ;; esac
|
||||
code=$(post "$ADMIN" folders "{\"path\":\"$F/Ziel\"}")
|
||||
e2e_expect 409 "$code" "Ordner doppelt anlegen"
|
||||
e2e_contains "$E2E_TMP/body.out" '"code":"nameTaken"' "Ordner doppelt: nameTaken"
|
||||
|
||||
# --- Verschieben und Konflikt ------------------------------------------------------------------------
|
||||
code=$(post "$ADMIN" move "$(move_umlaut_json)")
|
||||
e2e_expect 200 "$code" "Umlautdatei verschieben"
|
||||
code=$(nc_put "$F/$UMLAUT_ENC" "zweite"); e2e_expect 201 "$code" "zweite Umlautdatei"
|
||||
code=$(post "$ADMIN" move "$(move_umlaut_json)")
|
||||
e2e_expect 409 "$code" "Verschieben auf vorhandenen Namen"
|
||||
e2e_contains "$E2E_TMP/body.out" '"code":"nameTaken"' "Verschieben: nameTaken"
|
||||
# die verschobene Datei im Ziel ist unveraendert (nicht ueberschrieben)
|
||||
body=$(curl -s -u "$ANNA" "$NC_DAV/files/anna$F/Ziel/$UMLAUT_ENC")
|
||||
[ "$body" = "hallo" ] || e2e_fail "Ziel wurde ueberschrieben: '$body'"
|
||||
|
||||
# --- Umbenennen ----------------------------------------------------------------------------------------
|
||||
code=$(post "$ADMIN" move "{\"from\":\"$F/Ziel\",\"to\":\"$F/Ziel2\"}")
|
||||
e2e_expect 200 "$code" "Ordner umbenennen"
|
||||
code=$(qget "$ADMIN" files "$F/Ziel2"); e2e_expect 200 "$code" "umbenannter Ordner"
|
||||
e2e_contains "$E2E_TMP/body.out" "\"name\":\"$UMLAUT_NAME\"" "Datei im umbenannten Ordner"
|
||||
code=$(post "$ADMIN" move "{\"from\":\"$F\",\"to\":\"$F/Ziel2/innen\"}")
|
||||
e2e_expect 400 "$code" "Ordner in sich selbst"
|
||||
e2e_contains "$E2E_TMP/body.out" '"code":"moveIntoItself"' "moveIntoItself"
|
||||
|
||||
# --- Ungueltiger Pfad ------------------------------------------------------------------------------------
|
||||
code=$(qget "$ADMIN" files "/../x"); e2e_expect 400 "$code" "Pfad mit .."
|
||||
e2e_contains "$E2E_TMP/body.out" '"code":"invalidPath"' "invalidPath"
|
||||
code=$(qget "$ADMIN" files "/gibt-es-nicht-$(date +%s)"); e2e_expect 404 "$code" "fehlender Ordner"
|
||||
e2e_contains "$E2E_TMP/body.out" '"code":"notFound"' "notFound"
|
||||
|
||||
# --- Zweiter Tessera-Benutzer: kein Zugriff auf annas Konto -------------------------------------------
|
||||
J2="$E2E_TMP/zweit.jar"
|
||||
e2e_second_user "nc-e2e-zweit" "$J2"
|
||||
e2e_grant_use "$ADMIN" "$J2"
|
||||
code=$(e2e_status "$J2" GET "$FILES/status"); e2e_expect 200 "$code" "Status zweiter Benutzer"
|
||||
e2e_contains "$E2E_TMP/body.out" '"account":null' "zweiter Benutzer: kein Konto"
|
||||
code=$(qget "$J2" files "/"); e2e_expect 409 "$code" "Dateien zweiter Benutzer"
|
||||
e2e_contains "$E2E_TMP/body.out" '"code":"notConnected"' "zweiter Benutzer: notConnected"
|
||||
code=$(qget "$J2" files "$F"); e2e_expect 409 "$code" "fremder Ordner, zweiter Benutzer"
|
||||
code=$(qdel "$J2" files "$F"); e2e_expect 409 "$code" "Loeschen, zweiter Benutzer"
|
||||
code=$(qget "$ADMIN" files "$F"); e2e_expect 200 "$code" "Admin sieht weiter seine Dateien"
|
||||
|
||||
# --- Loeschen in den Papierkorb ---------------------------------------------------------------------------
|
||||
code=$(qdel "$ADMIN" files "$F"); e2e_expect 200 "$code" "Testordner loeschen"
|
||||
code=$(qget "$ADMIN" files "$F"); e2e_expect 404 "$code" "Testordner ist weg"
|
||||
curl -s -u "$ANNA" -X PROPFIND -H 'Depth: 1' "$NC_DAV/trashbin/anna/trash" > "$E2E_TMP/trash.xml"
|
||||
grep -q "$FNAME" "$E2E_TMP/trash.xml" || e2e_fail "Papierkorb enthaelt $FNAME nicht"
|
||||
|
||||
# --- Aufraeumen ---------------------------------------------------------------------------------------------
|
||||
code=$(e2e_status "$ADMIN" DELETE "$FILES/connect"); e2e_expect 200 "$code" "Abmelden"
|
||||
echo "e2e files ok"
|
||||
Reference in New Issue
Block a user