T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/soundstudiopro.com/private_html/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/private_html/admin_api.php
<?php
// Include security functions
require_once 'includes/security.php';

// Validate admin access
validateAdminAccess();

// Rate limiting for API
if (!checkRateLimit('admin_api', 100, 60)) {
    http_response_code(429);
    echo json_encode(['error' => 'Rate limit exceeded']);
    exit;
}

header('Content-Type: application/json');

require_once 'config/database.php';

$pdo = getDBConnection();

if (!$pdo) {
    http_response_code(500);
    echo json_encode(['error' => 'Database connection failed']);
    exit;
}

try {
    // Parse input - support both GET and POST (JSON body)
    $input = [];
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $raw_input = file_get_contents('php://input');
        if (!empty($raw_input)) {
            $input = json_decode($raw_input, true) ?? [];
        }
    }
    
    // Get action from either GET, POST, or JSON body
    $action = sanitizeString($_GET['action'] ?? $input['action'] ?? $_POST['action'] ?? 'stats');
    
    // Validate action parameter
    $validActions = ['stats', 'recent_activity', 'user_details', 'update_user', 'delete_user', 'track_details', 'get_user_details', 'block_user', 'unblock_user', 'block_ip', 'login_as_user', 'return_to_admin', 'make_admin', 'remove_admin', 'change_password', 'upgrade_to_pro', 'test_db_connection', 'check_file_permissions', 'check_disk_space', 'clear_cache', 'delete_track', 'retry_track', 'delete_orphaned_track', 'assign_orphaned_track', 'transfer_track', 'retry_all_failed'];
    if (!in_array($action, $validActions)) {
        http_response_code(400);
        echo json_encode(['error' => 'Invalid action: ' . $action]);
        exit;
    }

switch ($action) {
    case 'stats':
            // Get comprehensive statistics
            $stats = [];
            
            // User stats
        $stmt = $pdo->prepare("SELECT COUNT(*) as total FROM users");
        $stmt->execute();
            $stats['totalUsers'] = $stmt->fetch()['total'];

            $stmt = $pdo->prepare("SELECT COUNT(*) as total FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)");
        $stmt->execute();
            $stats['newUsers'] = $stmt->fetch()['total'];
            
            $stmt = $pdo->prepare("SELECT COUNT(*) as total FROM users WHERE plan IN ('starter', 'pro')");
        $stmt->execute();
            $stats['premiumUsers'] = $stmt->fetch()['total'];
            
            // Track stats
            $stmt = $pdo->prepare("SELECT COUNT(*) as total FROM music_tracks");
        $stmt->execute();
            $stats['totalTracks'] = $stmt->fetch()['total'];
            
        $stmt = $pdo->prepare("
            SELECT 
                COUNT(CASE WHEN status = 'complete' THEN 1 END) as completed,
                COUNT(CASE WHEN status = 'processing' THEN 1 END) as processing,
                COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed
            FROM music_tracks
        ");
        $stmt->execute();
        $trackStats = $stmt->fetch();
            $stats['trackStats'] = $trackStats;
            
            $stmt = $pdo->prepare("
                SELECT COUNT(*) as total 
                FROM music_tracks 
                WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
            ");
            $stmt->execute();
            $stats['newTracks'] = $stmt->fetch()['total'];
            
            // Duration stats
            $stmt = $pdo->prepare("
                SELECT 
                    AVG(duration) as avg_duration,
                    MIN(duration) as min_duration,
                    MAX(duration) as max_duration,
                    COUNT(CASE WHEN duration < 60 THEN 1 END) as short_tracks,
                    COUNT(CASE WHEN duration >= 60 AND duration < 180 THEN 1 END) as medium_tracks,
                    COUNT(CASE WHEN duration >= 180 THEN 1 END) as long_tracks
                FROM music_tracks 
                WHERE status = 'complete' AND duration > 0
            ");
            $stmt->execute();
            $stats['durationStats'] = $stmt->fetch();
            
            echo json_encode(['success' => true, 'data' => $stats]);
            break;
            
        case 'recent_activity':
            // Get recent activity
        $stmt = $pdo->prepare("
            SELECT 
                mt.id,
                    mt.title,
                    mt.status,
                    mt.duration,
                    mt.created_at,
                    u.name as user_name,
                    u.plan
            FROM music_tracks mt
            JOIN users u ON mt.user_id = u.id
            ORDER BY mt.created_at DESC
                LIMIT 20
        ");
        $stmt->execute();
            $recentActivity = $stmt->fetchAll();
            
            echo json_encode(['success' => true, 'data' => $recentActivity]);
            break;
            
        case 'top_users':
            // Get top users
            $stmt = $pdo->prepare("
                SELECT 
                    u.id,
                    u.name,
                    u.plan,
                    COUNT(mt.id) as total_tracks,
                    COUNT(CASE WHEN mt.status = 'complete' THEN 1 END) as completed_tracks,
                    COUNT(CASE WHEN mt.status = 'processing' THEN 1 END) as processing_tracks,
                    COUNT(CASE WHEN mt.status = 'failed' THEN 1 END) as failed_tracks,
                    MAX(mt.created_at) as last_activity
                FROM users u
                LEFT JOIN music_tracks mt ON u.id = mt.user_id
                GROUP BY u.id, u.name, u.plan
                ORDER BY total_tracks DESC
                LIMIT 15
            ");
            $stmt->execute();
            $topUsers = $stmt->fetchAll();
            
            echo json_encode(['success' => true, 'data' => $topUsers]);
            break;
            
        case 'user_stats':
            // Get user track statistics
            $stmt = $pdo->prepare("
                SELECT 
                    u.name,
                    u.plan,
                    COUNT(CASE WHEN mt.status = 'complete' THEN 1 END) as completed,
                    COUNT(CASE WHEN mt.status = 'processing' THEN 1 END) as processing,
                    COUNT(CASE WHEN mt.status = 'failed' THEN 1 END) as failed
                FROM users u
                LEFT JOIN music_tracks mt ON u.id = mt.user_id
                GROUP BY u.id, u.name, u.plan
                HAVING completed > 0 OR processing > 0 OR failed > 0
                ORDER BY (completed + processing + failed) DESC
            ");
            $stmt->execute();
            $userStats = $stmt->fetchAll();
            
            echo json_encode(['success' => true, 'data' => $userStats]);
            break;
            
        case 'plan_stats':
            // Get plan statistics
            $stmt = $pdo->prepare("
                SELECT 
                    u.plan,
                    COUNT(u.id) as user_count,
                    COUNT(mt.id) as total_tracks,
                    COUNT(CASE WHEN mt.status = 'complete' THEN 1 END) as completed_tracks,
                    AVG(mt.duration) as avg_duration
                FROM users u
                LEFT JOIN music_tracks mt ON u.id = mt.user_id
                GROUP BY u.plan
                ORDER BY user_count DESC
            ");
            $stmt->execute();
            $planStats = $stmt->fetchAll();
            
            echo json_encode(['success' => true, 'data' => $planStats]);
                break;
            
        case 'retry_failed':
            // Bulk retry failed tracks
            $stmt = $pdo->prepare("
                SELECT id, user_id, title 
                FROM music_tracks 
                WHERE status = 'failed' 
                ORDER BY created_at DESC
            ");
            $stmt->execute();
            $failedTracks = $stmt->fetchAll();
            
            $retried = 0;
            foreach ($failedTracks as $track) {
                // Update status to processing
                $updateStmt = $pdo->prepare("
                    UPDATE music_tracks 
                    SET status = 'processing', updated_at = NOW() 
                    WHERE id = ?
                ");
                $updateStmt->execute([$track['id']]);
                $retried++;
            }
            
            echo json_encode([
                'success' => true, 
                'message' => "Retried $retried failed tracks",
                'retried' => $retried
            ]);
            break;
            
        case 'assign_orphaned_track':
            // Assign orphaned track to user
            $track_id = $input['track_id'] ?? null;
            $user_id = $input['user_id'] ?? null;
            
            if (!$track_id || !$user_id) {
                echo json_encode(['success' => false, 'message' => 'Track ID and User ID are required']);
                break;
            }
            
            // Verify track is orphaned
            $stmt = $pdo->prepare("SELECT id FROM music_tracks WHERE id = ? AND (user_id IS NULL OR user_id = 0)");
            $stmt->execute([$track_id]);
            if (!$stmt->fetch()) {
                echo json_encode(['success' => false, 'message' => 'Track is not orphaned or does not exist']);
                break;
            }
            
            // Verify user exists
            $stmt = $pdo->prepare("SELECT id FROM users WHERE id = ?");
            $stmt->execute([$user_id]);
            if (!$stmt->fetch()) {
                echo json_encode(['success' => false, 'message' => 'User does not exist']);
                break;
            }
            
            // Assign track to user
            $stmt = $pdo->prepare("UPDATE music_tracks SET user_id = ?, updated_at = NOW() WHERE id = ?");
            $stmt->execute([$user_id, $track_id]);
            
            echo json_encode(['success' => true, 'message' => 'Track assigned successfully']);
            break;
            
        case 'assign_all_orphaned_tracks':
            // Assign all orphaned tracks to admin user
            $admin_user_id = $_SESSION['user_id'] ?? null;
            
            if (!$admin_user_id) {
                echo json_encode(['success' => false, 'message' => 'Admin user not found']);
                break;
            }
            
            // Get all orphaned tracks
            $stmt = $pdo->prepare("
                SELECT id FROM music_tracks 
                WHERE user_id IS NULL OR user_id = 0
            ");
            $stmt->execute();
            $orphaned_tracks = $stmt->fetchAll();
            
            $assigned_count = 0;
            foreach ($orphaned_tracks as $track) {
                $updateStmt = $pdo->prepare("UPDATE music_tracks SET user_id = ?, updated_at = NOW() WHERE id = ?");
                $updateStmt->execute([$admin_user_id, $track['id']]);
                $assigned_count++;
            }
            
            echo json_encode([
                'success' => true, 
                'message' => "Assigned $assigned_count orphaned tracks to admin",
                'assigned_count' => $assigned_count
            ]);
            break;
            
        case 'delete_orphaned_track':
            // Delete orphaned track
            $track_id = $input['track_id'] ?? null;
            
            if (!$track_id) {
                echo json_encode(['success' => false, 'message' => 'Track ID is required']);
                break;
            }
            
            // Verify track is orphaned
            $stmt = $pdo->prepare("SELECT id FROM music_tracks WHERE id = ? AND (user_id IS NULL OR user_id = 0)");
            $stmt->execute([$track_id]);
            if (!$stmt->fetch()) {
                echo json_encode(['success' => false, 'message' => 'Track is not orphaned or does not exist']);
                break;
            }
            
            // Delete track
            $stmt = $pdo->prepare("DELETE FROM music_tracks WHERE id = ?");
            $stmt->execute([$track_id]);
            
            echo json_encode(['success' => true, 'message' => 'Track deleted successfully']);
            break;
            
        case 'transfer_track':
            // Transfer track to different user
            $track_id = $input['track_id'] ?? null;
            $user_id = $input['user_id'] ?? null;
            
            if (!$track_id || !$user_id) {
                echo json_encode(['success' => false, 'message' => 'Track ID and User ID are required']);
                break;
            }
            
            // Verify track exists
            $stmt = $pdo->prepare("SELECT id, user_id FROM music_tracks WHERE id = ?");
            $stmt->execute([$track_id]);
            $track = $stmt->fetch();
            
            if (!$track) {
                echo json_encode(['success' => false, 'message' => 'Track does not exist']);
                break;
            }
            
            // Verify user exists
            $stmt = $pdo->prepare("SELECT id FROM users WHERE id = ?");
            $stmt->execute([$user_id]);
            if (!$stmt->fetch()) {
                echo json_encode(['success' => false, 'message' => 'User does not exist']);
                break;
            }
            
            // Transfer track to user
            $stmt = $pdo->prepare("UPDATE music_tracks SET user_id = ?, updated_at = NOW() WHERE id = ?");
            $stmt->execute([$user_id, $track_id]);
            
            echo json_encode(['success' => true, 'message' => 'Track transferred successfully']);
            break;
            
        case 'retry_track':
            // Retry failed track
            $track_id = $input['track_id'] ?? null;
            
            if (!$track_id) {
                echo json_encode(['success' => false, 'message' => 'Track ID is required']);
                break;
            }
            
            // Verify track exists and is failed
            $stmt = $pdo->prepare("SELECT id, status FROM music_tracks WHERE id = ?");
            $stmt->execute([$track_id]);
            $track = $stmt->fetch();
            
            if (!$track) {
                echo json_encode(['success' => false, 'message' => 'Track does not exist']);
                break;
            }
            
            if ($track['status'] !== 'failed') {
                echo json_encode(['success' => false, 'message' => 'Track is not in failed status']);
                break;
            }
            
            // Update status to processing
            $stmt = $pdo->prepare("UPDATE music_tracks SET status = 'processing', updated_at = NOW() WHERE id = ?");
            $stmt->execute([$track_id]);
            
            echo json_encode(['success' => true, 'message' => 'Track retry initiated']);
            break;
            
        case 'delete_track':
            // Delete any track (admin only)
            $track_id = $input['track_id'] ?? null;
            
            if (!$track_id) {
                echo json_encode(['success' => false, 'message' => 'Track ID is required']);
                break;
            }
            
            // Verify track exists
            $stmt = $pdo->prepare("SELECT id FROM music_tracks WHERE id = ?");
            $stmt->execute([$track_id]);
            if (!$stmt->fetch()) {
                echo json_encode(['success' => false, 'message' => 'Track does not exist']);
                break;
            }
            
            try {
                // Start transaction
                $pdo->beginTransaction();
                
                // Helper function to safely delete from a table (ignores if table doesn't exist)
                $safeDelete = function($table, $track_id) use ($pdo) {
                    try {
                        $stmt = $pdo->prepare("DELETE FROM {$table} WHERE track_id = ?");
                        $stmt->execute([$track_id]);
                        return true;
                    } catch (PDOException $e) {
                        // Ignore "table doesn't exist" errors, but log others
                        if (strpos($e->getMessage(), "doesn't exist") === false) {
                            error_log("Error deleting from {$table}: " . $e->getMessage());
                        }
                        return false;
                    }
                };
                
                // Delete related data first (foreign key constraints)
                // Note: Order matters - delete child records before parent
                // Use safe delete to handle missing tables gracefully
                $safeDelete('audio_variations', $track_id);
                $safeDelete('track_likes', $track_id);
                $safeDelete('track_comments', $track_id);
                $safeDelete('track_downloads', $track_id);
                $safeDelete('track_plays', $track_id);
                $safeDelete('track_views', $track_id);
                $safeDelete('track_votes', $track_id);
                $safeDelete('track_shares', $track_id);
                $safeDelete('track_purchases', $track_id);
                $safeDelete('playlist_tracks', $track_id);
                $safeDelete('sales', $track_id);
                
                // Delete the main track
                $stmt = $pdo->prepare("DELETE FROM music_tracks WHERE id = ?");
                $stmt->execute([$track_id]);
                
                // Verify deletion
                $verify_stmt = $pdo->prepare("SELECT id FROM music_tracks WHERE id = ?");
                $verify_stmt->execute([$track_id]);
                if ($verify_stmt->fetch()) {
                    $pdo->rollBack();
                    echo json_encode(['success' => false, 'message' => 'Track deletion failed - track still exists']);
                    break;
                }
                
                // Commit transaction
                $pdo->commit();
                
                echo json_encode(['success' => true, 'message' => 'Track deleted successfully']);
            } catch (Exception $e) {
                if ($pdo->inTransaction()) {
                    $pdo->rollBack();
                }
                echo json_encode(['success' => false, 'message' => 'Error deleting track: ' . $e->getMessage()]);
            }
            break;
            
        case 'update_user':
            // Update user credits
            error_log("Admin API: update_user called with user_id=" . ($_GET['user_id'] ?? 'null') . ", credits=" . ($_GET['credits'] ?? 'null'));
            
            $user_id = validateInteger($_GET['user_id'] ?? null);
            $credits = validateInteger($_GET['credits'] ?? null, 0, 10000);
            
            error_log("Admin API: validated user_id=" . ($user_id ?? 'null') . ", credits=" . ($credits ?? 'null'));
            
            if (!$user_id || $credits === null) {
                error_log("Admin API: validation failed - user_id=" . ($user_id ?? 'null') . ", credits=" . ($credits ?? 'null'));
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID or credits']);
                break;
            }
            
            $stmt = $pdo->prepare("UPDATE users SET credits = ? WHERE id = ?");
            $result = $stmt->execute([$credits, $user_id]);
            
            error_log("Admin API: update result=" . ($result ? 'success' : 'failed') . ", rows affected=" . $stmt->rowCount());
            
            echo json_encode(['success' => true, 'message' => 'User updated successfully']);
            break;
            
        case 'login_as_user':
            // Login as another user
            $user_id = validateInteger($_GET['user_id'] ?? null);
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            // Get user data
            $stmt = $pdo->prepare("SELECT id, name, email, plan, credits, is_admin FROM users WHERE id = ?");
            $stmt->execute([$user_id]);
            $user = $stmt->fetch();
            
            if (!$user) {
                http_response_code(404);
                echo json_encode(['error' => 'User not found']);
                break;
            }
            
            // Store original admin session data
            $_SESSION['original_admin_id'] = $_SESSION['user_id'];
            $_SESSION['original_admin_name'] = $_SESSION['user_name'];
            $_SESSION['original_admin_email'] = $_SESSION['user_email'];
            $_SESSION['original_admin_plan'] = $_SESSION['plan'];
            $_SESSION['original_admin_credits'] = $_SESSION['credits'];
            $_SESSION['original_admin_is_admin'] = $_SESSION['is_admin'];
            $_SESSION['is_impersonating'] = true;
            
            // Update session to login as this user
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['user_name'] = $user['name'];
            $_SESSION['user_email'] = $user['email'];
            $_SESSION['plan'] = $user['plan'];
            $_SESSION['credits'] = $user['credits'];
            $_SESSION['is_admin'] = $user['is_admin'];
            
            echo json_encode(['success' => true, 'message' => 'Logged in as user']);
            break;
            
        case 'make_admin':
            // Make user an admin
            $user_id = validateInteger($_GET['user_id'] ?? null);
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            $stmt = $pdo->prepare("UPDATE users SET is_admin = 1 WHERE id = ?");
            $stmt->execute([$user_id]);
            
            echo json_encode(['success' => true, 'message' => 'User is now an admin']);
            break;
            
        case 'remove_admin':
            // Remove admin privileges
            $user_id = validateInteger($_GET['user_id'] ?? null);
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            // Don't allow removing admin from self
            if ($user_id == $_SESSION['user_id']) {
                http_response_code(400);
                echo json_encode(['error' => 'Cannot remove admin privileges from yourself']);
                break;
            }
            
            $stmt = $pdo->prepare("UPDATE users SET is_admin = 0 WHERE id = ?");
            $stmt->execute([$user_id]);
            
            echo json_encode(['success' => true, 'message' => 'Admin privileges removed']);
            break;
            
        case 'change_password':
            // Change user password
            $user_id = validateInteger($_GET['user_id'] ?? null);
            $new_password = $_POST['new_password'] ?? '';
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            if (empty($new_password)) {
                http_response_code(400);
                echo json_encode(['error' => 'Password is required']);
                break;
            }
            
            if (strlen($new_password) < 6) {
                http_response_code(400);
                echo json_encode(['error' => 'Password must be at least 6 characters long']);
                break;
            }
            
            // Verify user exists
            $stmt = $pdo->prepare("SELECT id, email FROM users WHERE id = ?");
            $stmt->execute([$user_id]);
            $user = $stmt->fetch();
            
            if (!$user) {
                http_response_code(404);
                echo json_encode(['error' => 'User not found']);
                break;
            }
            
            // Hash the new password
            $hashed_password = password_hash($new_password, PASSWORD_DEFAULT);
            
            // Update password
            $stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
            $stmt->execute([$hashed_password, $user_id]);
            
            echo json_encode(['success' => true, 'message' => 'Password changed successfully']);
            break;
            
        case 'upgrade_to_pro':
            // Upgrade user to Pro plan
            $user_id = validateInteger($_GET['user_id'] ?? null);
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            // Verify user exists
            $stmt = $pdo->prepare("SELECT id, email, plan FROM users WHERE id = ?");
            $stmt->execute([$user_id]);
            $user = $stmt->fetch();
            
            if (!$user) {
                http_response_code(404);
                echo json_encode(['error' => 'User not found']);
                break;
            }
            
            if ($user['plan'] === 'pro') {
                http_response_code(400);
                echo json_encode(['error' => 'User is already on Pro plan']);
                break;
            }
            
            // Upgrade to Pro
            $stmt = $pdo->prepare("UPDATE users SET plan = 'pro' WHERE id = ?");
            $stmt->execute([$user_id]);
            
            echo json_encode(['success' => true, 'message' => 'User upgraded to Pro plan successfully']);
            break;
            
        case 'delete_user':
            // Delete user and all their tracks
            $user_id = $_GET['user_id'] ?? null;
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            // Don't allow deleting self
            if ($user_id == $_SESSION['user_id']) {
                http_response_code(400);
                echo json_encode(['error' => 'Cannot delete yourself']);
                break;
            }
            
            // Start transaction
            $pdo->beginTransaction();
            
            try {
                // Delete user's tracks first
                $stmt = $pdo->prepare("DELETE FROM music_tracks WHERE user_id = ?");
                $stmt->execute([$user_id]);
                
                // Delete user
                $stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
                $stmt->execute([$user_id]);
                
                $pdo->commit();
                echo json_encode(['success' => true, 'message' => 'User deleted successfully']);
            } catch (Exception $e) {
                $pdo->rollback();
                http_response_code(500);
                echo json_encode(['error' => 'Error deleting user: ' . $e->getMessage()]);
            }
            break;
            
        case 'return_to_admin':
            // Return to original admin session
            if (!isset($_SESSION['is_impersonating']) || !$_SESSION['is_impersonating']) {
                http_response_code(400);
                echo json_encode(['error' => 'Not currently impersonating a user']);
                break;
            }
            
            // Restore original admin session data
            $_SESSION['user_id'] = $_SESSION['original_admin_id'];
            $_SESSION['user_name'] = $_SESSION['original_admin_name'];
            $_SESSION['user_email'] = $_SESSION['original_admin_email'];
            $_SESSION['plan'] = $_SESSION['original_admin_plan'];
            $_SESSION['credits'] = $_SESSION['original_admin_credits'];
            $_SESSION['is_admin'] = $_SESSION['original_admin_is_admin'];
            
            // Clean up impersonation data
            unset($_SESSION['original_admin_id']);
            unset($_SESSION['original_admin_name']);
            unset($_SESSION['original_admin_email']);
            unset($_SESSION['original_admin_plan']);
            unset($_SESSION['original_admin_credits']);
            unset($_SESSION['original_admin_is_admin']);
            unset($_SESSION['is_impersonating']);
            
            echo json_encode(['success' => true, 'message' => 'Returned to admin session']);
            break;
            
        case 'get_user_details':
            // Get detailed user information
            $user_id = validateInteger($_GET['user_id'] ?? null);
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            $stmt = $pdo->prepare("
                SELECT id, name, email, credits, plan, is_admin, is_blocked, 
                       block_reason, last_login_ip, last_login_at, 
                       failed_login_attempts, last_failed_login, created_at
                FROM users WHERE id = ?
            ");
            $stmt->execute([$user_id]);
            $user = $stmt->fetch();
            
            if (!$user) {
                http_response_code(404);
                echo json_encode(['error' => 'User not found']);
                break;
            }
            
            echo json_encode(['success' => true, 'user' => $user]);
            break;
            
        case 'block_user':
            // Block a user
            $user_id = validateInteger($_GET['user_id'] ?? null);
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            // Don't allow blocking self
            if ($user_id == $_SESSION['user_id']) {
                http_response_code(400);
                echo json_encode(['error' => 'Cannot block yourself']);
                break;
            }
            
            $stmt = $pdo->prepare("
                UPDATE users SET 
                    is_blocked = 1, 
                    block_reason = 'Blocked by admin',
                    blocked_at = NOW()
                WHERE id = ?
            ");
            $stmt->execute([$user_id]);
            
            // Log security event
            $stmt = $pdo->prepare("
                INSERT INTO security_events (event_type, details, user_id, admin_id, ip_address, user_agent)
                VALUES (?, ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                'user_blocked',
                'User blocked by admin',
                $user_id,
                $_SESSION['user_id'],
                $_SERVER['REMOTE_ADDR'] ?? 'unknown',
                $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
            ]);
            
            echo json_encode(['success' => true, 'message' => 'User blocked successfully']);
            break;
            
        case 'unblock_user':
            // Unblock a user
            $user_id = validateInteger($_GET['user_id'] ?? null);
            
            if (!$user_id) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid user ID']);
                break;
            }
            
            $stmt = $pdo->prepare("
                UPDATE users SET 
                    is_blocked = 0, 
                    block_reason = NULL,
                    blocked_at = NULL
                WHERE id = ?
            ");
            $stmt->execute([$user_id]);
            
            // Log security event
            $stmt = $pdo->prepare("
                INSERT INTO security_events (event_type, details, user_id, admin_id, ip_address, user_agent)
                VALUES (?, ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                'user_unblocked',
                'User unblocked by admin',
                $user_id,
                $_SESSION['user_id'],
                $_SERVER['REMOTE_ADDR'] ?? 'unknown',
                $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
            ]);
            
            echo json_encode(['success' => true, 'message' => 'User unblocked successfully']);
            break;
            
        case 'block_ip':
            // Block an IP address
            $ip_address = $_GET['ip_address'] ?? null;
            
            if (!$ip_address || !filter_var($ip_address, FILTER_VALIDATE_IP)) {
                http_response_code(400);
                echo json_encode(['error' => 'Invalid IP address']);
                break;
            }
            
            // Check if IP is already blocked
            $stmt = $pdo->prepare("SELECT id FROM ip_blacklist WHERE ip_address = ?");
            $stmt->execute([$ip_address]);
            
            if ($stmt->fetch()) {
                http_response_code(400);
                echo json_encode(['error' => 'IP address is already blocked']);
                break;
            }
            
            $stmt = $pdo->prepare("
                INSERT INTO ip_blacklist (ip_address, reason, blocked_by)
                VALUES (?, ?, ?)
            ");
            $stmt->execute([
                $ip_address,
                'Blocked by admin due to suspicious activity',
                $_SESSION['user_id']
            ]);
            
            // Log security event
            $stmt = $pdo->prepare("
                INSERT INTO security_events (event_type, details, admin_id, ip_address, user_agent)
                VALUES (?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                'ip_blocked',
                'IP address blocked: ' . $ip_address,
                $_SESSION['user_id'],
                $_SERVER['REMOTE_ADDR'] ?? 'unknown',
                $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
            ]);
            
            echo json_encode(['success' => true, 'message' => 'IP address blocked successfully']);
            break;
            
        case 'test_db_connection':
            // Test database connection
            try {
                $test_stmt = $pdo->prepare("SELECT 1 as test");
                $test_stmt->execute();
                $result = $test_stmt->fetch();
                
                if ($result && $result['test'] == 1) {
                    echo json_encode(['success' => true, 'message' => 'Database connection successful']);
                } else {
                    echo json_encode(['success' => false, 'error' => 'Database test query failed']);
                }
            } catch (Exception $e) {
                echo json_encode(['success' => false, 'error' => 'Database connection failed: ' . $e->getMessage()]);
            }
            break;
            
        case 'check_file_permissions':
            // Check file permissions
            $critical_files = [
                'config/database.php',
                'admin.php',
                'includes/header.php',
                'utils/audiofiles.php'
            ];
            
            $results = [];
            foreach ($critical_files as $file) {
                $results[$file] = [
                    'exists' => file_exists($file),
                    'readable' => is_readable($file),
                    'writable' => is_writable($file)
                ];
            }
            
            $all_good = true;
            foreach ($results as $file => $perms) {
                if (!$perms['exists'] || !$perms['readable']) {
                    $all_good = false;
                    break;
                }
            }
            
            echo json_encode([
                'success' => $all_good,
                'results' => $results,
                'message' => $all_good ? 'All file permissions are correct' : 'Some file permissions need attention'
            ]);
            break;
            
        case 'check_disk_space':
            // Check disk space
            $total_space = disk_total_space('.');
            $free_space = disk_free_space('.');
            $used_space = $total_space - $free_space;
            $usage_percent = ($used_space / $total_space) * 100;
            
            $status = $usage_percent < 80 ? 'good' : ($usage_percent < 90 ? 'warning' : 'critical');
            
            echo json_encode([
                'success' => $usage_percent < 90,
                'total_gb' => round($total_space / 1024 / 1024 / 1024, 2),
                'free_gb' => round($free_space / 1024 / 1024 / 1024, 2),
                'used_gb' => round($used_space / 1024 / 1024 / 1024, 2),
                'usage_percent' => round($usage_percent, 2),
                'status' => $status,
                'message' => "Disk usage: {$usage_percent}%"
            ]);
            break;
            
        case 'clear_cache':
            // Clear all cache
            try {
                // Clear file cache
                $cache_dir = 'cache/';
                if (is_dir($cache_dir)) {
                    $files = glob($cache_dir . '*.json');
                    foreach ($files as $file) {
                        if (is_file($file)) {
                            unlink($file);
                        }
                    }
                }
                
                // Clear session cache
                session_cache_limiter('nocache');
                
                echo json_encode(['success' => true, 'message' => 'Cache cleared successfully']);
            } catch (Exception $e) {
                echo json_encode(['success' => false, 'error' => 'Cache clear failed: ' . $e->getMessage()]);
            }
            break;
            
        default:
            http_response_code(400);
            echo json_encode(['error' => 'Invalid action']);
    }
    
    } catch (Exception $e) {
    error_log("Admin API Error: " . $e->getMessage());
        http_response_code(500);
    echo json_encode(['error' => 'Internal server error']);
}
?> 

CasperSecurity Mini