Files
easystream-main/tests/Integration/AuthIntegrationTest.php
SamiAhmed7777 0b7e2d0a5b feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory
- Added PROJECT_OVERVIEW.md with feature highlights and getting started guide
- Added ARCHITECTURE.md with system design and technical details
- Added SECURITY.md with comprehensive security implementation guide
- Added DEVELOPMENT.md with development workflows and best practices
- Added DEPLOYMENT.md with production deployment instructions
- Added API.md with complete REST API documentation
- Added CONTRIBUTING.md with contribution guidelines
- Added CHANGELOG.md with version history and migration notes
- Reorganized all documentation files into docs/ directory for better organization
- Updated README.md with proper documentation links and quick navigation
- Enhanced project structure with professional documentation standards
2025-10-21 00:39:45 -07:00

523 lines
18 KiB
PHP

<?php
namespace EasyStream\Tests\Integration;
use PHPUnit\Framework\TestCase;
use VAuth;
use VRBAC;
use VMiddleware;
class AuthIntegrationTest extends TestCase
{
private $auth;
private $rbac;
private $middleware;
private $testUserId;
private $adminUserId;
protected function setUp(): void
{
$this->auth = VAuth::getInstance();
$this->rbac = VRBAC::getInstance();
$this->middleware = VMiddleware::getInstance();
// Clear session data
if (isset($_SESSION)) {
$_SESSION = [];
}
// Mock server variables
$_SERVER = [
'REQUEST_URI' => '/test',
'REQUEST_METHOD' => 'POST',
'HTTP_USER_AGENT' => 'PHPUnit Integration Test',
'REMOTE_ADDR' => '127.0.0.1',
'HTTPS' => '1',
'HTTP_ACCEPT' => 'text/html'
];
// Clean up any existing test data
$this->cleanupTestData();
// Create test users
$this->createTestUsers();
}
protected function tearDown(): void
{
// Clean up test data
$this->cleanupTestData();
// Clear session
if (isset($_SESSION)) {
$_SESSION = [];
}
}
private function cleanupTestData()
{
global $class_database;
$db = $class_database->dbConnection();
// Clean up test users and related data
$testEmails = ['authint@example.com', 'authintadmin@example.com'];
foreach ($testEmails as $email) {
$userId = $db->GetOne("SELECT user_id FROM db_users WHERE email = ?", [$email]);
if ($userId) {
$db->Execute("DELETE FROM db_user_permissions WHERE user_id = ?", [$userId]);
$db->Execute("DELETE FROM db_role_history WHERE user_id = ?", [$userId]);
$db->Execute("DELETE FROM db_user_suspensions WHERE user_id = ?", [$userId]);
$db->Execute("DELETE FROM db_user_bans WHERE user_id = ?", [$userId]);
$db->Execute("DELETE FROM db_sessions WHERE user_id = ?", [$userId]);
$db->Execute("DELETE FROM db_login_history WHERE user_id = ?", [$userId]);
$db->Execute("DELETE FROM db_users WHERE user_id = ?", [$userId]);
}
}
}
private function createTestUsers()
{
// Create regular test user
$userData = [
'username' => 'authinttest',
'email' => 'authint@example.com',
'password' => 'TestPassword123!'
];
$result = $this->auth->register($userData);
if ($result['success']) {
$this->testUserId = $result['user_id'];
// Verify email
global $class_database;
$db = $class_database->dbConnection();
$token = $db->GetOne("SELECT verification_token FROM db_users WHERE user_id = ?", [$this->testUserId]);
if ($token) {
$this->auth->verifyEmail($token);
}
}
// Create admin test user
$adminData = [
'username' => 'authintadmin',
'email' => 'authintadmin@example.com',
'password' => 'AdminPassword123!'
];
$adminResult = $this->auth->register($adminData);
if ($adminResult['success']) {
$this->adminUserId = $adminResult['user_id'];
// Set as admin and verify
global $class_database;
$db = $class_database->dbConnection();
$token = $db->GetOne("SELECT verification_token FROM db_users WHERE user_id = ?", [$this->adminUserId]);
if ($token) {
$this->auth->verifyEmail($token);
}
$db->Execute("UPDATE db_users SET role = 'admin' WHERE user_id = ?", [$this->adminUserId]);
}
}
/**
* Test complete user registration and verification workflow
*/
public function testCompleteRegistrationWorkflow()
{
// Test registration
$userData = [
'username' => 'newuser',
'email' => 'newuser@example.com',
'password' => 'NewPassword123!'
];
$result = $this->auth->register($userData);
$this->assertTrue($result['success']);
$this->assertArrayHasKey('user_id', $result);
$userId = $result['user_id'];
// Test user exists in database
global $class_database;
$db = $class_database->dbConnection();
$userExists = $db->GetOne("SELECT COUNT(*) FROM db_users WHERE user_id = ?", [$userId]);
$this->assertEquals(1, $userExists);
// Test email is not verified initially
$emailVerified = $db->GetOne("SELECT email_verified FROM db_users WHERE user_id = ?", [$userId]);
$this->assertEquals(0, $emailVerified);
// Get verification token
$token = $db->GetOne("SELECT verification_token FROM db_users WHERE user_id = ?", [$userId]);
$this->assertNotEmpty($token);
// Test email verification
$verifyResult = $this->auth->verifyEmail($token);
$this->assertTrue($verifyResult['success']);
// Test email is now verified
$emailVerified = $db->GetOne("SELECT email_verified FROM db_users WHERE user_id = ?", [$userId]);
$this->assertEquals(1, $emailVerified);
// Test token is cleared
$tokenAfter = $db->GetOne("SELECT verification_token FROM db_users WHERE user_id = ?", [$userId]);
$this->assertNull($tokenAfter);
// Clean up
$db->Execute("DELETE FROM db_users WHERE user_id = ?", [$userId]);
}
/**
* Test complete login and session workflow
*/
public function testCompleteLoginWorkflow()
{
// Test login
$result = $this->auth->login('authinttest', 'TestPassword123!');
$this->assertTrue($result['success']);
$this->assertArrayHasKey('user', $result);
// Test session is created
$this->assertTrue($this->auth->isAuthenticated());
$currentUser = $this->auth->getCurrentUser();
$this->assertNotNull($currentUser);
$this->assertEquals('authinttest', $currentUser['username']);
// Test session exists in database
global $class_database;
$db = $class_database->dbConnection();
$sessionExists = $db->GetOne("SELECT COUNT(*) FROM db_sessions WHERE user_id = ?", [$this->testUserId]);
$this->assertGreaterThan(0, $sessionExists);
// Test logout
$logoutResult = $this->auth->logout();
$this->assertTrue($logoutResult['success']);
// Test session is destroyed
$this->assertFalse($this->auth->isAuthenticated());
$this->assertNull($this->auth->getCurrentUser());
// Test session is removed from database
$sessionExists = $db->GetOne("SELECT COUNT(*) FROM db_sessions WHERE user_id = ?", [$this->testUserId]);
$this->assertEquals(0, $sessionExists);
}
/**
* Test authentication with RBAC integration
*/
public function testAuthRBACIntegration()
{
// Login as regular user
$this->auth->login('authinttest', 'TestPassword123!');
// Test basic permissions
$this->assertTrue($this->rbac->hasPermission('content.view'));
$this->assertTrue($this->rbac->hasPermission('content.create'));
$this->assertFalse($this->rbac->hasPermission('admin.dashboard'));
// Logout and login as admin
$this->auth->logout();
$this->auth->login('authintadmin', 'AdminPassword123!');
// Test admin permissions
$this->assertTrue($this->rbac->hasPermission('admin.dashboard'));
$this->assertTrue($this->rbac->hasPermission('user.ban'));
$this->assertTrue($this->rbac->hasRole('admin'));
$this->auth->logout();
}
/**
* Test middleware integration with authentication
*/
public function testMiddlewareAuthIntegration()
{
// Test unauthenticated access
$this->expectOutputRegex('/Location:/');
ob_start();
$result = $this->middleware->requireAuth();
ob_end_clean();
$this->assertFalse($result);
// Login user
$this->auth->login('authinttest', 'TestPassword123!');
// Test authenticated access
ob_start();
$result = $this->middleware->requireAuth();
$output = ob_get_clean();
$this->assertTrue($result);
$this->assertEmpty($output);
// Test role requirement
ob_start();
$result = $this->middleware->requireRole('member');
$output = ob_get_clean();
$this->assertTrue($result);
$this->assertEmpty($output);
// Test permission requirement
ob_start();
$result = $this->middleware->requirePermission('content.create');
$output = ob_get_clean();
$this->assertTrue($result);
$this->assertEmpty($output);
$this->auth->logout();
}
/**
* Test password reset workflow
*/
public function testPasswordResetWorkflow()
{
// Request password reset
$result = $this->auth->requestPasswordReset('authint@example.com');
$this->assertTrue($result['success']);
// Get reset token from database
global $class_database;
$db = $class_database->dbConnection();
$token = $db->GetOne("SELECT reset_token FROM db_users WHERE user_id = ?", [$this->testUserId]);
$this->assertNotEmpty($token);
// Test password reset
$newPassword = 'NewPassword456!';
$resetResult = $this->auth->resetPassword($token, $newPassword);
$this->assertTrue($resetResult['success']);
// Test old password no longer works
$oldLoginResult = $this->auth->login('authinttest', 'TestPassword123!');
$this->assertFalse($oldLoginResult['success']);
// Test new password works
$newLoginResult = $this->auth->login('authinttest', $newPassword);
$this->assertTrue($newLoginResult['success']);
// Test token is cleared
$tokenAfter = $db->GetOne("SELECT reset_token FROM db_users WHERE user_id = ?", [$this->testUserId]);
$this->assertNull($tokenAfter);
$this->auth->logout();
}
/**
* Test user suspension integration
*/
public function testUserSuspensionIntegration()
{
// Login as admin
$this->auth->login('authintadmin', 'AdminPassword123!');
// Suspend the test user
$result = $this->rbac->suspendUser($this->testUserId, 'Test suspension', $this->adminUserId);
$this->assertTrue($result);
$this->auth->logout();
// Try to login as suspended user
$loginResult = $this->auth->login('authinttest', 'TestPassword123!');
$this->assertFalse($loginResult['success']);
$this->assertStringContainsString('not active', $loginResult['message']);
// Reinstate user
$this->auth->login('authintadmin', 'AdminPassword123!');
$reinstateResult = $this->rbac->reinstateUser($this->testUserId, 'Test reinstatement', $this->adminUserId);
$this->assertTrue($reinstateResult);
$this->auth->logout();
// Test user can login again
$loginResult = $this->auth->login('authinttest', 'TestPassword123!');
$this->assertTrue($loginResult['success']);
$this->auth->logout();
}
/**
* Test session timeout and cleanup
*/
public function testSessionTimeoutAndCleanup()
{
// Login user
$this->auth->login('authinttest', 'TestPassword123!');
$this->assertTrue($this->auth->isAuthenticated());
// Simulate session timeout by modifying last activity
$_SESSION['LAST_ACTIVITY'] = time() - 7200; // 2 hours ago
// Test session is expired
$this->assertFalse($this->auth->isAuthenticated());
// Test session data is cleared
$this->assertNull($this->auth->getCurrentUser());
}
/**
* Test concurrent sessions
*/
public function testConcurrentSessions()
{
// Login user
$this->auth->login('authinttest', 'TestPassword123!');
$sessionId1 = session_id();
// Simulate second session
session_write_close();
session_id('test_session_2');
session_start();
// Login same user in second session
$this->auth->login('authinttest', 'TestPassword123!');
$sessionId2 = session_id();
$this->assertNotEquals($sessionId1, $sessionId2);
// Test both sessions exist in database
global $class_database;
$db = $class_database->dbConnection();
$sessionCount = $db->GetOne("SELECT COUNT(*) FROM db_sessions WHERE user_id = ?", [$this->testUserId]);
$this->assertGreaterThanOrEqual(1, $sessionCount);
// Logout from current session
$this->auth->logout();
}
/**
* Test remember me functionality
*/
public function testRememberMeFunctionality()
{
// Login with remember me
$result = $this->auth->login('authinttest', 'TestPassword123!', true);
$this->assertTrue($result['success']);
// Test remember token is set in database
global $class_database;
$db = $class_database->dbConnection();
$rememberToken = $db->GetOne("SELECT remember_token FROM db_users WHERE user_id = ?", [$this->testUserId]);
$this->assertNotNull($rememberToken);
// Test session is marked as remember me
$rememberMe = $db->GetOne("SELECT remember_me FROM db_sessions WHERE user_id = ?", [$this->testUserId]);
$this->assertEquals(1, $rememberMe);
// Logout
$this->auth->logout();
// Test remember token is cleared
$rememberToken = $db->GetOne("SELECT remember_token FROM db_users WHERE user_id = ?", [$this->testUserId]);
$this->assertNull($rememberToken);
}
/**
* Test email verification requirement
*/
public function testEmailVerificationRequirement()
{
// Create unverified user
$userData = [
'username' => 'unverified',
'email' => 'unverified@example.com',
'password' => 'TestPassword123!'
];
$result = $this->auth->register($userData);
$this->assertTrue($result['success']);
$userId = $result['user_id'];
// Try to login without verification (should fail if verification required)
global $cfg;
$cfg['require_email_verification'] = true;
$loginResult = $this->auth->login('unverified', 'TestPassword123!');
$this->assertFalse($loginResult['success']);
$this->assertStringContainsString('verify', $loginResult['message']);
// Clean up
global $class_database;
$db = $class_database->dbConnection();
$db->Execute("DELETE FROM db_users WHERE user_id = ?", [$userId]);
}
/**
* Test rate limiting integration
*/
public function testRateLimitingIntegration()
{
// Make multiple failed login attempts
for ($i = 0; $i < 6; $i++) {
$result = $this->auth->login('authinttest', 'WrongPassword');
if ($i < 5) {
$this->assertFalse($result['success']);
$this->assertStringContainsString('Invalid credentials', $result['message']);
} else {
// 6th attempt should be rate limited
$this->assertFalse($result['success']);
$this->assertStringContainsString('Too many', $result['message']);
}
}
// Even correct password should be rate limited now
$result = $this->auth->login('authinttest', 'TestPassword123!');
$this->assertFalse($result['success']);
$this->assertStringContainsString('Too many', $result['message']);
}
/**
* Test database transaction integrity
*/
public function testDatabaseTransactionIntegrity()
{
global $class_database;
$db = $class_database->dbConnection();
// Count initial users
$initialCount = $db->GetOne("SELECT COUNT(*) FROM db_users");
// Try to register with invalid data (should not create partial records)
$userData = [
'username' => 'testuser',
'email' => 'invalid-email', // Invalid email
'password' => 'TestPassword123!'
];
$result = $this->auth->register($userData);
$this->assertFalse($result['success']);
// Count should be unchanged
$finalCount = $db->GetOne("SELECT COUNT(*) FROM db_users");
$this->assertEquals($initialCount, $finalCount);
}
/**
* Test authentication state consistency
*/
public function testAuthenticationStateConsistency()
{
// Login user
$this->auth->login('authinttest', 'TestPassword123!');
// Test all authentication state methods are consistent
$this->assertTrue($this->auth->isAuthenticated());
$this->assertNotNull($this->auth->getCurrentUser());
$currentUser = $this->auth->getCurrentUser();
$this->assertEquals($this->testUserId, $currentUser['user_id']);
$this->assertEquals('authinttest', $currentUser['username']);
// Test session variables are set correctly
$this->assertEquals($this->testUserId, $_SESSION['USER_ID']);
$this->assertEquals('authinttest', $_SESSION['USERNAME']);
$this->assertArrayHasKey('LOGIN_TIME', $_SESSION);
$this->assertArrayHasKey('SESSION_TOKEN', $_SESSION);
$this->auth->logout();
// Test all state is cleared after logout
$this->assertFalse($this->auth->isAuthenticated());
$this->assertNull($this->auth->getCurrentUser());
$this->assertArrayNotHasKey('USER_ID', $_SESSION);
}
}