46 lines
1.5 KiB
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)
|
|
}
|
|
}
|