Files
story/internal/httpapi/onboarding_customer_auth_test.go
T

87 lines
3.5 KiB
Go
Raw Normal View History

package httpapi
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"data-terminal-cloud/internal/alerts"
"data-terminal-cloud/internal/identity"
"data-terminal-cloud/internal/onboarding"
)
func TestCustomerModelReadDoesNotGrantOperatorWrites(t *testing.T) {
for _, tc := range []struct {
method, path string
allowed bool
}{
{"GET", "/api/v1/content-models", true},
{"POST", "/api/v1/content-models", false},
{"POST", "/api/v1/content-models/123/activate", false},
{"GET", "/api/v1/content-models/123", false},
{"GET", "/api/v1/ops/content-models", false},
} {
if customerCookieRequest(httptest.NewRequest(tc.method, tc.path, nil)) != tc.allowed {
t.Fatalf("wrong auth boundary: %s %s", tc.method, tc.path)
}
}
}
func TestAlertRoutesSelectOperatorCookieAuthentication(t *testing.T) {
router := NewRouter(RouterOptions{ServiceName: "api", TokenVerifier: &identity.OIDCVerifier{}, AlertService: &alerts.Service{}, OnboardingService: &onboarding.Service{}})
for _, path := range []string{"alert-routing-policies", "alerts", "alert-silences", "alert-delivery-tests"} {
r := httptest.NewRequest("GET", "https://platform.example/api/v1/ops/"+path, nil)
r.AddCookie(&http.Cookie{Name: "__Host-platform-onboarding", Value: "customer-cookie"})
w := httptest.NewRecorder()
router.ServeHTTP(w, r)
var body struct {
Code string `json:"code"`
}
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
t.Fatal(err)
}
if w.Code != 401 || body.Code != "LOGIN_REQUIRED" {
t.Fatalf("%s must require an operator cookie: %s", path, w.Body.String())
}
}
}
func TestCustomerCookieRouteBoundary(t *testing.T) {
for _, path := range []string{"/api/v1/memoirs/query", "/api/v1/memoirs/generate", "/api/v1/memoirs/import", "/api/v1/memoirs/illustrations/123"} {
if !customerCookiePath(path) {
t.Errorf("memoir customer auth unavailable: %s", path)
}
}
for _, path := range []string{"/api/v1/me", "/api/v1/devices", "/api/v1/households/123", "/api/v1/events", "/api/v1/memories/mutations", "/api/v1/stories/123", "/api/v1/conversations/123/turns", "/api/v1/privacy-requests/123", "/api/v1/exports/123", "/api/v1/member-invitations/accept"} {
if !customerCookiePath(path) {
t.Errorf("customer route not enabled: %s", path)
}
}
for _, path := range []string{"/api/v1/ops/devices", "/api/v1/content-models", "/api/v1/device/calls/prepare", "/api/v1/device/v3/sessions", "/api/v1/memories-admin", "/api/v1/devices-admin", "/internal/v1/tools/memory-search", "/callbacks/v1/vertc/voice-chat"} {
if customerCookiePath(path) {
t.Errorf("cookie crossed authentication boundary: %s", path)
}
}
}
func TestOperatorCookieRouteBoundary(t *testing.T) {
for _, path := range []string{"/api/v1/ops/devices", "/api/v1/ops/device-inventory", "/api/v1/content-models", "/api/v1/me", "/api/v1/events"} {
r := httptest.NewRequest("GET", path, nil)
r.Header.Set("X-Login-Portal", "operator")
if !operatorCookieRequest(r) {
t.Errorf("operator route unavailable: %s", path)
}
}
for _, path := range []string{"/api/v1/ops-admin", "/api/v1/device/calls/prepare", "/api/v1/web/login/password", "/callbacks/v1/vertc/voice-chat", "/api/v1/households", "/internal/v1/tools/memory-search"} {
r := httptest.NewRequest("POST", path, nil)
r.Header.Set("X-Login-Portal", "operator")
if operatorCookieRequest(r) {
t.Errorf("operator cookie crossed boundary: %s", path)
}
}
if operatorCookieRequest(httptest.NewRequest("GET", "/api/v1/me", nil)) {
t.Fatal("operator identity selected in customer portal")
}
}