Fixes errors in ratelimiter
							parent
							
								
									4182ba6c1b
								
							
						
					
					
						commit
						487c23da3e
					
				|  | @ -123,7 +123,20 @@ class RateLimiter { | |||
|      */ | ||||
|     public function isIpBlacklisted($ip) { | ||||
|         // First check if IP is explicitly blacklisted or in a blacklisted range
 | ||||
|         $stmt = $this->db->prepare("SELECT ip_address, is_network, expiry_time FROM {$this->blacklistTable}"); | ||||
|         $stmt = $this->db->prepare("SELECT ip_address, is_network, expiry_time FROM {$this->blacklistTable} WHERE ip_address = ?"); | ||||
|         $stmt->execute([$ip]); | ||||
|         $row = $stmt->fetch(PDO::FETCH_ASSOC); | ||||
| 
 | ||||
|         if ($row) { | ||||
|             // Skip expired entries
 | ||||
|             if ($row['expiry_time'] !== null && strtotime($row['expiry_time']) < time()) { | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         // Check network ranges
 | ||||
|         $stmt = $this->db->prepare("SELECT ip_address, expiry_time FROM {$this->blacklistTable} WHERE is_network = 1"); | ||||
|         $stmt->execute(); | ||||
| 
 | ||||
|         while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { | ||||
|  | @ -132,14 +145,8 @@ class RateLimiter { | |||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             if ($row['is_network']) { | ||||
|                 if ($this->ipInRange($ip, $row['ip_address'])) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } else { | ||||
|                 if ($ip === $row['ip_address']) { | ||||
|                     return true; | ||||
|                 } | ||||
|             if ($this->ipInRange($ip, $row['ip_address'])) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -307,6 +314,7 @@ class RateLimiter { | |||
| 
 | ||||
|             // Remove the IP
 | ||||
|             $stmt = $this->db->prepare("DELETE FROM {$this->blacklistTable} WHERE ip_address = ?"); | ||||
| 
 | ||||
|             $result = $stmt->execute([$ip]); | ||||
| 
 | ||||
|             if ($result && $ipDetails) { | ||||
|  | @ -495,12 +503,12 @@ class RateLimiter { | |||
|         // Get limit based on endpoint type and user role
 | ||||
|         $limit = $this->getPageLimitForEndpoint($endpoint, $userId); | ||||
| 
 | ||||
|         // Count recent requests
 | ||||
|         // Count recent requests, including this one
 | ||||
|         $sql = "SELECT COUNT(*) as request_count
 | ||||
|                 FROM {$this->pagesRatelimitTable} | ||||
|                 WHERE ip_address = :ip | ||||
|                 AND endpoint = :endpoint | ||||
|                 AND request_time > DATETIME('now', '-1 minute')";
 | ||||
|                 AND request_time >= DATETIME('now', '-1 minute')";
 | ||||
| 
 | ||||
|         $stmt = $this->db->prepare($sql); | ||||
|         $stmt->execute([ | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ require_once __DIR__ . '/../classes/ratelimiter.php'; | |||
|  */ | ||||
| function checkRateLimit($database, $endpoint, $userId = null) { | ||||
|     $isTest = defined('PHPUNIT_RUNNING'); | ||||
|     $rateLimiter = new RateLimiter($database['db']); | ||||
|     $rateLimiter = new RateLimiter($database); | ||||
|     $ipAddress = $_SERVER['REMOTE_ADDR']; | ||||
| 
 | ||||
|     // Check if request is allowed
 | ||||
|  |  | |||
|  | @ -19,11 +19,11 @@ unset($error); | |||
| try { | ||||
| 
 | ||||
|     // connect to database
 | ||||
|     $dbWeb = connectDB($config); | ||||
|     $dbWeb = connectDB($config)['db']; | ||||
| 
 | ||||
|     // Initialize RateLimiter
 | ||||
|     require_once '../app/classes/ratelimiter.php'; | ||||
|     $rateLimiter = new RateLimiter($dbWeb['db']); | ||||
|     $rateLimiter = new RateLimiter($dbWeb); | ||||
| 
 | ||||
|     if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) { | ||||
|         try { | ||||
|  | @ -54,8 +54,8 @@ try { | |||
|                 throw new Exception("Invalid input: " . implode(", ", $errors)); | ||||
|             } | ||||
| 
 | ||||
|             $username = $_POST['username']; | ||||
|             $password = $_POST['password']; | ||||
|             $username = $formData['username']; | ||||
|             $password = $formData['password']; | ||||
| 
 | ||||
|             // Check if IP is blacklisted
 | ||||
|             if ($rateLimiter->isIpBlacklisted($user_IP)) { | ||||
|  | @ -73,7 +73,7 @@ try { | |||
|             // login successful
 | ||||
|             if ( $userObject->login($username, $password) ) { | ||||
|                 // if remember_me is checked, max out the session
 | ||||
|                 if (isset($_POST['remember_me'])) { | ||||
|                 if (isset($formData['remember_me'])) { | ||||
|                     // 30*24*60*60 = 30 days
 | ||||
|                     $cookie_lifetime = 30 * 24 * 60 * 60; | ||||
|                     $setcookie_lifetime = time() + 30 * 24 * 60 * 60; | ||||
|  | @ -119,7 +119,7 @@ try { | |||
|                 $logObject->insertLog($user_id, "Login: User \"$username\" logged in. IP: $user_IP", 'user');
 | ||||
| 
 | ||||
|                 // Set success message and redirect
 | ||||
|                 Feedback::flash('LOGIN', 'LOGIN_SUCCESS', null, true); | ||||
|                 Feedback::flash('LOGIN', 'LOGIN_SUCCESS'); | ||||
|                 header('Location: ' . htmlspecialchars($app_root)); | ||||
|                 exit(); | ||||
|             } else { | ||||
|  | @ -140,7 +140,7 @@ try { | |||
| 
 | ||||
| // Show configured login message if any
 | ||||
| if (!empty($config['login_message'])) { | ||||
|     echo Feedback::render('NOTICE', 'DEFAULT', $config['login_message'], false, false, false); | ||||
|     echo Feedback::render('NOTICE', 'DEFAULT', $config['login_message'], false); | ||||
| } | ||||
| 
 | ||||
| // Get any new feedback messages
 | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ if ($config['registration_enabled'] == true) { | |||
|     try { | ||||
| 
 | ||||
|         // connect to database
 | ||||
|         $dbWeb = connectDB($config); | ||||
|         $dbWeb = connectDB($config)['db']; | ||||
| 
 | ||||
|         if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) { | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ require_once '../app/helpers/security.php'; | |||
| $security = SecurityHelper::getInstance(); | ||||
| 
 | ||||
| // Verify CSRF token for POST requests
 | ||||
| verifyCsrfToken(); | ||||
| applyCsrfMiddleware(); | ||||
| 
 | ||||
| // Initialize feedback message system
 | ||||
| require_once '../app/classes/feedback.php'; | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| 
 | ||||
| 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'; | ||||
| require_once dirname(__DIR__, 3) . '/app/includes/rate_limit_middleware.php'; | ||||
| 
 | ||||
| use PHPUnit\Framework\TestCase; | ||||
|  | @ -75,7 +76,7 @@ class RateLimitMiddlewareTest extends TestCase | |||
|     { | ||||
|         // Test multiple requests
 | ||||
|         for ($i = 1; $i <= 5; $i++) { | ||||
|             $result = checkRateLimit(['db' => $this->db], '/login'); | ||||
|             $result = checkRateLimit($this->db, '/login'); | ||||
| 
 | ||||
|             if ($i <= 5) { | ||||
|                 // First 5 requests should pass
 | ||||
|  | @ -91,7 +92,7 @@ class RateLimitMiddlewareTest extends TestCase | |||
|     { | ||||
|         // Test AJAX request bypass
 | ||||
|         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; | ||||
|         $result = checkRateLimit(['db' => $this->db], '/login'); | ||||
|         $result = checkRateLimit($this->db, '/login'); | ||||
|         $this->assertTrue($result); | ||||
|     } | ||||
| 
 | ||||
|  | @ -99,14 +100,14 @@ class RateLimitMiddlewareTest extends TestCase | |||
|     { | ||||
|         // Use up the rate limit
 | ||||
|         for ($i = 0; $i < 5; $i++) { | ||||
|             checkRateLimit(['db' => $this->db], '/login'); | ||||
|             checkRateLimit($this->db, '/login'); | ||||
|         } | ||||
| 
 | ||||
|         // Wait for rate limit to reset (use a short window for testing)
 | ||||
|         sleep(2); | ||||
| 
 | ||||
|         // Should be able to make request again
 | ||||
|         $result = checkRateLimit(['db' => $this->db], '/login'); | ||||
|         $result = checkRateLimit($this->db, '/login'); | ||||
|         $this->assertTrue($result); | ||||
|     } | ||||
| 
 | ||||
|  | @ -114,11 +115,11 @@ class RateLimitMiddlewareTest extends TestCase | |||
|     { | ||||
|         // Use up rate limit for login
 | ||||
|         for ($i = 0; $i < 5; $i++) { | ||||
|             checkRateLimit(['db' => $this->db], '/login'); | ||||
|             checkRateLimit($this->db, '/login'); | ||||
|         } | ||||
| 
 | ||||
|         // Should still be able to access different endpoint
 | ||||
|         $result = checkRateLimit(['db' => $this->db], '/dashboard'); | ||||
|         $result = checkRateLimit($this->db, '/dashboard'); | ||||
|         $this->assertTrue($result); | ||||
|     } | ||||
| 
 | ||||
|  | @ -127,12 +128,12 @@ class RateLimitMiddlewareTest extends TestCase | |||
|         // Use up rate limit for first IP
 | ||||
|         $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; | ||||
|         for ($i = 0; $i < 5; $i++) { | ||||
|             checkRateLimit(['db' => $this->db], '/login'); | ||||
|             checkRateLimit($this->db, '/login'); | ||||
|         } | ||||
| 
 | ||||
|         // Different IP should not be affected
 | ||||
|         $_SERVER['REMOTE_ADDR'] = '127.0.0.2'; | ||||
|         $result = checkRateLimit(['db' => $this->db], '/login'); | ||||
|         $result = checkRateLimit($this->db, '/login'); | ||||
|         $this->assertTrue($result); | ||||
|     } | ||||
| 
 | ||||
|  | @ -146,7 +147,7 @@ class RateLimitMiddlewareTest extends TestCase | |||
| 
 | ||||
|         // Should be able to make more requests than limit
 | ||||
|         for ($i = 0; $i < 10; $i++) { | ||||
|             $result = checkRateLimit(['db' => $this->db], '/login'); | ||||
|             $result = checkRateLimit($this->db, '/login'); | ||||
|             $this->assertTrue($result); | ||||
|         } | ||||
|     } | ||||
|  | @ -160,7 +161,7 @@ class RateLimitMiddlewareTest extends TestCase | |||
|         ); | ||||
| 
 | ||||
|         // Should be blocked immediately
 | ||||
|         $result = checkRateLimit(['db' => $this->db], '/login'); | ||||
|         $result = checkRateLimit($this->db, '/login'); | ||||
|         $this->assertFalse($result); | ||||
|     } | ||||
| 
 | ||||
|  | @ -168,7 +169,7 @@ class RateLimitMiddlewareTest extends TestCase | |||
|     { | ||||
|         // Use up some of the rate limit
 | ||||
|         for ($i = 0; $i < 2; $i++) { | ||||
|             checkRateLimit(['db' => $this->db], '/login'); | ||||
|             checkRateLimit($this->db, '/login'); | ||||
|         } | ||||
| 
 | ||||
|         // Destroy and restart session
 | ||||
|  | @ -176,7 +177,7 @@ class RateLimitMiddlewareTest extends TestCase | |||
|         //session_start();
 | ||||
| 
 | ||||
|         // Should still count previous requests
 | ||||
|         $result = checkRateLimit(['db' => $this->db], '/login'); | ||||
|         $result = checkRateLimit($this->db, '/login'); | ||||
|         $this->assertTrue($result); | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue