Caddy SORTS top-level directives, so a 'rewrite' runs before 'basicauth'. The rewrite changed /admin/ to /admin.html, and the path-based auth matchers then saw /admin.html (which matched the family 'not path /admin/*' block, not the operator '/admin/*' block) — so the operator password was checked against the family hash and 401'd. Serve each page from its own 'handle' block (which preserves order, so the auth is checked on the original path before any file rewrite): - handle /admin* : operator (frank) only, try_files /admin.html - handle @data : shared data + assets, family (dank) OR operator (frank), so the admin page's fetches of services.json/status.json reuse the operator credential - handle : everything else (the user page), family (dank)
48 lines
2.0 KiB
Bash
48 lines
2.0 KiB
Bash
#!/usr/bin/env bats
|
|
# Seam: the homepage site block in dankclaw/Caddyfile. It must carry a root
|
|
# basicauth hash and a distinct /admin/-scoped admin hash (Q18/Q19), and serve
|
|
# /srv/homepage. caddy is not on the dev box, so the tests assert the
|
|
# structure statically; the deploy renders the two real hashes from the .env.
|
|
|
|
load helpers
|
|
|
|
setup() {
|
|
CADDY="$REPO_ROOT/dankclaw/Caddyfile"
|
|
}
|
|
|
|
@test "the homepage has a root hash and a distinct admin hash (Q18/Q38)" {
|
|
grep -q "REPLACE_WITH_HASH" "$CADDY"
|
|
grep -q "REPLACE_WITH_ADMIN_HASH" "$CADDY"
|
|
}
|
|
|
|
@test "the admin basicauth is scoped to /admin/ (Q19)" {
|
|
# The admin page is a 'handle /admin*' block with the operator (frank)
|
|
# credential. Caddy sorts a top-level 'rewrite' before 'basicauth', which
|
|
# would change the path and break the path-based auth matcher; 'handle'
|
|
# preserves order, so the auth is checked on the original path.
|
|
grep -qE "handle[[:space:]]+/admin\*" "$CADDY"
|
|
grep -qE "frank[[:space:]]+REPLACE_WITH_ADMIN_HASH" "$CADDY"
|
|
}
|
|
|
|
@test "the homepage serves /srv/homepage" {
|
|
grep -q "root \* /srv/homepage" "$CADDY"
|
|
grep -q "file_server" "$CADDY"
|
|
}
|
|
|
|
@test "the /admin/ page serves admin.html and / serves index.html" {
|
|
# Each page is served by its own 'handle' block via 'try_files' (which
|
|
# serves the named file without a top-level 'rewrite' that Caddy would
|
|
# sort before the basicauth).
|
|
grep -qE "try_files[[:space:]]+/admin.html" "$CADDY"
|
|
grep -qE "try_files[[:space:]]+/index.html" "$CADDY"
|
|
}
|
|
|
|
@test "the shared data + assets accept both the family and the operator" {
|
|
# The admin page (frank) and the user page (dank) both fetch the shared
|
|
# data (services.json, status.json) and assets. The browser reuses the
|
|
# page's credential for these, so the block must accept both users.
|
|
grep -qE "@data[[:space:]]+path[[:space:]]+/services\.json[[:space:]]+/status\.json" "$CADDY"
|
|
grep -qE "handle[[:space:]]+@data" "$CADDY"
|
|
grep -qE "dank[[:space:]]+REPLACE_WITH_HASH" "$CADDY"
|
|
}
|