Smail/server/controllers/security_limiter_test.go

46 lines
1.5 KiB
Go

package controllers
import (
"net/http"
"net/http/httptest"
"testing"
"time"
)
func TestPublicSecurityLimitersIsolateIPAndExpire(t *testing.T) {
limiter := newLoginLimiter(2)
now := time.Date(2026, 8, 26, 12, 0, 0, 0, time.UTC)
limiter.now = func() time.Time { return now }
first := httptest.NewRequest(http.MethodPost, "https://mail.example.com/api/security", nil)
first.RemoteAddr = "192.0.2.10:1234"
second := httptest.NewRequest(http.MethodPost, "https://mail.example.com/api/security", nil)
second.RemoteAddr = "192.0.2.11:1234"
firstKey := limiter.ipKey(first)
secondKey := limiter.ipKey(second)
limiter.recordFailure(firstKey)
if limiter.blocked(firstKey) {
t.Fatal("public security limiter blocked the first attempt too early")
}
limiter.recordFailure(firstKey)
if !limiter.blocked(firstKey) {
t.Fatal("public security limiter did not block the repeated IP")
}
if limiter.blocked(secondKey) {
t.Fatal("public security limiter shared state across IPs")
}
now = now.Add(loginBlockTime + time.Second)
if limiter.blocked(firstKey) {
t.Fatal("public security limiter block did not expire")
}
}
func TestPublicSecurityLimiterUsesBoundedEntryStore(t *testing.T) {
limiter := newLoginLimiter(1)
for index := 0; index < loginMaxEntries+128; index++ {
limiter.recordFailure("public-ip-key-" + string(rune(index)))
}
if len(limiter.attempts) > loginMaxEntries {
t.Fatalf("public security limiter entries = %d, want <= %d", len(limiter.attempts), loginMaxEntries)
}
}