add auth + remote nrepl
CI / Test + coverage (push) Successful in 39s

This commit is contained in:
2026-09-19 07:21:19 -09:00
parent 3b0b608d7d
commit d9499594bf
21 changed files with 932 additions and 14 deletions
+7
View File
@@ -61,6 +61,13 @@ bb integration-test/integration_test.bb http://localhost:3000 --watch --interval
| 8 | `GET /api-docs` | 200, `text/html` |
| 9 | `GET /api/add?x=2&y=3` | 200, EDN `{:result 5}` |
| 10 | `GET /api/add` with bad params | 400 for a missing or non-numeric param |
| 11 | `GET /auth/login` | 302 to Gitea's authorize URL with the client id and a state; `HttpOnly` cookie |
| 12 | `GET /auth/callback` with no login in progress | 400 |
| 13 | `GET /auth/me` without a session | 401 |
| 14 | `POST /nrepl` without a session | 401, even with an invalid body |
The app container gets dummy Gitea settings from `docker-compose.yml`, so tests 11-14 cover the
unauthenticated surface only; completing a login needs a real Gitea (the unit tests stub one).
Test 4 needs the compiled UI, which the Docker image includes (`script/integration-test`
builds it). Against a locally running server, run `script/ui-build` first.
+7
View File
@@ -10,6 +10,13 @@ services:
- apparmor:unconfined
environment:
- PORT=${TBD_PORT:-3000}
# Dummy OAuth settings so /auth/login can be exercised; there's no Gitea to complete a login.
- BASE_URL=http://tbd-app:${TBD_PORT:-3000}
- GITEA_URL=http://gitea.invalid
- GITEA_CLIENT_ID=integration-client
- GITEA_CLIENT_SECRET=integration-secret
- ADMIN_USERS=integration-admin
- SESSION_SECRET=integration-session-secret
# No container healthcheck: healthchecks run via `docker exec`, which hits the
# same LXC/AppArmor runc bug (opencontainers/runc#5007) as image builds and
# always fails here. integration_test.bb polls the server until it's ready.
+35
View File
@@ -18,6 +18,17 @@
(defn head* [base-url]
(http/head base-url {:throw false}))
;; The login redirect points at Gitea; we want to see it, not follow it.
(def no-redirect-client (http/client {:follow-redirects :never}))
(defn get-no-redirect* [url]
(http/get url {:throw false :client no-redirect-client}))
(defn post-json* [url body]
(http/post url {:throw false
:headers {"Content-Type" "application/json"}
:body body}))
(defn wait-for-server [{:keys [base-url max-retries retry-delay-ms]}]
(println (str "=== Waiting for server at " base-url " ==="))
(loop [i 1]
@@ -122,6 +133,30 @@
(assert-eq "Non-numeric x" 400 (:status (get* (str base-url "/api/add?x=abc&y=3"))))
(println)
(println "Test 11: GET /auth/login redirects to Gitea's authorize page")
(let [resp (get-no-redirect* (str base-url "/auth/login"))
location (get (:headers resp) "location" "")]
(assert-eq "HTTP status" 302 (:status resp))
(assert-contains "Location" "/login/oauth/authorize?" location)
(assert-contains "Location has the client id" "client_id=integration-client" location)
(assert-contains "Location has a state" "state=" location)
(assert-contains "Session cookie is HttpOnly" "HttpOnly" (str (get (:headers resp) "set-cookie" ""))))
(println)
(println "Test 12: GET /auth/callback with no login in progress returns 400")
(assert-eq "HTTP status" 400 (:status (get-no-redirect* (str base-url "/auth/callback?code=x&state=y"))))
(println)
(println "Test 13: GET /auth/me without a session returns 401")
(assert-eq "HTTP status" 401 (:status (get* (str base-url "/auth/me"))))
(println)
(println "Test 14: POST /nrepl without a session returns 401 and starts nothing")
(assert-eq "Valid body" 401 (:status (post-json* (str base-url "/nrepl") "{\"enabled\":true}")))
(assert-eq "Invalid body (auth is checked first)" 401 (:status (post-json* (str base-url "/nrepl") "nope")))
(assert-eq "A query-string admin flag is no bypass" 401 (:status (post-json* (str base-url "/nrepl?admin=true") "{\"enabled\":true}")))
(println)
(println "================================")
(println (format " Results: %d passed, %d failed" @pass @fail))
(println "================================")