Files
easystream-main/tests/Unit/RBACTest.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

448 lines
16 KiB
PHP

<?php
namespace EasyStream\Tests\Unit;
use PHPUnit\Framework\TestCase;
use VRBAC;
use VAuth;
class RBACTest extends TestCase
{
private $rbac;
private $auth;
private $testUserId;
private $adminUserId;
protected function setUp(): void
{
$this->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);
}
}