$type, 'message' => $message]; header("Location: {$url}"); exit; }; if (!admin_validate_csrf('admin_users', $token)) { $setFlashAndRedirect('error', 'Invalid session token. Please try again.', $redirectUrl); } if ($userId <= 0 || !admin_user_exists($pdo, $userId)) { $setFlashAndRedirect('error', 'The selected user could not be found.', $redirectUrl); } $adminId = $_SESSION['ADMIN_ID'] ?? ($_SESSION['admin_id'] ?? null); try { switch ($action) { case 'assign_role': { $roleName = trim($_POST['role_name'] ?? ''); if ($roleName === '' || !isset($roleLookup[$roleName])) { throw new InvalidArgumentException('Please select a valid role to assign.'); } if (in_array($roleName, ['guest'], true)) { throw new InvalidArgumentException('The selected role cannot be assigned manually.'); } $existingRoles = admin_get_user_roles($pdo, $userId); if (in_array($roleName, $existingRoles, true)) { $message = sprintf('User already has the %s role.', $roleName); } else { $result = $rbac->assignRole($userId, $roleName, $adminId, 'Assigned via admin panel'); if (!$result) { throw new RuntimeException('Failed to assign role. Please try again.'); } $message = sprintf('Role %s assigned successfully.', $roleName); } $setFlashAndRedirect('success', $message, $redirectUrl); break; } case 'remove_role': { $roleName = trim($_POST['role_name'] ?? ''); if ($roleName === '' || !isset($roleLookup[$roleName])) { throw new InvalidArgumentException('Please select a valid role to remove.'); } if (in_array($roleName, ['guest', 'member', 'super_admin'], true)) { throw new InvalidArgumentException('The selected role cannot be removed from this interface.'); } $existingRoles = admin_get_user_roles($pdo, $userId); if (!in_array($roleName, $existingRoles, true)) { $message = sprintf('Role %s was already removed.', $roleName); } else { $result = $rbac->removeRole($userId, $roleName, $adminId, 'Removed via admin panel'); if (!$result) { throw new RuntimeException('Failed to remove role. Please try again.'); } $message = sprintf('Role %s removed successfully.', $roleName); } $setFlashAndRedirect('success', $message, $redirectUrl); break; } case 'set_active': { $activeValue = isset($_POST['active_value']) && (int) $_POST['active_value'] === 1; if (!admin_set_user_active($pdo, $userId, $activeValue)) { throw new RuntimeException('Unable to update user status. Please try again.'); } $message = $activeValue ? 'User account activated.' : 'User account marked inactive.'; $setFlashAndRedirect('success', $message, $redirectUrl); break; } case 'enable_streaming': { $result = $rbac->assignRole($userId, VRBAC::ROLE_STREAMER, $adminId, 'Streaming access enabled via admin panel'); if (!$result) { throw new RuntimeException('Unable to grant streaming access. Verify the user roles and try again.'); } $setFlashAndRedirect('success', 'Streaming access enabled and stream key prepared.', $redirectUrl); break; } case 'disable_streaming': { $result = $rbac->removeRole($userId, VRBAC::ROLE_STREAMER, $adminId, 'Streaming access revoked via admin panel'); if (!$result) { throw new RuntimeException('Unable to revoke streaming access. Verify the current roles and try again.'); } $setFlashAndRedirect('success', 'Streaming access revoked for the user.', $redirectUrl); break; } case 'regenerate_stream_key': { VStreamKeyManager::getInstance()->regenerateStreamKey($userId); $setFlashAndRedirect('success', 'Stream key regenerated successfully.', $redirectUrl); break; } default: throw new InvalidArgumentException('Unknown action requested.'); } } catch (Throwable $e) { $setFlashAndRedirect('error', $e->getMessage(), $redirectUrl); } } $filters = [ 'q' => trim($_GET['q'] ?? ''), 'status' => $_GET['status'] ?? '', 'role' => $_GET['role'] ?? '', 'verified' => $_GET['verified'] ?? '', 'streaming' => $_GET['streaming'] ?? '', ]; $page = isset($_GET['page']) ? max(1, (int) $_GET['page']) : 1; $perPage = 20; $offset = ($page - 1) * $perPage; $userStats = admin_fetch_user_stats($pdo); $recentUsers = admin_fetch_recent_users($pdo, 20); $roleDistribution = admin_fetch_role_distribution($pdo); $userGrowth = admin_fetch_user_growth($pdo, 14); $topCreators = admin_fetch_top_creators($pdo, 12); $userDirectory = admin_search_users($pdo, $filters, $perPage, $offset); $totalUsersMatching = admin_count_users($pdo, $filters); $totalPages = max(1, (int) ceil($totalUsersMatching / $perPage)); $assignableRoles = array_filter( $availableRoles, static fn(array $role): bool => !in_array($role['role_name'], ['guest', 'super_admin'], true) ); $csrfToken = admin_csrf_token('admin_users'); admin_page_start('User Operations Center', 'users'); ?>
👥
Total Users
joined today active
Verified Accounts
% verification rate
🎯
Retention Focus
Active beyond first day

User Directory Filters

0): ?> result
Reset

User Directory

Showing page of
No users matched the current filters. Adjust your filters and try again.
User Roles Streaming Engagement Account Controls
# · Verified Inactive
Email: Joined: Last login:
No active roles
Status: Role gated: Streams: / Key: Updated:
Token balance: Total logins:
1): ?>

Role Distribution

Open Legacy Manager
No role data available yet.
0 ? ($total / $userStats['total']) * 100 : 0; ?>
Role Total Users Share
%

Sign-up Trend (Last 14 Days)

Insufficient data to chart growth.
Date New Accounts

Recent Sign-ups

No recent registrations found.
User Email Joined Status Tokens
# · Verified

Creator Snapshot

Token analytics
No creator metrics ready yet.
User Videos Tokens Earned Token Balance
# ·

Operational Shortcuts

🔎
Advanced Search
Filter by activity, role, verification, or balances.
📠
Subscription Management
Review subscriptions and premium upgrades.
💳
Token Adjustments
Credit or debit balances and configure packages.
📅
Security Events
Audit sensitive changes performed by staff.