Files
rose_cat707 0d84b07f68
CI / docker (push) Successful in 1m58s
feat: Wormhole 内网穿透与反向代理网关
Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。
Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 17:52:43 +08:00

60 lines
1.3 KiB
Go

package auth
import (
"errors"
"testing"
"time"
"github.com/wormhole/wormhole/internal/config"
)
func TestLoginLimiterBlocksAfterMaxAttempts(t *testing.T) {
l := NewLoginLimiter(&config.AuthConfig{
LoginMaxAttempts: 3,
LoginWindow: time.Minute,
LoginLockout: 10 * time.Minute,
})
ip := "192.168.1.1"
user := "admin"
for i := 0; i < 3; i++ {
if _, blocked := l.IsBlocked(ip, user); blocked {
t.Fatalf("unexpected block at attempt %d", i+1)
}
l.RecordFailure(ip, user)
}
retry, blocked := l.IsBlocked(ip, user)
if !blocked || retry <= 0 {
t.Fatalf("expected block after max attempts, retry=%v blocked=%v", retry, blocked)
}
}
func TestLoginLimiterResetClearsBlock(t *testing.T) {
l := NewLoginLimiter(&config.AuthConfig{
LoginMaxAttempts: 2,
LoginWindow: time.Minute,
LoginLockout: time.Minute,
})
ip := "10.0.0.1"
l.RecordFailure(ip, "u1")
l.RecordFailure(ip, "u1")
if _, blocked := l.IsBlocked(ip, "u1"); !blocked {
t.Fatal("expected blocked")
}
l.Reset(ip, "u1")
if _, blocked := l.IsBlocked(ip, "u1"); blocked {
t.Fatal("expected unblocked after reset")
}
}
func TestLoginBlockedError(t *testing.T) {
err := &LoginBlockedError{RetryAfter: 30 * time.Second}
if !errors.As(err, new(*LoginBlockedError)) {
t.Fatal("LoginBlockedError should be detectable via errors.As")
}
}