test: Add isRequestAuthenticated tests for API package
Add comprehensive tests for the isRequestAuthenticated function covering: - Nil inputs (config, request, both) - Basic auth (valid, invalid password, invalid username, malformed base64, missing colon) - API token via X-API-Token header - API token via Bearer authorization header (case insensitive) - Invalid/empty/whitespace API tokens - No auth configured scenarios - Empty session cookie handling Coverage: isRequestAuthenticated 26.1% → 82.6% Coverage: API package 30.7% → 30.9%
This commit is contained in:
parent
cf6149e884
commit
71e15886ed
1 changed files with 202 additions and 0 deletions
|
|
@ -2,10 +2,12 @@ package api
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/auth"
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
||||
)
|
||||
|
||||
|
|
@ -1075,3 +1077,203 @@ func TestResolvePublicURL_NilRequest(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsRequestAuthenticated_NilInputs(t *testing.T) {
|
||||
t.Run("nil config returns false", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
if isRequestAuthenticated(nil, req) {
|
||||
t.Error("expected false for nil config")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("nil request returns false", func(t *testing.T) {
|
||||
cfg := &config.Config{}
|
||||
if isRequestAuthenticated(cfg, nil) {
|
||||
t.Error("expected false for nil request")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("both nil returns false", func(t *testing.T) {
|
||||
if isRequestAuthenticated(nil, nil) {
|
||||
t.Error("expected false when both nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsRequestAuthenticated_BasicAuth(t *testing.T) {
|
||||
password := "testPassword123"
|
||||
hashedPass, err := auth.HashPassword(password)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to hash password: %v", err)
|
||||
}
|
||||
|
||||
cfg := &config.Config{
|
||||
AuthUser: "admin",
|
||||
AuthPass: hashedPass,
|
||||
}
|
||||
|
||||
t.Run("valid basic auth", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
creds := base64.StdEncoding.EncodeToString([]byte("admin:" + password))
|
||||
req.Header.Set("Authorization", "Basic "+creds)
|
||||
|
||||
if !isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected true for valid basic auth")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("invalid password", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
creds := base64.StdEncoding.EncodeToString([]byte("admin:wrongpassword"))
|
||||
req.Header.Set("Authorization", "Basic "+creds)
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for invalid password")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("invalid username", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
creds := base64.StdEncoding.EncodeToString([]byte("wronguser:" + password))
|
||||
req.Header.Set("Authorization", "Basic "+creds)
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for invalid username")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("malformed base64", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
req.Header.Set("Authorization", "Basic notbase64!!!")
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for malformed base64")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("missing colon in credentials", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
creds := base64.StdEncoding.EncodeToString([]byte("nocolon"))
|
||||
req.Header.Set("Authorization", "Basic "+creds)
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for credentials without colon")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no auth header", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for no auth header")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsRequestAuthenticated_APIToken(t *testing.T) {
|
||||
// Create a valid API token record
|
||||
rawToken := "test-api-token-12345"
|
||||
record, err := config.NewAPITokenRecord(rawToken, "test-token", []string{"read"})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create API token record: %v", err)
|
||||
}
|
||||
|
||||
cfg := &config.Config{
|
||||
APITokens: []config.APITokenRecord{*record},
|
||||
}
|
||||
|
||||
t.Run("valid X-API-Token header", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
req.Header.Set("X-API-Token", rawToken)
|
||||
|
||||
if !isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected true for valid API token")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("valid Bearer token", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+rawToken)
|
||||
|
||||
if !isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected true for valid Bearer token")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Bearer case insensitive", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
req.Header.Set("Authorization", "bearer "+rawToken)
|
||||
|
||||
if !isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected true for lowercase bearer")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("invalid API token", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
req.Header.Set("X-API-Token", "invalid-token")
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for invalid API token")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("empty API token", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
req.Header.Set("X-API-Token", "")
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for empty API token")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("whitespace only API token", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
req.Header.Set("X-API-Token", " ")
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for whitespace-only API token")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsRequestAuthenticated_NoAuthConfigured(t *testing.T) {
|
||||
cfg := &config.Config{}
|
||||
|
||||
t.Run("no auth configured returns false", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false when no auth is configured")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("basic auth header ignored when not configured", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
creds := base64.StdEncoding.EncodeToString([]byte("admin:password"))
|
||||
req.Header.Set("Authorization", "Basic "+creds)
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false when basic auth not configured")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsRequestAuthenticated_SessionCookie(t *testing.T) {
|
||||
cfg := &config.Config{}
|
||||
|
||||
t.Run("empty session cookie value returns false", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/test", nil)
|
||||
req.AddCookie(&http.Cookie{
|
||||
Name: "pulse_session",
|
||||
Value: "",
|
||||
})
|
||||
|
||||
if isRequestAuthenticated(cfg, req) {
|
||||
t.Error("expected false for empty session cookie value")
|
||||
}
|
||||
})
|
||||
|
||||
// Note: Testing valid session would require setting up the session store,
|
||||
// which is tested elsewhere. Here we test the branch logic.
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue