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); } }