- auth.Mount(env, key) wraps csrf.Protect with locked D-14/D-24 options - auth.LoadKeyFromEnv() reads SESSION_SECRET, hex-decodes, validates 32 bytes; fails fast on error - ui.CSRFField(token) templ component renders hidden _csrf input - Layout, LoginPage/Fragment, SignupPage/Fragment, Index all embed @ui.CSRFField(csrfToken) - Handlers thread csrf.Token(r) into every page/fragment render call - NewRouter mounts auth.Mount after ResolveSession, before all route groups (D-24) - main.go calls auth.LoadKeyFromEnv(); logs.Fatalf on missing/invalid SESSION_SECRET - SESSION_SECRET documented in .env.example with openssl rand -hex 32 instruction - go.mod: gorilla/csrf v1.7.3 (direct); prior tests updated with getCSRFToken helper - All Plan 04/05/06 tests updated to acquire and submit valid _csrf tokens
51 lines
1.6 KiB
Go
51 lines
1.6 KiB
Go
package templates
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"backend/internal/auth"
|
|
)
|
|
|
|
// TestLayout_LogoutFormVisibleWhenAuthed verifies that the logout form is
|
|
// rendered in the header when Layout receives a non-nil user (D-22).
|
|
// The _csrf hidden field must also be present (AUTH-06).
|
|
func TestLayout_LogoutFormVisibleWhenAuthed(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
user := &auth.User{Email: "a@b.c"}
|
|
err := Layout("Test", user, "mytesttoken").Render(context.Background(), &buf)
|
|
if err != nil {
|
|
t.Fatalf("Layout.Render: %v", err)
|
|
}
|
|
body := buf.String()
|
|
|
|
if !strings.Contains(body, `action="/logout"`) {
|
|
t.Errorf("Layout body missing action=\"/logout\"; want logout form when authed\nbody: %s", body)
|
|
}
|
|
if !strings.Contains(body, `method="POST"`) {
|
|
t.Errorf("Layout body missing method=\"POST\"; logout must be a POST form (D-22)")
|
|
}
|
|
if !strings.Contains(body, `name="_csrf"`) {
|
|
t.Errorf("Layout body missing name=\"_csrf\"; logout form must embed CSRF field (AUTH-06)")
|
|
}
|
|
if !strings.Contains(body, `value="mytesttoken"`) {
|
|
t.Errorf("Layout body missing value=\"mytesttoken\"; CSRF token not threaded into form")
|
|
}
|
|
}
|
|
|
|
// TestLayout_LogoutFormHiddenWhenUnauthed verifies that no logout form is
|
|
// rendered when Layout receives a nil user (unauthenticated request).
|
|
func TestLayout_LogoutFormHiddenWhenUnauthed(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
err := Layout("Test", nil, "").Render(context.Background(), &buf)
|
|
if err != nil {
|
|
t.Fatalf("Layout.Render: %v", err)
|
|
}
|
|
body := buf.String()
|
|
|
|
if strings.Contains(body, `action="/logout"`) {
|
|
t.Errorf("Layout body must NOT contain action=\"/logout\" when user is nil (unauthenticated)")
|
|
}
|
|
}
|