rbac = VRBAC::getInstance(); $this->auth = VAuth::getInstance(); // Clear session data if (isset($_SESSION)) { $_SESSION = []; } // Mock server variables $_SERVER = [ 'REQUEST_URI' => '/test', 'REQUEST_METHOD' => 'GET', 'HTTP_USER_AGENT' => 'PHPUnit RBAC Test', 'REMOTE_ADDR' => '127.0.0.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 = ['rbactest@example.com', 'rbacadmin@example.com', 'rbacmember@example.com']; $testUsernames = ['rbactest', 'rbacadmin', 'rbacmember']; 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_users WHERE user_id = ?", [$userId]); } } } private function createTestUsers() { // Create regular test user $userData = [ 'username' => 'rbactest', 'email' => 'rbactest@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(); $db->Execute("UPDATE db_users SET email_verified = 1 WHERE user_id = ?", [$this->testUserId]); } // Create admin test user $adminData = [ 'username' => 'rbacadmin', 'email' => 'rbacadmin@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(); $db->Execute("UPDATE db_users SET role = 'admin', email_verified = 1 WHERE user_id = ?", [$this->adminUserId]); } } /** * Test RBAC singleton pattern */ public function testSingletonPattern() { $rbac1 = VRBAC::getInstance(); $rbac2 = VRBAC::getInstance(); $this->assertSame($rbac1, $rbac2); $this->assertInstanceOf(VRBAC::class, $rbac1); } /** * Test role hierarchy */ public function testRoleHierarchy() { // Test role levels $this->assertTrue($this->rbac->hasRole('guest', $this->testUserId)); $this->assertTrue($this->rbac->hasRole('member', $this->testUserId)); $this->assertFalse($this->rbac->hasRole('admin', $this->testUserId)); $this->assertTrue($this->rbac->hasRole('guest', $this->adminUserId)); $this->assertTrue($this->rbac->hasRole('member', $this->adminUserId)); $this->assertTrue($this->rbac->hasRole('admin', $this->adminUserId)); } /** * Test basic permission checking */ public function testBasicPermissions() { // Test member permissions $this->assertTrue($this->rbac->hasPermission('content.view', $this->testUserId)); $this->assertTrue($this->rbac->hasPermission('content.create', $this->testUserId)); $this->assertFalse($this->rbac->hasPermission('admin.dashboard', $this->testUserId)); // Test admin permissions $this->assertTrue($this->rbac->hasPermission('content.view', $this->adminUserId)); $this->assertTrue($this->rbac->hasPermission('admin.dashboard', $this->adminUserId)); $this->assertTrue($this->rbac->hasPermission('user.ban', $this->adminUserId)); } /** * Test guest permissions */ public function testGuestPermissions() { // Test guest permissions without user ID (not logged in) $this->assertTrue($this->rbac->hasPermission('content.view')); $this->assertTrue($this->rbac->hasPermission('comment.view')); $this->assertFalse($this->rbac->hasPermission('content.create')); $this->assertFalse($this->rbac->hasPermission('admin.dashboard')); } /** * Test custom user permissions */ public function testCustomUserPermissions() { // Grant custom permission $result = $this->rbac->grantPermission($this->testUserId, 'feature.beta', $this->adminUserId); $this->assertTrue($result); // Test custom permission $this->assertTrue($this->rbac->hasPermission('feature.beta', $this->testUserId)); // Revoke custom permission $revokeResult = $this->rbac->revokePermission($this->testUserId, 'feature.beta', $this->adminUserId); $this->assertTrue($revokeResult); // Test permission is revoked $this->assertFalse($this->rbac->hasPermission('feature.beta', $this->testUserId)); } /** * Test permission expiration */ public function testPermissionExpiration() { // Grant permission with expiration $expiresAt = date('Y-m-d H:i:s', time() + 3600); // 1 hour from now $result = $this->rbac->grantPermission($this->testUserId, 'upload.large_files', $this->adminUserId, $expiresAt); $this->assertTrue($result); // Test permission is active $this->assertTrue($this->rbac->hasPermission('upload.large_files', $this->testUserId)); // Test with expired permission (simulate by setting past date) global $class_database; $db = $class_database->dbConnection(); $db->Execute("UPDATE db_user_permissions SET expires_at = ? WHERE user_id = ? AND permission = ?", [date('Y-m-d H:i:s', time() - 3600), $this->testUserId, 'upload.large_files']); // Test permission is expired $this->assertFalse($this->rbac->hasPermission('upload.large_files', $this->testUserId)); } /** * Test multiple permission checking */ public function testMultiplePermissions() { $permissions = ['content.view', 'content.create', 'comment.create']; // Test hasAnyPermission $this->assertTrue($this->rbac->hasAnyPermission($permissions, $this->testUserId)); $this->assertTrue($this->rbac->hasAnyPermission(['admin.dashboard', 'content.view'], $this->testUserId)); $this->assertFalse($this->rbac->hasAnyPermission(['admin.dashboard', 'admin.system'], $this->testUserId)); // Test hasAllPermissions $this->assertTrue($this->rbac->hasAllPermissions($permissions, $this->testUserId)); $this->assertFalse($this->rbac->hasAllPermissions(['content.view', 'admin.dashboard'], $this->testUserId)); } /** * Test role changes */ public function testRoleChanges() { // Change user role $result = $this->rbac->changeUserRole($this->testUserId, 'verified', $this->adminUserId, 'Test role change'); $this->assertTrue($result); // Test new role permissions $this->assertTrue($this->rbac->hasRole('verified', $this->testUserId)); $this->assertTrue($this->rbac->hasPermission('content.publish', $this->testUserId)); // Test invalid role change $invalidResult = $this->rbac->changeUserRole($this->testUserId, 'invalid_role', $this->adminUserId); $this->assertFalse($invalidResult); } /** * Test user suspension */ public function testUserSuspension() { // Suspend user $result = $this->rbac->suspendUser($this->testUserId, 'Test suspension', $this->adminUserId); $this->assertTrue($result); // Test suspended user has no permissions $this->assertFalse($this->rbac->hasPermission('content.view', $this->testUserId)); $this->assertFalse($this->rbac->hasPermission('content.create', $this->testUserId)); // Reinstate user $reinstateResult = $this->rbac->reinstateUser($this->testUserId, 'Test reinstatement', $this->adminUserId); $this->assertTrue($reinstateResult); // Test reinstated user has permissions again $this->assertTrue($this->rbac->hasPermission('content.view', $this->testUserId)); $this->assertTrue($this->rbac->hasPermission('content.create', $this->testUserId)); } /** * Test user banning */ public function testUserBanning() { // Ban user $result = $this->rbac->banUser($this->testUserId, 'Test ban', $this->adminUserId, false); $this->assertTrue($result); // Test banned user has no permissions $this->assertFalse($this->rbac->hasPermission('content.view', $this->testUserId)); $this->assertFalse($this->rbac->hasRole('member', $this->testUserId)); // Reinstate user $reinstateResult = $this->rbac->reinstateUser($this->testUserId, 'Test unban', $this->adminUserId); $this->assertTrue($reinstateResult); // Test unbanned user has permissions again $this->assertTrue($this->rbac->hasPermission('content.view', $this->testUserId)); } /** * Test context-based permissions */ public function testContextPermissions() { // Test content ownership context $context = ['content_owner_id' => $this->testUserId]; // User should be able to edit their own content $this->assertTrue($this->rbac->hasPermission('content.edit', $this->testUserId, $context)); $this->assertTrue($this->rbac->hasPermission('content.delete', $this->testUserId, $context)); // User should not be able to edit others' content without permission $otherContext = ['content_owner_id' => $this->adminUserId]; $this->assertFalse($this->rbac->hasPermission('content.moderate', $this->testUserId, $otherContext)); } /** * Test permission middleware */ public function testPermissionMiddleware() { // Mock current user session $_SESSION['USER_ID'] = $this->testUserId; $_SESSION['USERNAME'] = 'rbactest'; $_SESSION['EMAIL'] = 'rbactest@example.com'; $_SESSION['ROLE'] = 'member'; $_SESSION['LOGIN_TIME'] = time(); $_SESSION['LAST_ACTIVITY'] = time(); // Test successful permission check $this->expectOutputString(''); // No output expected for successful check ob_start(); $result = $this->rbac->requirePermission('content.view'); $output = ob_get_clean(); $this->assertTrue($result); $this->assertEmpty($output); // Clear session for next test $_SESSION = []; } /** * Test role middleware */ public function testRoleMiddleware() { // Mock current user session $_SESSION['USER_ID'] = $this->adminUserId; $_SESSION['USERNAME'] = 'rbacadmin'; $_SESSION['EMAIL'] = 'rbacadmin@example.com'; $_SESSION['ROLE'] = 'admin'; $_SESSION['LOGIN_TIME'] = time(); $_SESSION['LAST_ACTIVITY'] = time(); // Test successful role check $this->expectOutputString(''); // No output expected for successful check ob_start(); $result = $this->rbac->requireRole('admin'); $output = ob_get_clean(); $this->assertTrue($result); $this->assertEmpty($output); // Clear session $_SESSION = []; } /** * Test getting user permissions */ public function testGetUserPermissions() { $permissions = $this->rbac->getUserPermissions($this->testUserId); $this->assertIsArray($permissions); $this->assertContains('content.view', $permissions); $this->assertContains('content.create', $permissions); $this->assertNotContains('admin.dashboard', $permissions); // Test admin permissions $adminPermissions = $this->rbac->getUserPermissions($this->adminUserId); $this->assertContains('admin.dashboard', $adminPermissions); $this->assertContains('user.ban', $adminPermissions); } /** * Test getting role permissions */ public function testGetRolePermissions() { $memberPermissions = $this->rbac->getRolePermissions('member'); $this->assertIsArray($memberPermissions); $this->assertContains('content.view', $memberPermissions); $this->assertContains('content.create', $memberPermissions); $adminPermissions = $this->rbac->getRolePermissions('admin'); $this->assertContains('admin.dashboard', $adminPermissions); $this->assertContains('user.ban', $adminPermissions); $guestPermissions = $this->rbac->getRolePermissions('guest'); $this->assertContains('content.view', $guestPermissions); $this->assertNotContains('content.create', $guestPermissions); } /** * Test permission validation edge cases */ public function testPermissionEdgeCases() { // Test with non-existent user $this->assertFalse($this->rbac->hasPermission('content.view', 99999)); // Test with invalid permission $this->assertFalse($this->rbac->hasPermission('invalid.permission', $this->testUserId)); // Test with null user ID and no session $this->assertTrue($this->rbac->hasPermission('content.view')); // Should check guest permissions // Test with empty permission $this->assertFalse($this->rbac->hasPermission('', $this->testUserId)); } /** * Test permission caching */ public function testPermissionCaching() { // First call should query database $permissions1 = $this->rbac->getUserPermissions($this->testUserId); // Second call should use cache $permissions2 = $this->rbac->getUserPermissions($this->testUserId); $this->assertEquals($permissions1, $permissions2); // Grant new permission (should clear cache) $this->rbac->grantPermission($this->testUserId, 'feature.beta', $this->adminUserId); // Should get updated permissions $permissions3 = $this->rbac->getUserPermissions($this->testUserId); $this->assertContains('feature.beta', $permissions3); } /** * Test error handling */ public function testErrorHandling() { // Test with invalid parameters $result = $this->rbac->grantPermission(null, 'test.permission', $this->adminUserId); $this->assertFalse($result); $result = $this->rbac->changeUserRole($this->testUserId, null, $this->adminUserId); $this->assertFalse($result); $result = $this->rbac->suspendUser(null, 'test', $this->adminUserId); $this->assertFalse($result); } }