107 lines
3.8 KiB
PHP
107 lines
3.8 KiB
PHP
<?php
|
|
|
|
require_once dirname(__DIR__, 3) . '/app/classes/database.php';
|
|
require_once dirname(__DIR__, 3) . '/app/classes/ratelimiter.php';
|
|
require_once dirname(__DIR__, 3) . '/app/classes/log.php';
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class RateLimiterTest extends TestCase
|
|
{
|
|
private $db;
|
|
private $rateLimiter;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// Prepare DB for Github CI
|
|
$host = defined('CI_DB_HOST') ? CI_DB_HOST : '127.0.0.1';
|
|
$password = defined('CI_DB_PASSWORD') ? CI_DB_PASSWORD : '';
|
|
|
|
// Set up test database
|
|
$this->db = new Database([
|
|
'type' => 'mariadb',
|
|
'host' => $host,
|
|
'port' => '3306',
|
|
'dbname' => 'jilo_test',
|
|
'user' => 'test_jilo',
|
|
'password' => $password
|
|
]);
|
|
|
|
// The RateLimiter constructor will create all necessary tables
|
|
$this->rateLimiter = new RateLimiter($this->db);
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
// Drop tables in correct order
|
|
$this->db->getConnection()->exec("DROP TABLE IF EXISTS {$this->rateLimiter->authRatelimitTable}");
|
|
$this->db->getConnection()->exec("DROP TABLE IF EXISTS {$this->rateLimiter->pagesRatelimitTable}");
|
|
$this->db->getConnection()->exec("DROP TABLE IF EXISTS {$this->rateLimiter->blacklistTable}");
|
|
$this->db->getConnection()->exec("DROP TABLE IF EXISTS {$this->rateLimiter->whitelistTable}");
|
|
parent::tearDown();
|
|
}
|
|
|
|
public function testGetRecentAttempts()
|
|
{
|
|
$ip = '8.8.8.8';
|
|
|
|
// Record some login attempts
|
|
$stmt = $this->db->getConnection()->prepare("INSERT INTO {$this->rateLimiter->authRatelimitTable}
|
|
(ip_address, username, attempted_at) VALUES (?, ?, NOW())");
|
|
|
|
// Add 3 attempts
|
|
for ($i = 0; $i < 3; $i++) {
|
|
$stmt->execute([$ip, 'testuser']);
|
|
}
|
|
|
|
$attempts = $this->rateLimiter->getRecentAttempts($ip);
|
|
$this->assertEquals(3, $attempts);
|
|
}
|
|
|
|
public function testIsIpBlacklisted()
|
|
{
|
|
$ip = '8.8.8.8';
|
|
|
|
// Add IP to blacklist
|
|
$stmt = $this->db->getConnection()->prepare("INSERT INTO {$this->rateLimiter->blacklistTable}
|
|
(ip_address, is_network, reason) VALUES (?, ?, ?)");
|
|
$stmt->execute([$ip, 0, 'Test blacklist']); // Explicitly set is_network to 0 (false)
|
|
|
|
$this->assertTrue($this->rateLimiter->isIpBlacklisted($ip));
|
|
$this->assertFalse($this->rateLimiter->isIpBlacklisted('8.8.4.4'));
|
|
}
|
|
|
|
public function testIsIpWhitelisted()
|
|
{
|
|
// Test with an IP that's not in the default whitelisted ranges
|
|
$ip = '8.8.8.8'; // Google's DNS, definitely not in private ranges
|
|
|
|
// Add IP to whitelist
|
|
$stmt = $this->db->getConnection()->prepare("INSERT INTO {$this->rateLimiter->whitelistTable}
|
|
(ip_address, is_network, description) VALUES (?, ?, ?)");
|
|
$stmt->execute([$ip, 0, 'Test whitelist']); // Explicitly set is_network to 0 (false)
|
|
|
|
$this->assertTrue($this->rateLimiter->isIpWhitelisted($ip));
|
|
$this->assertFalse($this->rateLimiter->isIpWhitelisted('8.8.4.4')); // Another IP not in private ranges
|
|
}
|
|
|
|
public function testRateLimitCheck()
|
|
{
|
|
$ip = '8.8.8.8'; // Use non-whitelisted IP
|
|
$endpoint = '/test';
|
|
|
|
// First request should be allowed
|
|
$this->assertTrue($this->rateLimiter->isPageRequestAllowed($ip, $endpoint));
|
|
|
|
// Add requests up to the limit
|
|
for ($i = 0; $i < 60; $i++) { // Default limit is 60 per minute
|
|
$this->rateLimiter->recordPageRequest($ip, $endpoint);
|
|
}
|
|
|
|
// The next request should be rate limited
|
|
$this->assertFalse($this->rateLimiter->isPageRequestAllowed($ip, $endpoint));
|
|
}
|
|
}
|