diff --git a/crates/httpd/src/auth_middleware.rs b/crates/httpd/src/auth_middleware.rs index f4d10f9c5..2539eff68 100644 --- a/crates/httpd/src/auth_middleware.rs +++ b/crates/httpd/src/auth_middleware.rs @@ -155,10 +155,16 @@ pub async fn auth_gate( next.run(request).await } else { // Remote connections to other pages when auth is not - // configured yet: redirect to a static "setup required" - // page instead of passing through, which would cause a - // redirect loop between `/` and `/onboarding` (#350). - Redirect::to("/setup-required").into_response() + // configured yet: send them to /onboarding so they can + // complete first-time setup via the setup-code flow + // (#350, #646). The original redirect loop between `/` + // and `/onboarding` was fixed separately at the SPA + // template layer via `should_redirect_from_onboarding`, + // which keeps remote visitors on /onboarding while auth + // setup is pending. The setup code (printed to stdout) + // still prevents an unauthorized remote visitor from + // claiming the instance. + Redirect::to("/onboarding").into_response() } }, AuthResult::Unauthorized => { diff --git a/crates/httpd/tests/auth_middleware.rs b/crates/httpd/tests/auth_middleware.rs index f55f3f6c8..74eb3599f 100644 --- a/crates/httpd/tests/auth_middleware.rs +++ b/crates/httpd/tests/auth_middleware.rs @@ -1360,10 +1360,11 @@ async fn onboarding_passes_through_for_remote_during_setup() { } /// During setup (no password), a remote connection to / is redirected to -/// /setup-required (same as /onboarding). +/// /onboarding so the user can enter the setup code and complete first- +/// time setup via the wizard's AuthStep (#646). #[cfg(feature = "web-ui")] #[tokio::test] -async fn root_redirects_to_setup_required_for_remote() { +async fn root_redirects_to_onboarding_for_remote() { let (addr, _store, _state) = start_proxied_server().await; let client = reqwest::Client::builder() @@ -1383,13 +1384,15 @@ async fn root_redirects_to_setup_required_for_remote() { .and_then(|v| v.to_str().ok()) .unwrap_or(""); assert_eq!( - location, "/setup-required", - "remote / during setup must redirect to /setup-required" + location, "/onboarding", + "remote / during setup must redirect to /onboarding" ); } -/// /setup-required is a public path and serves content even for remote -/// connections during setup (no redirect loop). +/// /setup-required is still served as a public stale-bookmark fallback +/// even for remote connections during setup. It is no longer the default +/// redirect target, but direct navigation must still work and must not +/// redirect-loop. #[cfg(feature = "web-ui")] #[tokio::test] async fn setup_required_page_accessible_for_remote() { @@ -1414,8 +1417,12 @@ async fn setup_required_page_accessible_for_remote() { ); let body = resp.text().await.unwrap(); assert!( - body.contains("Authentication Not Configured"), - "/setup-required should contain the setup heading" + body.contains("First-time setup"), + "/setup-required should contain the new setup heading" + ); + assert!( + body.contains("href=\"/onboarding\""), + "/setup-required should link to /onboarding" ); } diff --git a/crates/web/src/templates.rs b/crates/web/src/templates.rs index 3cf10df1f..5a5fd15b5 100644 --- a/crates/web/src/templates.rs +++ b/crates/web/src/templates.rs @@ -844,12 +844,16 @@ mod tests { "should produce a full HTML document" ); assert!( - html.contains("Authentication Not Configured"), - "should contain the setup-required heading" + html.contains("First-time setup"), + "should contain the new setup heading" ); assert!( - html.contains("moltis auth reset-password"), - "should contain the CLI reset command" + html.contains("setup code"), + "should mention the one-time setup code" + ); + assert!( + html.contains("href=\"/onboarding\""), + "should link to the onboarding wizard" ); assert!( html.contains("/assets/v/test123/"), diff --git a/crates/web/src/templates/setup-required.html b/crates/web/src/templates/setup-required.html index 3c50df25c..b7358bd6c 100644 --- a/crates/web/src/templates/setup-required.html +++ b/crates/web/src/templates/setup-required.html @@ -12,18 +12,22 @@
This instance requires authentication to be set up before it can be accessed remotely.
-Connect from the local machine or use the CLI:
-moltis auth reset-password
This instance has not been configured yet. To finish setup remotely, use the one-time setup code printed to the server's standard output when the process started.
+For a docker-compose deployment, find the code with:
+docker compose logs moltis
Locked out of an existing instance with filesystem access? The moltis auth reset-password CLI command can recover it — do not use it on a fresh install.