package api import ( "net/http" "net/http/httptest" "testing" "time" ) const validJWTForTests = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXItMTIzIn0.signature" func TestResolveNamespaceForTokenRejectsInvalidTokenOutsideTestMode(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/index.cfm/instances" { t.Fatalf("unexpected path: %s", r.URL.Path) } w.WriteHeader(http.StatusUnauthorized) })) defer server.Close() oldDeckAPIs := deckAPIs deckAPIs = map[string]string{"test": server.URL} defer func() { deckAPIs = oldDeckAPIs }() s := &Server{http: server.Client()} if _, err := s.resolveNamespaceForToken("user@example.com", "test", false); err == nil { t.Fatal("expected invalid token to be rejected outside test mode") } } func TestResolveNamespaceForTokenAllowsValidatedJWTInTestMode(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if got := r.Header.Get("Authorization"); got == "" { t.Fatal("expected Authorization header") } w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{"results":[]}`)) })) defer server.Close() oldDeckAPIs := deckAPIs deckAPIs = map[string]string{"test": server.URL} defer func() { deckAPIs = oldDeckAPIs }() s := &Server{http: server.Client()} ns, err := s.resolveNamespaceForToken(validJWTForTests, "test", true) if err != nil { t.Fatalf("expected JWT to pass in test mode: %v", err) } expected, err := namespaceFromJWT(validJWTForTests) if err != nil { t.Fatalf("namespaceFromJWT: %v", err) } if ns != expected { t.Fatalf("expected namespace %q, got %q", expected, ns) } } func TestResolveNamespaceForTokenAllowsEmailFallbackOnlyInTestMode(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) })) defer server.Close() oldDeckAPIs := deckAPIs deckAPIs = map[string]string{"test": server.URL} defer func() { deckAPIs = oldDeckAPIs }() s := &Server{http: server.Client()} ns, err := s.resolveNamespaceForToken("user@example.com", "test", true) if err != nil { t.Fatalf("expected email fallback in test mode: %v", err) } if ns != namespaceFromSub("user@example.com") { t.Fatalf("unexpected namespace: %q", ns) } _, err = s.resolveNamespaceForToken("user@example.com", "test", false) if err == nil { t.Fatal("expected email fallback to be rejected outside test mode") } } func TestValidateDeckTokenCachesSuccessfulValidation(t *testing.T) { requests := 0 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requests++ w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{"results":[]}`)) })) defer server.Close() oldDeckAPIs := deckAPIs deckAPIs = map[string]string{"test": server.URL} defer func() { deckAPIs = oldDeckAPIs }() s := &Server{http: server.Client()} if err := s.validateDeckToken(validJWTForTests, "test"); err != nil { t.Fatalf("first validate failed: %v", err) } if err := s.validateDeckToken(validJWTForTests, "test"); err != nil { t.Fatalf("second validate failed: %v", err) } if requests != 1 { t.Fatalf("expected 1 upstream request because of cache, got %d", requests) } if v, ok := s.tokenCache.Load("test:" + validJWTForTests); !ok || time.Now().After(v.(time.Time)) { t.Fatal("expected token to be cached") } }