mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-08-06 10:45:35 -05:00
Introduce a thread-safe RateLimiter that tracks attempts per key (IP address) within a sliding time window, and wire it into the authentication endpoints: - Login: failed login attempts from an address are counted; once the configured maximum is exceeded within the window, further logins from that address are rejected with RespTooManyRequests. A successful login clears the failed attempts for that address. - Registration: implement the previously stubbed tooManyRegistrationAttempts, limiting how many accounts can be created per address per window. - Forgot-password: throttle both the email-request and the email-challenge paths per address. New [security] settings with defaults: max_login_attempts_per_ip=5 / login_attempt_window_seconds=900 max_registrations_per_ip=2 / registration_window_seconds=3600 max_forgot_password_requests_per_ip=3 / forgot_password_window_seconds=3600 Adds unit tests for the RateLimiter (window limit, over-limit blocking, clearing, per-key independence). Took 3 minutes
50 lines
1.2 KiB
C++
50 lines
1.2 KiB
C++
#include "ratelimiter.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
TEST(RateLimiterTest, AllowsAttemptsWithinLimit)
|
|
{
|
|
RateLimiter limiter;
|
|
ASSERT_FALSE(limiter.recordAttempt("ip", 3, 60));
|
|
ASSERT_FALSE(limiter.recordAttempt("ip", 3, 60));
|
|
ASSERT_FALSE(limiter.recordAttempt("ip", 3, 60));
|
|
ASSERT_FALSE(limiter.isBlocked("ip", 3, 60));
|
|
}
|
|
|
|
TEST(RateLimiterTest, BlocksAttemptsOverLimit)
|
|
{
|
|
RateLimiter limiter;
|
|
ASSERT_FALSE(limiter.recordAttempt("ip", 2, 60));
|
|
ASSERT_FALSE(limiter.recordAttempt("ip", 2, 60));
|
|
ASSERT_TRUE(limiter.recordAttempt("ip", 2, 60));
|
|
ASSERT_TRUE(limiter.isBlocked("ip", 2, 60));
|
|
}
|
|
|
|
TEST(RateLimiterTest, ClearAttempts)
|
|
{
|
|
RateLimiter limiter;
|
|
ASSERT_TRUE(limiter.recordAttempt("ip", 0, 60));
|
|
ASSERT_TRUE(limiter.isBlocked("ip", 0, 60));
|
|
limiter.clearAttempts("ip");
|
|
ASSERT_FALSE(limiter.isBlocked("ip", 0, 60));
|
|
}
|
|
|
|
TEST(RateLimiterTest, KeysAreIndependent)
|
|
{
|
|
RateLimiter limiter;
|
|
ASSERT_TRUE(limiter.recordAttempt("a", 0, 60));
|
|
ASSERT_FALSE(limiter.isBlocked("b", 0, 60));
|
|
ASSERT_TRUE(limiter.isBlocked("a", 0, 60));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|