level !== UserLevel::SUPERADMIN) { return false; } // Cannot impersonate other SUPERADMIN users if ($target->level === UserLevel::SUPERADMIN) { return false; } // Cannot impersonate self if ($admin->id === $target->id) { return false; } // Can only impersonate NORMALUSER if ($target->level !== UserLevel::NORMALUSER) { return false; } // Check if admin is already impersonating someone if ($this->isImpersonating()) { return false; } return true; } public function isImpersonating(): bool { return Session::has(self::IMPERSONATION_SESSION_KEY) && Session::has(self::ORIGINAL_USER_KEY); } public function getCurrentImpersonator(): ?User { if (! $this->isImpersonating()) { return null; } $originalUserId = Session::get(self::ORIGINAL_USER_KEY); return User::find($originalUserId); } public function getImpersonationStartTime(): ?Carbon { if (! $this->isImpersonating()) { return null; } return Session::get(self::IMPERSONATION_START_TIME_KEY); } public function isImpersonationExpired(): bool { if (! $this->isImpersonating()) { return false; } $startTime = $this->getImpersonationStartTime(); if (! $startTime) { return true; } return $startTime->diffInMinutes(now()) > self::IMPERSONATION_TIMEOUT; } public function startImpersonation(User $admin, User $target, Request $request): bool { if (! $this->canImpersonate($admin, $target)) { return false; } // Store original admin user info Session::put(self::ORIGINAL_USER_KEY, $admin->id); Session::put(self::IMPERSONATION_START_TIME_KEY, now()); // Log the impersonation start $impersonationLog = ImpersonationLog::create([ 'admin_id' => $admin->id, 'target_user_id' => $target->id, 'start_time' => now(), 'ip_address' => $request->ip(), 'user_agent' => $request->userAgent(), 'status' => 'active', ]); Session::put(self::IMPERSONATION_SESSION_KEY, $impersonationLog->id); // Log out the admin and log in as target user Auth::logout(); Auth::login($target); // Regenerate session for security Session::regenerate(true); return true; } public function stopImpersonation(Request $request): bool { if (! $this->isImpersonating()) { return false; } $admin = $this->getCurrentImpersonator(); $target = Auth::user(); $impersonationLogId = Session::get(self::IMPERSONATION_SESSION_KEY); // Update the impersonation log if ($impersonationLogId) { $log = ImpersonationLog::find($impersonationLogId); if ($log) { $log->update([ 'end_time' => now(), 'status' => 'completed', ]); } } // Clear impersonation session data Session::forget([ self::IMPERSONATION_SESSION_KEY, self::IMPERSONATION_START_TIME_KEY, self::ORIGINAL_USER_KEY, ]); // Log out target user and log back in as admin Auth::logout(); if ($admin) { Auth::login($admin); } // Regenerate session for security Session::regenerate(true); return true; } public function forceStopAllImpersonations(): void { // Force end any active impersonation sessions in the database ImpersonationLog::where('status', 'active') ->whereNull('end_time') ->update([ 'end_time' => now(), 'status' => 'force_terminated', ]); } public function getRemainingMinutes(): int { if (! $this->isImpersonating()) { return 0; } $startTime = $this->getImpersonationStartTime(); if (! $startTime) { return 0; } $elapsed = $startTime->diffInMinutes(now()); $remaining = self::IMPERSONATION_TIMEOUT - $elapsed; return (int) max(0, $remaining); } }