iptv-stream-web/tests/unit/SecurityTest.php
Vincent 41cd7a4fd8 Add comprehensive unit tests for Security, UserModel, and Validation utilities
- Implemented SecurityTest to validate token generation, CSRF protection, input sanitization, and rate limiting.
- Created UserModelTest to ensure correct database operations for user management, including creation, updating, banning, and fetching active users.
- Developed ValidationTest to verify input validation and sanitization for user IDs, nicknames, messages, and API requests.
- Introduced Security and Validation utility classes with methods for secure token generation, input sanitization, and comprehensive validation rules.
2025-09-30 21:22:28 -04:00

187 lines
6.2 KiB
PHP

<?php
use PHPUnit\Framework\TestCase;
/**
* Test Security utility functions
*/
class SecurityTest extends TestCase
{
protected function setUp(): void
{
// Clear any previous session data
$_SESSION = [];
$_POST = [];
$_GET = [];
}
public function testGenerateSecureToken()
{
$token1 = Security::generateSecureToken(16);
$token2 = Security::generateSecureToken(16);
// Test length
$this->assertEquals(32, strlen($token1)); // 16 bytes = 32 hex chars
$this->assertEquals(32, strlen($token2));
// Test uniqueness
$this->assertNotEquals($token1, $token2);
// Test valid hex characters
$this->assertMatchesRegularExpression('/^[a-f0-9]+$/', $token1);
$this->assertMatchesRegularExpression('/^[a-f0-9]+$/', $token2);
}
public function testGenerateSecureUserId()
{
$userId1 = Security::generateSecureUserId();
$userId2 = Security::generateSecureUserId();
// Test format (32 char hex)
$this->assertEquals(32, strlen($userId1));
$this->assertEquals(32, strlen($userId2));
// Test uniqueness
$this->assertNotEquals($userId1, $userId2);
// Test valid characters
$this->assertMatchesRegularExpression('/^[a-f0-9]+$/', $userId1);
$this->assertMatchesRegularExpression('/^[a-f0-9]+$/', $userId2);
}
public function testGetClientIP()
{
// Test with default server vars
$ip = Security::getClientIP();
$this->assertEquals('127.0.0.1', $ip);
// Test with forwarded headers
$_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.1.100, 10.0.0.1';
$ip = Security::getClientIP();
$this->assertEquals('192.168.1.100', $ip);
// Test with real IP header
$_SERVER['HTTP_X_REAL_IP'] = '203.0.113.1';
unset($_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = Security::getClientIP();
$this->assertEquals('203.0.113.1', $ip);
}
public function testSanitizeInput()
{
// Test string sanitization
$input = '<script>alert("xss")</script>Hello World';
$result = Security::sanitizeInput($input, 'string');
$this->assertEquals('alert("xss")Hello World', $result);
// Test email sanitization
$email = 'test@example.com<script>evil</script>';
$result = Security::sanitizeInput($email, 'email');
$this->assertEquals('test@example.com<script>evil</script>', $result);
// Test URL sanitization
$url = 'http://example.com/path<script>evil</script>';
$result = Security::sanitizeInput($url, 'url');
$this->assertEquals('http://example.com/path', $result); // Scripts should be stripped
}
public function testValidateCSRFToken()
{
// Generate a token
$token = Security::generateCSRFToken();
$_SESSION['csrf_token'] = $token;
// Test valid token
$this->assertTrue(Security::validateCSRFToken($token));
// Test invalid token
$this->assertFalse(Security::validateCSRFToken('invalid_token'));
// Test missing token
$this->assertFalse(Security::validateCSRFToken(''));
}
public function testCheckRateLimit()
{
$ip = '192.168.1.100';
// First request should succeed
$result1 = Security::checkRateLimit($ip, 'test_action', 3, 60);
$this->assertTrue($result1);
// Second request should succeed
$result2 = Security::checkRateLimit($ip, 'test_action', 3, 60);
$this->assertTrue($result2);
// Third request should succeed
$result3 = Security::checkRateLimit($ip, 'test_action', 3, 60);
$this->assertTrue($result3);
// Fourth request should fail (over limit)
$result4 = Security::checkRateLimit($ip, 'test_action', 3, 60);
$this->assertFalse($result4);
}
public function testIsValidStreamUrl()
{
// Valid URLs
$this->assertTrue(Security::isValidStreamUrl('http://127.0.0.1:8080/stream'));
$this->assertTrue(Security::isValidStreamUrl('https://127.0.0.1:8080/stream'));
$this->assertTrue(Security::isValidStreamUrl('http://localhost:8080/stream'));
// Invalid URLs
$this->assertFalse(Security::isValidStreamUrl('http://evil.com/stream'));
$this->assertFalse(Security::isValidStreamUrl('http://192.168.1.1/stream'));
$this->assertFalse(Security::isValidStreamUrl('javascript:alert(1)'));
$this->assertFalse(Security::isValidStreamUrl(''));
}
public function testAdminAuthentication()
{
// Test without any auth setup
$this->assertFalse(Security::isAdminAuthenticated());
// Set up session auth
$_SESSION['admin_authenticated'] = true;
$_SESSION['admin_login_time'] = time();
$this->assertTrue(Security::isAdminAuthenticated());
}
public function testAuthenticateAdmin()
{
// This would need proper config setup for real testing
// For now, test that the method exists and handles failures
$result = Security::authenticateAdmin('invalid_user', 'invalid_pass');
$this->assertFalse($result);
}
public function testDetectSuspiciousActivity()
{
// Test with normal request
$warnings = Security::detectSuspiciousActivity();
$this->assertIsArray($warnings);
// Test with suspicious user agent
$_SERVER['HTTP_USER_AGENT'] = 'sqlmap';
$warnings = Security::detectSuspiciousActivity();
$this->assertContains('Suspicious user agent detected', $warnings);
// Reset
$_SERVER['HTTP_USER_AGENT'] = 'PHPUnit/Test';
}
public function testLogSecurityEvent()
{
// Start output buffering to capture logs
ob_start();
// Generate a security event
Security::logSecurityEvent('test_event', ['test_data' => 'value']);
// The actual logging happens in ErrorHandler, so we test that no exceptions are thrown
$this->assertTrue(true);
ob_end_clean();
}
}