dataTable($request); } $stats = $this->getStatsData(); return view('pages.system_settings.session-manager', compact('stats')); } protected function getDriver() { return config('session.driver'); } public function getStats() { return response()->json($this->getStatsData()); } protected function getStatsData() { $driver = $this->getDriver(); if ($driver === 'database') { $activeCutoff = now()->subMinutes(30)->timestamp; return [ 'total' => DB::table('sessions')->count(), 'active' => DB::table('sessions')->where('last_activity', '>=', $activeCutoff)->count(), 'users' => DB::table('sessions')->whereNotNull('user_id')->count(), 'guests' => DB::table('sessions')->whereNull('user_id')->count(), 'unique_ips' => DB::table('sessions')->distinct('ip_address')->count('ip_address'), ]; } if ($driver === 'redis') { $service = app(SystemMonitoringService::class); $total = $service->getActiveUsers(); // For Redis, we'd need to iterate all to get specific user/guest breakdown // For performance, we'll return total for now or a limited set return [ 'total' => $total, 'active' => $total, 'users' => 'N/A (Redis)', 'guests' => 'N/A (Redis)', 'unique_ips' => 'N/A (Redis)', ]; } return [ 'total' => 0, 'active' => 0, 'users' => 0, 'guests' => 0, 'unique_ips' => 0, ]; } protected function dataTable(Request $request) { $driver = $this->getDriver(); $sessions = []; $recordsTotal = 0; $recordsFiltered = 0; $activeCutoff = now()->subMinutes(30)->timestamp; $idleCutoff = now()->subMinutes(5)->timestamp; $currentSessionId = session()->getId(); if ($driver === 'database') { $query = DB::table('sessions') ->leftJoin('users', 'sessions.user_id', '=', 'users.id') ->select( 'sessions.*', 'users.email as user_email', 'users.name as user_name' ); $recordsTotal = DB::table('sessions')->count(); // Status Filter if ($status = DataTable::columnSearch($request, 0)) { $operator = $status === 'active' ? '>=' : '<'; $query->where('sessions.last_activity', $operator, $activeCutoff); } // User Filter if ($userSearch = DataTable::columnSearch($request, 1)) { $query->where(function ($q) use ($userSearch) { $q->where('users.email', 'like', "%{$userSearch}%") ->orWhere('users.name', 'like', "%{$userSearch}%"); }); } // IP Filter if ($ipSearch = DataTable::columnSearch($request, 3)) { $query->where('sessions.ip_address', 'like', "%{$ipSearch}%"); } // Global Search if ($globalSearch = DataTable::globalSearch($request)) { $query->where(function ($q) use ($globalSearch) { $q->where('users.email', 'like', "%{$globalSearch}%") ->orWhere('users.name', 'like', "%{$globalSearch}%") ->orWhere('sessions.id', 'like', "%{$globalSearch}%") ->orWhere('sessions.ip_address', 'like', "%{$globalSearch}%"); }); } $recordsFiltered = (clone $query)->count(); [$orderIndex, $orderDirection] = DataTable::order($request, 4, 'desc'); $sortColumn = match ($orderIndex) { 0 => 'sessions.last_activity', 1 => 'users.name', 3 => 'sessions.ip_address', 4 => 'sessions.last_activity', default => 'sessions.last_activity', }; $sessions = $query ->orderBy($sortColumn, $orderDirection) ->skip(DataTable::start($request)) ->take(DataTable::length($request)) ->get(); } else { // REDIS DRIVER LOGIC $connection = config('session.connection') ?? 'default'; $redis = Redis::connection($connection); $sessionCookie = config('session.cookie', 'laravel_session'); $prefix = config('database.redis.options.prefix', ''); // Optimization: Get keys once $patterns = [$sessionCookie.':*']; $keys = []; foreach ($patterns as $p) { $searchPattern = str_replace($prefix, '', $p); $keys = array_merge($keys, $redis->keys($searchPattern)); } $keys = array_unique($keys); $recordsTotal = count($keys); $recordsFiltered = $recordsTotal; $start = DataTable::start($request); $length = DataTable::length($request); $pagedKeys = array_slice($keys, $start, $length); $tempSessions = []; $userIds = []; foreach ($pagedKeys as $key) { $pureKey = str_replace($prefix, '', $key); $data = $redis->get($pureKey); if ($data) { try { $unserialized = unserialize($data, ['allowed_classes' => false]); if (is_string($unserialized)) { $unserialized = unserialize($unserialized, ['allowed_classes' => false]); } } catch (\Exception $e) { continue; } $parts = explode(':', $key); $sessionId = end($parts); if (isset($unserialized['user_id'])) { $userIds[] = $unserialized['user_id']; } $tempSessions[] = [ 'id' => $sessionId, 'user_id' => $unserialized['user_id'] ?? null, 'ip_address' => $unserialized['ip_address'] ?? 'N/A', 'user_agent' => $unserialized['user_agent'] ?? 'N/A', 'last_activity' => $unserialized['last_activity'] ?? time(), ]; } } // Batch fetch users to prevent N+1 $users = ! empty($userIds) ? DB::table('users')->whereIn('id', array_unique($userIds))->get()->keyBy('id') : collect(); foreach ($tempSessions as $sessData) { $user = $users->get($sessData['user_id']); $sessions[] = (object) array_merge($sessData, [ 'user_name' => $user->name ?? 'Guest', 'user_email' => $user->email ?? 'N/A', ]); } } $rows = collect($sessions)->map(function ($session) use ($activeCutoff, $idleCutoff, $currentSessionId) { $isCurrent = $session->id === $currentSessionId; $userAgent = SessionHelper::parseUserAgent($session->user_agent); // Status Logic if ($isCurrent) { $statusHtml = ' '.__('LIVE').' '; } elseif ($session->last_activity >= $idleCutoff) { $statusHtml = ''.__('ACTIVE').''; } elseif ($session->last_activity >= $activeCutoff) { $statusHtml = ''.__('IDLE').''; } else { $statusHtml = ''.__('EXPIRED').''; } // User Column $userHtml = '
'.e($session->user_name ?? 'Guest').'
'.e($session->user_email ?? substr($session->id, 0, 8).'...').'
'; // Device Column $deviceHtml = '
'.$userAgent['browser'].'
'.$userAgent['os'].'
'; $timestamp = Carbon::createFromTimestamp($session->last_activity); $actionsHtml = '
'; $actionsHtml .= ''; if (! $isCurrent) { if (auth()->user()->can('manage active sessions')) { $actionsHtml .= ''; } else { $actionsHtml .= ''; } } else { $actionsHtml .= ''; } $actionsHtml .= '
'; return [ $statusHtml, $userHtml, $deviceHtml, ''.e($session->ip_address).'', e($timestamp->diffForHumans()), $actionsHtml, $isCurrent, // For custom row coloring in JS ]; })->all(); return DataTable::response($request, $recordsTotal, $recordsFiltered, $rows); } public function destroy(Request $request, $id) { if ($id === session()->getId()) { return response()->json(['success' => false, 'message' => __('Cannot terminate current session.')], 403); } $driver = $this->getDriver(); if ($driver === 'database') { DB::table('sessions')->where('id', $id)->delete(); } elseif ($driver === 'redis') { $connection = config('session.connection') ?? 'default'; $redis = Redis::connection($connection); $sessionCookie = config('session.cookie', 'laravel_session'); $redis->del($sessionCookie.':'.$id); } return response()->json(['success' => true, 'message' => __('Session terminated successfully.')]); } }