#!/usr/bin/env bash set -euo pipefail BASE=${BASE:-http://localhost:8080} API=$BASE/api J=(-H 'content-type: application/json') [ -f .env ] && set -a && . ./.env && set +a say(){ echo "smoke: $1"; } die(){ echo "SMOKE FAIL: $1"; exit 1; } tokfor(){ curl -fsS "$API/auth/login" "${J[@]}" -d "{\"username\":\"$1\",\"password\":\"$2\"}" | sed -E 's/.*"token":"([^"]+)".*/\1/'; } say "healthz" curl -fsS "$API/healthz" >/dev/null || die "healthz down" say "login" TOK=$(tokfor "$ADMIN_USER" "$ADMIN_PASSWORD") [ -n "$TOK" ] || die "no token" AUTH="authorization: Bearer $TOK" say "member user + role enforcement" curl -fsS "$API/users" "${J[@]}" -H "$AUTH" -d '{"username":"smoke","password":"smokepw123","role":"member"}' >/dev/null || die "create member" MTOK=$(tokfor smoke smokepw123) code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "$API/users" "${J[@]}" -H "authorization: Bearer $MTOK" -d '{"username":"x","password":"xpw12345","role":"member"}') [ "$code" = 403 ] || die "member write not blocked ($code)" say "library + bad-ext upload rejected + good upload + scan" mkdir -p library/smoke-books LID=$(curl -fsS "$API/libraries" "${J[@]}" -H "$AUTH" -d '{"name":"smoke","root_path":"/data/books/smoke-books"}' | sed -E 's/.*"id":([0-9]+).*/\1/') printf 'x' > library_upload_note.txt curl -fsS -o /dev/null "$API/libraries/$LID/upload" -H "$AUTH" -F "file=@library_upload_note.txt;filename=virus.exe" && die "bad ext upload must fail" || true printf 'hello smoke book' > library_upload_note.txt curl -fsS -o /dev/null "$API/libraries/$LID/upload" -H "$AUTH" -F "file=@library_upload_note.txt;filename=note.txt" || die "upload failed" curl -fsS -o /dev/null -X POST "$API/libraries/$LID/scan" -H "$AUTH" || die "scan trigger" found="" for _ in $(seq 30); do if curl -fsS "$API/books?library=$LID" -H "$AUTH" | grep -q '"path":"note.txt"'; then found=1; break; fi sleep 1 done [ -n "$found" ] || die "book not indexed after 30s" say "read + progress roundtrip" BID=$(curl -fsS "$API/books?library=$LID" -H "$AUTH" | sed -E 's/.*"id":([0-9]+).*/\1/') curl -fsS "$API/books/$BID/file" -H "$AUTH" | grep -q "hello smoke book" || die "file body" code=$(curl -s -o /dev/null -w '%{http_code}' -X PUT "$API/books/$BID/progress" "${J[@]}" -H "authorization: Bearer $MTOK" -d '{"locator":{"scroll":0.5},"percent":0.5}') [ "$code" = 204 ] || die "progress put $code" curl -fsS "$API/progress" -H "authorization: Bearer $MTOK" | grep -q '"percent":0.5' || die "progress read" say "immutable cache header" COVER=$(curl -fsS "$API/books/$BID" -H "$AUTH" | sed -E 's/.*"cover_url":"([^"]+)".*/\1/') curl -fsS -o /dev/null -D - "$BASE$COVER" -H "$AUTH" | grep -qi 'cache-control:.*immutable' || die "cover not immutable" say "delete book → file gone from host dir" curl -fsS -o /dev/null -X DELETE "$API/books/$BID" -H "$AUTH" || die "delete" [ ! -f library/smoke-books/note.txt ] || die "file survived delete" say "ALL SMOKE TESTS PASSED"