Home mode: a signed-out page request carries return_to
The local plugin's RequireSession redirects a signed-out page request to /signin with no return_to, so after Home sign-in Memoria landed on the root instead of the page the person asked for. In Home mode, redirect GET/HEAD to /signin?return_to=<request URI>; connect's Signin keeps a safe path through the exchange and lands on it. TestHomeSigninReturnsToTheExactPage failed first (/connectors went to "/signin") and passes now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 files changed,
+37
−0
internal/memoria/app.go+12 −0internal/memoria/home_consumer_test.go+25 −0
CI passed — run details
CI log
=== vet === go vet ./... === fmt === === test === go test ./... ? amadan.net/oficina/memoria/cmd/memoria [no test files] ok amadan.net/oficina/memoria/internal/memoria 8.711s ok amadan.net/oficina/memoria/internal/memoria/chunk (cached) ok amadan.net/oficina/memoria/internal/memoria/fact (cached) ? amadan.net/oficina/memoria/internal/memoria/icons [no test files] ok amadan.net/oficina/memoria/internal/memoria/index (cached) ok amadan.net/oficina/memoria/internal/memoria/notion (cached) ok amadan.net/oficina/memoria/internal/memoria/provider (cached) ok amadan.net/oficina/memoria/internal/memoria/query (cached) ok amadan.net/oficina/memoria/internal/memoria/seal (cached) ok amadan.net/oficina/memoria/internal/memoria/sibling (cached) ok amadan.net/oficina/memoria/internal/memoriatest 5.044s ? amadan.net/oficina/memoria/scripts/writeestilo [no test files] ? amadan.net/oficina/memoria/tools/bench [no test files] ? amadan.net/oficina/memoria/tools/drive [no test files] ? amadan.net/oficina/memoria/tools/seed [no test files] ? amadan.net/oficina/memoria/tools/vendorassets [no test files] === migration-check === go run github.com/carlosframework/rastrillo/cmd/rastrillo migration check rastrillo migration check: models and migrations agree
diff --git a/internal/memoria/app.go b/internal/memoria/app.go| index b2e3501..ef42cef 100644 |
| --- a/internal/memoria/app.go |
| +++ b/internal/memoria/app.go |
| @@ -6,6 +6,7 @@ import ( |
| "context" |
| "log/slog" |
| "net/http" |
| + "net/url" |
| "strings" |
| "github.com/go-chi/chi/v5" |
| @@ -235,6 +236,17 @@ func (a *app) requireSession(next http.Handler) http.Handler { |
| } |
| next.ServeHTTP(w, r) |
| }) |
| + // In Home mode a signed-out page request carries the page to |
| + // sign-in, so Home sign-in comes back to it rather than to the |
| + // root: connect's Signin keeps a safe return_to through the |
| + // exchange. The local plugin's own refusal drops the path. Same |
| + // cookie, same table: WireHome checked the names agree. |
| + if a.home != nil && (r.Method == http.MethodGet || r.Method == http.MethodHead) { |
| + if _, ok := a.home.sessions.From(r); !ok { |
| + http.Redirect(w, r, signinPath+"?return_to="+url.QueryEscape(r.URL.RequestURI()), http.StatusSeeOther) |
| + return |
| + } |
| + } |
| a.auth.RequireSession(guarded).ServeHTTP(w, r) |
| }) |
| } |
diff --git a/internal/memoria/home_consumer_test.go b/internal/memoria/home_consumer_test.go| index 5b35997..5c41319 100644 |
| --- a/internal/memoria/home_consumer_test.go |
| +++ b/internal/memoria/home_consumer_test.go |
| @@ -90,3 +90,28 @@ func TestAllAppsLinksToDirectory(t *testing.T) { |
| t.Fatal("All apps shown with no directory configured") |
| } |
| } |
| + |
| +// A signed-out visit to a page in Home mode goes to sign-in carrying the |
| +// page, and Home sign-in comes back to that exact page, not the root. |
| +func TestHomeSigninReturnsToTheExactPage(t *testing.T) { |
| + f := newHomeConsumerFixture(t, "") |
| + f.local(t) |
| + if w := f.do("GET", "/account/home", ""); w.Code != http.StatusOK { |
| + t.Fatal("link page", w.Code) |
| + } |
| + start := homeRedirect(t, f.do("POST", "/account/home", "")) |
| + if homeRedirect(t, f.exchange(t, start, "opaque-home-alice")) != "/account/home/confirm" { |
| + t.Fatal("wrong proof landing") |
| + } |
| + homeRedirect(t, f.do("POST", "/account/home/confirm", "")) |
| + f.do("POST", "/signout", "") |
| + |
| + signin := homeRedirect(t, f.do("GET", "/connectors", "")) |
| + if signin != "/signin?return_to=%2Fconnectors" { |
| + t.Fatalf("signed-out /connectors went to %q, want /signin?return_to=%%2Fconnectors", signin) |
| + } |
| + start = homeRedirect(t, f.do("GET", signin, "")) |
| + if got := homeRedirect(t, f.exchange(t, start, "opaque-home-alice")); got != "/connectors" { |
| + t.Fatalf("Home sign-in landed on %q, want /connectors", got) |
| + } |
| +} |