64 lines
2.0 KiB
Go
64 lines
2.0 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"testing/fstest"
|
|
|
|
"finance-duck/internal/app"
|
|
)
|
|
|
|
func TestOriginAndHostGuardProtectNoLoginService(t *testing.T) {
|
|
t.Setenv("OPENROUTER_API_KEY", "")
|
|
t.Setenv("ENABLEBANKING_APP_ID", "")
|
|
t.Setenv("ENABLEBANKING_KEY_FILE", "")
|
|
t.Setenv("ENABLEBANKING_REDIRECT_URL", "")
|
|
a, err := app.Open(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer a.Close()
|
|
h, err := New(a, fstest.MapFS{"index.html": &fstest.MapFile{Data: []byte("<!doctype html><title>Finance</title>")}}, "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cases := []struct {
|
|
name, host, origin, content string
|
|
want int
|
|
}{{"rebound host", "attacker.example", "", "application/json", 403}, {"cross origin", "localhost:8080", "https://attacker.example", "application/json", 403}, {"simple form CSRF", "localhost:8080", "", "text/plain", 415}, {"valid local mutation", "localhost:8080", "http://localhost:8080", "application/json", 200}}
|
|
for _, tt := range cases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodPost, "http://localhost:8080/api/settings", strings.NewReader(`{"model":"example/model","include_amount":false}`))
|
|
r.Host = tt.host
|
|
r.Header.Set("Content-Type", tt.content)
|
|
r.Header.Set("Origin", tt.origin)
|
|
w := httptest.NewRecorder()
|
|
h.ServeHTTP(w, r)
|
|
if w.Code != tt.want {
|
|
t.Fatalf("got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
})
|
|
}
|
|
r := httptest.NewRequest(http.MethodGet, "http://localhost:8080/api/state", nil)
|
|
w := httptest.NewRecorder()
|
|
h.ServeHTTP(w, r)
|
|
var s app.State
|
|
if err = json.NewDecoder(w.Body).Decode(&s); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if s.Settings.Model != "example/model" {
|
|
t.Fatal("same-origin edit not persisted")
|
|
}
|
|
r = httptest.NewRequest(http.MethodGet, "http://localhost:8080/", nil)
|
|
w = httptest.NewRecorder()
|
|
h.ServeHTTP(w, r)
|
|
b, _ := io.ReadAll(w.Body)
|
|
if w.Code != 200 || !strings.Contains(string(b), "<!doctype html>") {
|
|
t.Fatalf("UI not served: %d %s", w.Code, b)
|
|
}
|
|
}
|