Files
Pulse/internal/api/router_rate_limit_security_test.go
2026-02-04 10:28:41 +00:00

60 lines
1.5 KiB
Go

package api
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/rcourtman/pulse-go-rewrite/internal/config"
"github.com/rcourtman/pulse-go-rewrite/pkg/auth"
)
func newLoginRouter(t *testing.T) *Router {
t.Helper()
hashed, err := auth.HashPassword("Password!1")
if err != nil {
t.Fatalf("hash password: %v", err)
}
cfg := &config.Config{
AuthUser: "admin",
AuthPass: hashed,
DataPath: t.TempDir(),
ConfigPath: t.TempDir(),
}
return NewRouter(cfg, nil, nil, nil, nil, "1.0.0")
}
func TestLoginRateLimitEnforced(t *testing.T) {
router := newLoginRouter(t)
ip := "203.0.113.200"
authLimiter.Reset(ip)
defer authLimiter.Reset(ip)
body := `{"username":"admin","password":"Password!1","rememberMe":false}`
for i := 0; i < 10; i++ {
req := httptest.NewRequest(http.MethodPost, "/api/login", strings.NewReader(body))
req.RemoteAddr = ip + ":12345"
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
router.mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("attempt %d: expected %d, got %d (%s)", i+1, http.StatusOK, rec.Code, rec.Body.String())
}
}
req := httptest.NewRequest(http.MethodPost, "/api/login", strings.NewReader(body))
req.RemoteAddr = ip + ":12345"
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
router.mux.ServeHTTP(rec, req)
if rec.Code != http.StatusTooManyRequests {
t.Fatalf("expected %d, got %d (%s)", http.StatusTooManyRequests, rec.Code, rec.Body.String())
}
}