Proving who somebody is and starting a session for them are separate operations. login_with_caldav does the first by asking the CalDAV server whether the credentials work; begin_session does the second and knows nothing about how the question was answered. OIDC arrives as a second way to reach begin_session, not as a second scheme threaded through everything -- which is what v1 had, with a JWT for most of the app and a separate SQLite session_token used only by the preferences API. The token lives in an HttpOnly cookie and nowhere else. v1 kept a JWT and the CalDAV password in localStorage, readable by any script on the origin, and re-sent the password in a header on every request. Here the password never leaves the server: it is encrypted with XChaCha20-Poly1305 and caldav_for is the only path back, handing out a client rather than a credential. Failed decryption is an error, not a subtly wrong password -- the AEAD tag is checked, so a tampered row surfaces here instead of as a mysterious CalDAV rejection later. A wrong password and an unreachable server stay distinct, because telling somebody their password is wrong when the server is down sends them to reset one that was fine. Errors carry a stable code alongside their message, so a client can branch on them. Internal ones say nothing about the inside of the server; the detail goes to the log. Tests go through router(), the same function main calls -- v1's suite rebuilt the route table and tested a copy until it stopped compiling. Skipping is now loud: a skipped test reports "ok", so run.sh sets RUNWAY_REQUIRE_CALDAV=1 and not running becomes a failure.
60 lines
2.0 KiB
Bash
Executable File
60 lines
2.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Run the CalDAV integration tests against a throwaway Baikal.
|
|
#
|
|
# Starts a container, walks it through the install wizard, runs the live test
|
|
# suite against it, and tears it down again. Nothing touches a real calendar.
|
|
#
|
|
# crates/runway-caldav/tests/baikal/run.sh # start, test, stop
|
|
# KEEP=1 crates/runway-caldav/tests/baikal/run.sh # leave it running
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
NAME="${NAME:-runway-baikal}"
|
|
PORT="${PORT:-8800}"
|
|
IMAGE="${IMAGE:-docker.io/ckulka/baikal:nginx}"
|
|
USERNAME="testuser"
|
|
PASSWORD="testpassword"
|
|
|
|
runtime() {
|
|
if command -v podman >/dev/null 2>&1; then echo podman
|
|
elif command -v docker >/dev/null 2>&1; then echo docker
|
|
else echo "need podman or docker" >&2; exit 1
|
|
fi
|
|
}
|
|
RUNTIME="$(runtime)"
|
|
|
|
cleanup() {
|
|
if [ "${KEEP:-0}" != "1" ]; then
|
|
"$RUNTIME" rm -f "$NAME" >/dev/null 2>&1 || true
|
|
else
|
|
echo "container $NAME left running on port $PORT"
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
"$RUNTIME" rm -f "$NAME" >/dev/null 2>&1 || true
|
|
"$RUNTIME" run -d --rm --name "$NAME" -p "$PORT:80" "$IMAGE" >/dev/null
|
|
echo "started $NAME ($IMAGE) on port $PORT"
|
|
|
|
# Baikal needs a moment before PHP answers.
|
|
for _ in $(seq 1 60); do
|
|
if [ "$(curl -sS -o /dev/null -w '%{http_code}' -L "http://localhost:$PORT/" 2>/dev/null)" = "200" ]; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
python3 "$HERE/setup.py" "http://localhost:$PORT" "$USERNAME" "$PASSWORD"
|
|
|
|
export RUNWAY_CALDAV_URL="http://localhost:$PORT/dav.php/"
|
|
export RUNWAY_CALDAV_USER="$USERNAME"
|
|
export RUNWAY_CALDAV_PASSWORD="$PASSWORD"
|
|
# Turns a silent skip into a failure: see the note in live.rs.
|
|
export RUNWAY_REQUIRE_CALDAV=1
|
|
|
|
# Both suites: the CalDAV client against the server, and the backend's own
|
|
# login flow against it. Skipped tests report as "ok", so the only way to know
|
|
# they ran is to run them here.
|
|
cargo test -p runway-caldav --test live -- --test-threads=1 "$@"
|
|
cargo test -p runway-server --test auth -- --test-threads=1 "$@"
|