Ctrl K
ComunidadGuías…

internal/middleware/auth_middleware_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package middleware

import (
	"context"
	"net/http"
	"net/http/httptest"
	"strconv"
	"testing"

	"xprem/internal/services"
	"xprem/internal/types"

	"github.com/gorilla/mux"
)

// runAuthMiddleware sends a request through NewAuthMiddleware on a
// non-app-scoped route, so the CLI-auth branch can only ever reject.
func runAuthMiddleware(t *testing.T, configure func(r *http.Request)) *httptest.ResponseRecorder {
	t.Helper()
	router := mux.NewRouter()
	router.Use(NewAuthMiddleware(services.NewDashboardAuthService(nil, nil), services.NewCliAuthService(nil)))
	router.HandleFunc("/settings", func(w http.ResponseWriter, r *http.Request) {
		if principal := services.PrincipalFromContext(r.Context()); principal != nil {
			w.Header().Set("X-Principal-Email", principal.Email)
			w.Header().Set("X-Principal-Admin", strconv.FormatBool(principal.IsAdmin))
		}
		w.Header().Set("X-Cli-App", services.CliAuthAppFromContext(r.Context()))
		w.WriteHeader(http.StatusOK)
	})
	r := httptest.NewRequest("GET", "/settings", nil)
	configure(r)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, r)
	return w
}

func TestAuthMiddleware(t *testing.T) {
	t.Setenv("JWT_SECRET", "test-secret")
	t.Setenv("ADMIN_EMAIL", "admin@example.com")
	t.Setenv("ADMIN_PASSWORD", "test-password")

	t.Run("cli auth rejected on a non-app-scoped route", func(t *testing.T) {
		w := runAuthMiddleware(t, func(r *http.Request) {
			r.Header.Set("Use-Cli-Auth", "true")
			r.Header.Set("Authorization", "Bearer some-cli-credential")
		})
		if w.Code != http.StatusUnauthorized {
			t.Fatalf("expected 401 for cli auth without app context, got %d", w.Code)
		}
	})

	t.Run("valid dashboard session is accepted", func(t *testing.T) {
		session, err := services.NewDashboardAuthService(nil, nil).LoginWithEmailPassword(context.Background(), "admin@example.com", "test-password")
		if err != nil {
			t.Fatalf("login failed: %v", err)
		}
		w := runAuthMiddleware(t, func(r *http.Request) {
			r.Header.Set("Authorization", "Bearer "+session.Token)
		})
		if w.Code != http.StatusOK {
			t.Fatalf("expected 200 with valid session token, got %d", w.Code)
		}
		if got := w.Header().Get("X-Principal-Email"); got != "admin@example.com" {
			t.Fatalf("expected the principal email to reach the handler, got %q", got)
		}
		if got := w.Header().Get("X-Principal-Admin"); got != "true" {
			t.Fatalf("expected the stateless principal to be admin, got %q", got)
		}
		if got := w.Header().Get("X-Cli-App"); got != "" {
			t.Fatalf("a dashboard session must not carry the CLI marker, got %q", got)
		}
	})

	t.Run("invalid bearer token is rejected", func(t *testing.T) {
		w := runAuthMiddleware(t, func(r *http.Request) {
			r.Header.Set("Authorization", "Bearer not-a-jwt")
		})
		if w.Code != http.StatusUnauthorized {
			t.Fatalf("expected 401 with invalid token, got %d", w.Code)
		}
	})

	t.Run("missing Authorization header is rejected", func(t *testing.T) {
		w := runAuthMiddleware(t, func(r *http.Request) {})
		if w.Code != http.StatusUnauthorized {
			t.Fatalf("expected 401 with no Authorization header, got %d", w.Code)
		}
	})
}

// fakeCliAuthRepo accepts any credential and answers with key id 0.
type fakeCliAuthRepo struct{}

func (fakeCliAuthRepo) ValidateCliCredential(_ context.Context, _ string, _ types.Auth) (int64, error) {
	return 0, nil
}
func (fakeCliAuthRepo) InsertApiKey(_ context.Context, _ string, _ string, _ string, _ string) (int64, error) {
	return 0, nil
}
func (fakeCliAuthRepo) GetApiKeyNameByID(_ context.Context, _ string, _ int64) (string, error) {
	return "", nil
}

func (fakeCliAuthRepo) GetApiKeysMetadataByAppID(_ context.Context, _ string) ([]types.ApiKeyMetadata, error) {
	return nil, nil
}
func (fakeCliAuthRepo) RevokeApiKeyByID(_ context.Context, _ int64, _ string) (string, error) {
	return "", nil
}

// TestAuthMiddlewareCliBranchStampsMarker checks that the CLI branch stamps
// the validated app on the context.
func TestAuthMiddlewareCliBranchStampsMarker(t *testing.T) {
	t.Setenv("JWT_SECRET", "test-secret")

	router := mux.NewRouter()
	appRouter := router.PathPrefix("/{APP_ID}").Subrouter()
	appRouter.Use(NewAuthMiddleware(services.NewDashboardAuthService(nil, nil), services.NewCliAuthService(fakeCliAuthRepo{})))
	appRouter.HandleFunc("/branches", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-Cli-App", services.CliAuthAppFromContext(r.Context()))
		if services.PrincipalFromContext(r.Context()) != nil {
			t.Error("a CLI request must not carry a dashboard principal")
		}
		w.WriteHeader(http.StatusOK)
	})

	r := httptest.NewRequest("GET", "/my-app/branches", nil)
	r.Header.Set("Use-Cli-Auth", "true")
	r.Header.Set("Authorization", "Bearer eoo_some-api-key")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, r)

	if w.Code != http.StatusOK {
		t.Fatalf("expected the validated CLI request to pass, got %d: %s", w.Code, w.Body.String())
	}
	if got := w.Header().Get("X-Cli-App"); got != "my-app" {
		t.Fatalf("expected the CLI marker to carry the validated app id, got %q", got)
	}
}