jilo-web/tests/Feature/Middleware/RateLimitMiddlewareTest.php

184 lines
5.4 KiB
PHP
Raw Permalink Normal View History

2025-02-19 13:31:01 +00:00
<?php
2025-02-20 08:41:14 +00:00
require_once dirname(__DIR__, 3) . '/app/classes/database.php';
require_once dirname(__DIR__, 3) . '/app/classes/ratelimiter.php';
2025-02-21 09:44:52 +00:00
require_once dirname(__DIR__, 3) . '/app/classes/log.php';
2025-02-20 08:41:14 +00:00
require_once dirname(__DIR__, 3) . '/app/includes/rate_limit_middleware.php';
2025-02-19 13:31:01 +00:00
use PHPUnit\Framework\TestCase;
class RateLimitMiddlewareTest extends TestCase
{
private $db;
private $rateLimiter;
protected function setUp(): void
{
parent::setUp();
// Set up test database
$this->db = new Database([
'type' => 'sqlite',
'dbFile' => ':memory:'
]);
// Create rate limiter table
$this->db->getConnection()->exec("CREATE TABLE pages_rate_limits (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip_address TEXT NOT NULL,
endpoint TEXT NOT NULL,
request_time DATETIME DEFAULT CURRENT_TIMESTAMP
)");
// Create ip_whitelist table
$this->db->getConnection()->exec("CREATE TABLE ip_whitelist (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip_address TEXT NOT NULL UNIQUE,
is_network BOOLEAN DEFAULT 0 CHECK(is_network IN (0,1)),
description TEXT,
created_at TEXT DEFAULT (DATETIME('now')),
created_by TEXT
)");
// Create ip_blacklist table
$this->db->getConnection()->exec("CREATE TABLE ip_blacklist (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip_address TEXT NOT NULL UNIQUE,
is_network BOOLEAN DEFAULT 0 CHECK(is_network IN (0,1)),
reason TEXT,
expiry_time TEXT NULL,
created_at TEXT DEFAULT (DATETIME('now')),
created_by TEXT
)");
$this->rateLimiter = new RateLimiter($this->db);
// Mock $_SERVER variables
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = '/login';
$_SERVER['REQUEST_METHOD'] = 'POST';
// Define testing constant
if (!defined('TESTING')) {
define('TESTING', true);
}
}
protected function tearDown(): void
{
// Clean up rate limit records
$this->db->getConnection()->exec('DELETE FROM pages_rate_limits');
parent::tearDown();
}
public function testRateLimitMiddleware()
{
// Test multiple requests
for ($i = 1; $i <= 5; $i++) {
2025-02-21 09:44:52 +00:00
$result = checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
if ($i <= 5) {
// First 5 requests should pass
$this->assertTrue($result);
} else {
// 6th and subsequent requests should be blocked
$this->assertFalse($result);
}
}
}
public function testRateLimitBypass()
{
// Test AJAX request bypass
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
2025-02-21 09:44:52 +00:00
$result = checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
$this->assertTrue($result);
}
public function testRateLimitReset()
{
// Use up the rate limit
for ($i = 0; $i < 5; $i++) {
2025-02-21 09:44:52 +00:00
checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
}
// Wait for rate limit to reset (use a short window for testing)
sleep(2);
// Should be able to make request again
2025-02-21 09:44:52 +00:00
$result = checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
$this->assertTrue($result);
}
public function testDifferentEndpoints()
{
// Use up rate limit for login
for ($i = 0; $i < 5; $i++) {
2025-02-21 09:44:52 +00:00
checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
}
// Should still be able to access different endpoint
2025-02-21 09:44:52 +00:00
$result = checkRateLimit($this->db, '/dashboard');
2025-02-19 13:31:01 +00:00
$this->assertTrue($result);
}
public function testDifferentIpAddresses()
{
// Use up rate limit for first IP
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
for ($i = 0; $i < 5; $i++) {
2025-02-21 09:44:52 +00:00
checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
}
// Different IP should not be affected
$_SERVER['REMOTE_ADDR'] = '127.0.0.2';
2025-02-21 09:44:52 +00:00
$result = checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
$this->assertTrue($result);
}
public function testWhitelistedIp()
{
// Add IP to whitelist
$this->db->execute(
'INSERT INTO ip_whitelist (ip_address, description, created_by) VALUES (?, ?, ?)',
['127.0.0.1', 'Test whitelist', 'PHPUnit']
);
// Should be able to make more requests than limit
for ($i = 0; $i < 10; $i++) {
2025-02-21 09:44:52 +00:00
$result = checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
$this->assertTrue($result);
}
}
public function testBlacklistedIp()
{
// Add IP to blacklist
$this->db->execute(
'INSERT INTO ip_blacklist (ip_address, reason, created_by) VALUES (?, ?, ?)',
['127.0.0.1', 'Test blacklist', 'PHPUnit']
);
// Should be blocked immediately
2025-02-21 09:44:52 +00:00
$result = checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
$this->assertFalse($result);
}
public function testRateLimitPersistence()
{
// Use up some of the rate limit
for ($i = 0; $i < 2; $i++) {
2025-02-21 09:44:52 +00:00
checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
}
// Destroy and restart session
//session_destroy();
//session_start();
// Should still count previous requests
2025-02-21 09:44:52 +00:00
$result = checkRateLimit($this->db, '/login');
2025-02-19 13:31:01 +00:00
$this->assertTrue($result);
}
}