package authz import ( "encoding/json" "net/http" "net/http/httptest" "os" "testing" "sourcecraft.dev/bigbes/sr-ht-core/crypto" "sourcecraft.dev/bigbes/sr-ht-ecore/ecoretest" ) // TestMain installs ecore's fixed test keyset into core-go's process-global // crypto, so Encrypt/Decrypt work offline. The keys are constants and the call // is idempotent, which is what lets this package and web/ both initialise // without the second rotating what the first sealed with. func TestMain(m *testing.M) { ecoretest.InitCrypto() os.Exit(m.Run()) } // sealCookie builds a valid unified-login cookie value carrying the given name. func sealCookie(t *testing.T, name string) string { t.Helper() payload, err := json.Marshal(map[string]string{"name": name}) if err != nil { t.Fatalf("marshal claims: %v", err) } return string(crypto.Encrypt(payload)) } func TestUsernameFromRequest_RoundTrip(t *testing.T) { r := httptest.NewRequest(http.MethodGet, "/", nil) r.AddCookie(&http.Cookie{Name: CookieName, Value: sealCookie(t, "bigbes")}) if got := UsernameFromRequest(r); got != "bigbes" { t.Fatalf("username = %q, want %q", got, "bigbes") } } func TestUsernameFromRequest_StripsTilde(t *testing.T) { r := httptest.NewRequest(http.MethodGet, "/", nil) r.AddCookie(&http.Cookie{Name: CookieName, Value: sealCookie(t, "~bigbes")}) if got := UsernameFromRequest(r); got != "bigbes" { t.Fatalf("username = %q, want %q", got, "bigbes") } } func TestUsernameFromRequest_GarbageCookie(t *testing.T) { r := httptest.NewRequest(http.MethodGet, "/", nil) r.AddCookie(&http.Cookie{Name: CookieName, Value: "not-a-valid-fernet-token"}) if got := UsernameFromRequest(r); got != "" { t.Fatalf("username = %q, want empty", got) } } func TestUsernameFromRequest_MissingCookie(t *testing.T) { r := httptest.NewRequest(http.MethodGet, "/", nil) if got := UsernameFromRequest(r); got != "" { t.Fatalf("username = %q, want empty", got) } } func TestUsernameFromRequest_NonJSONPayload(t *testing.T) { r := httptest.NewRequest(http.MethodGet, "/", nil) // A well-formed Fernet token whose plaintext is not JSON. r.AddCookie(&http.Cookie{Name: CookieName, Value: string(crypto.Encrypt([]byte("plain text")))}) if got := UsernameFromRequest(r); got != "" { t.Fatalf("username = %q, want empty", got) } } func TestMiddlewareAndForContext(t *testing.T) { var seen string h := Middleware()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { seen = ForContext(r.Context()) })) r := httptest.NewRequest(http.MethodGet, "/", nil) r.AddCookie(&http.Cookie{Name: CookieName, Value: sealCookie(t, "bigbes")}) h.ServeHTTP(httptest.NewRecorder(), r) if seen != "bigbes" { t.Fatalf("ForContext = %q, want %q", seen, "bigbes") } // Anonymous request: middleware still runs, ForContext yields "". seen = "sentinel" h.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(http.MethodGet, "/", nil)) if seen != "" { t.Fatalf("anonymous ForContext = %q, want empty", seen) } } func TestForContext_NoValue(t *testing.T) { if got := ForContext(httptest.NewRequest(http.MethodGet, "/", nil).Context()); got != "" { t.Fatalf("ForContext on bare context = %q, want empty", got) } }