Wrap /user/{username} in RequireAuth middleware (closes #60) #71

Merged
sneak merged 2 commits from issue-60-user-requireauth into main 2026-08-07 14:00:17 +02:00
Collaborator

Enforces authentication for the /user/{username} route group at the middleware layer, matching every other authenticated route group.

Changes

  • internal/server/routes.go (setupUserRoutes): added r.Use(s.mw.RequireAuth()) immediately after the existing r.Use(s.mw.CSRF()) on the /user/{username} group, so auth is enforced by design (CSRF first, then RequireAuth) — consistent with /sources and /source/{sourceID}.
  • internal/handlers/profile.go (HandleProfile): removed the now-dead unauthenticated-redirect branch (RequireAuth guarantees an authenticated session before the handler runs). The handler still reads the username and user id from the session for the own-profile-only check; a request for another user's profile still returns 403. The session-retrieval error is now handled as a 500.

Tests (internal/handlers/profile_test.go)

  • own profile returns 200
  • another user's profile returns 403
  • an unauthenticated request to /user/{username} is redirected to /pages/login at the middleware layer and never reaches the endpoint handler (routing-level test replicating the CSRF + RequireAuth chain)

Validation

docker build . (fmt-check, lint, test, build) passes.

Closes #60

Enforces authentication for the `/user/{username}` route group at the middleware layer, matching every other authenticated route group. ## Changes - **`internal/server/routes.go`** (`setupUserRoutes`): added `r.Use(s.mw.RequireAuth())` immediately after the existing `r.Use(s.mw.CSRF())` on the `/user/{username}` group, so auth is enforced by design (CSRF first, then RequireAuth) — consistent with `/sources` and `/source/{sourceID}`. - **`internal/handlers/profile.go`** (`HandleProfile`): removed the now-dead unauthenticated-redirect branch (RequireAuth guarantees an authenticated session before the handler runs). The handler still reads the username and user id from the session for the own-profile-only check; a request for another user's profile still returns 403. The session-retrieval error is now handled as a 500. ## Tests (`internal/handlers/profile_test.go`) - own profile returns 200 - another user's profile returns 403 - an unauthenticated request to `/user/{username}` is redirected to `/pages/login` at the middleware layer and never reaches the endpoint handler (routing-level test replicating the CSRF + RequireAuth chain) ## Validation `docker build .` (fmt-check, lint, test, build) passes. Closes #60
clawbot added 1 commit 2026-08-07 13:48:38 +02:00
Wrap /user/{username} in RequireAuth middleware (closes #60)
All checks were successful
check / check (push) Successful in 5s
326629494e
Author
Collaborator

What changed

internal/server/routes.go — in setupUserRoutes(), added r.Use(s.mw.RequireAuth()) immediately after the existing r.Use(s.mw.CSRF()) on the /user/{username} route group. Relative order is CSRF first, then RequireAuth, matching /sources and /source/{sourceID}.

internal/handlers/profile.go — in HandleProfile, removed the now-unreachable "not authenticated -> redirect to /pages/login" branch (RequireAuth guarantees an authenticated session before the handler runs). The handler still reads the username and user id from the session for the own-profile-only comparison and template data; a request for another user's profile still returns 403. A session-retrieval error is now surfaced as a 500 rather than a redirect.

internal/handlers/profile_test.go (new) — three tests:

  • TestHandleProfile_OwnProfile_OK: own profile returns 200
  • TestHandleProfile_OtherProfile_Forbidden: another user's profile returns 403
  • TestUserRoute_Unauthenticated_RedirectedByMiddleware: replicates the route group's CSRF + RequireAuth chain and asserts an unauthenticated request to /user/{username} returns 303 to /pages/login and never reaches the endpoint handler

Validation

docker build . (runs fmt-check, lint, test, build) completed successfully:

#32 naming to docker.io/library/webhooker-issue60 done
#32 DONE 0.7s

Build exited 0; no lint findings, all tests pass.

## What changed **`internal/server/routes.go`** — in `setupUserRoutes()`, added `r.Use(s.mw.RequireAuth())` immediately after the existing `r.Use(s.mw.CSRF())` on the `/user/{username}` route group. Relative order is CSRF first, then RequireAuth, matching `/sources` and `/source/{sourceID}`. **`internal/handlers/profile.go`** — in `HandleProfile`, removed the now-unreachable "not authenticated -> redirect to `/pages/login`" branch (RequireAuth guarantees an authenticated session before the handler runs). The handler still reads the username and user id from the session for the own-profile-only comparison and template data; a request for another user's profile still returns 403. A session-retrieval error is now surfaced as a 500 rather than a redirect. **`internal/handlers/profile_test.go`** (new) — three tests: - `TestHandleProfile_OwnProfile_OK`: own profile returns 200 - `TestHandleProfile_OtherProfile_Forbidden`: another user's profile returns 403 - `TestUserRoute_Unauthenticated_RedirectedByMiddleware`: replicates the route group's CSRF + RequireAuth chain and asserts an unauthenticated request to `/user/{username}` returns 303 to `/pages/login` and never reaches the endpoint handler ## Validation `docker build .` (runs fmt-check, lint, test, build) completed successfully: ``` #32 naming to docker.io/library/webhooker-issue60 done #32 DONE 0.7s ``` Build exited 0; no lint findings, all tests pass.
Author
Collaborator

Independent review — PASS (merge-ready)

Reviewed the diff against the issue spec and repo policies; posture was adversarial.

Correctness / spec

  • internal/server/routes.go setupUserRoutes() now applies RequireAuth() immediately after CSRF() on /user/{username}, matching the /sources and /source/{sourceID} ordering. Meets the definition of done.
  • internal/handlers/profile.go HandleProfile drops the now-dead unauthenticated-redirect branch; a session.Get error returns 500; the own-profile-only 403 is unchanged. Correct given RequireAuth runs first.
  • Tests cover own-profile 200, other-profile 403, and an unauthenticated request redirected (303) to /pages/login without reaching the handler.

Policy

  • Change is limited to the three intended files. make fmt clean, docker build . green (fmt-check + lint + test + build). No AI/tooling references. Commit subject closes the issue.

One non-blocking observation

  • TestUserRoute_Unauthenticated_RedirectedByMiddleware reconstructs the route group (CSRF then RequireAuth) inside the test rather than exercising the production setupUserRoutes, so it would not catch a future accidental removal of the RequireAuth line from routes.go. It does correctly prove the middleware chain's behaviour. Acceptable for a one-line wiring change given there is no full-server route test seam today; worth tightening if such a seam is added later.

Verdict: meets the bar. Marking merge-ready and handing to @sneak for final review.

## Independent review — PASS (merge-ready) Reviewed the diff against the issue spec and repo policies; posture was adversarial. **Correctness / spec** - `internal/server/routes.go` `setupUserRoutes()` now applies `RequireAuth()` immediately after `CSRF()` on `/user/{username}`, matching the `/sources` and `/source/{sourceID}` ordering. Meets the definition of done. - `internal/handlers/profile.go` `HandleProfile` drops the now-dead unauthenticated-redirect branch; a `session.Get` error returns 500; the own-profile-only 403 is unchanged. Correct given `RequireAuth` runs first. - Tests cover own-profile 200, other-profile 403, and an unauthenticated request redirected (303) to `/pages/login` without reaching the handler. **Policy** - Change is limited to the three intended files. `make fmt` clean, `docker build .` green (fmt-check + lint + test + build). No AI/tooling references. Commit subject closes the issue. **One non-blocking observation** - `TestUserRoute_Unauthenticated_RedirectedByMiddleware` reconstructs the route group (`CSRF` then `RequireAuth`) inside the test rather than exercising the production `setupUserRoutes`, so it would not catch a future accidental removal of the `RequireAuth` line from `routes.go`. It does correctly prove the middleware chain's behaviour. Acceptable for a one-line wiring change given there is no full-server route test seam today; worth tightening if such a seam is added later. Verdict: meets the bar. Marking merge-ready and handing to @sneak for final review.
sneak was assigned by clawbot 2026-08-07 13:50:55 +02:00
sneak added 1 commit 2026-08-07 13:58:43 +02:00
Merge branch 'main' into issue-60-user-requireauth
All checks were successful
check / check (push) Successful in 2m38s
4ea24de8f6
sneak merged commit 07fc63d9fa into main 2026-08-07 14:00:17 +02:00
sneak deleted branch issue-60-user-requireauth 2026-08-07 14:00:17 +02:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#71