hasRole('super_admin')) { abort(403, 'Only super admins can impersonate users.'); } if ($targetUser->hasRole('super_admin')) { abort(403, 'Cannot impersonate another super admin.'); } $tokenName = 'impersonation-by-' . $admin->id; $newToken = $targetUser->createToken($tokenName); Cache::put( "impersonation:{$newToken->accessToken->id}", $admin->id, now()->addHours(4), ); activity('admin') ->causedBy($admin) ->performedOn($targetUser) ->event('admin.impersonation.started') ->withProperties([ 'admin_id' => $admin->id, 'target_user_id' => $targetUser->id, ]) ->log('Started impersonating user ' . $targetUser->full_name); return [ 'token' => $newToken->plainTextToken, 'user' => $targetUser, 'admin_id' => $admin->id, ]; } /** * Stop impersonation and return the original admin. */ public function stop(User $currentUser): User { $currentToken = $currentUser->currentAccessToken(); if (! $currentToken || ! str_starts_with($currentToken->name, 'impersonation-by-')) { abort(400, 'No active impersonation session.'); } $adminId = Cache::get("impersonation:{$currentToken->id}"); $admin = $adminId ? User::find($adminId) : null; if (! $admin) { // Fallback: extract admin ID from token name $admin = User::find(str_replace('impersonation-by-', '', $currentToken->name)); } activity('admin') ->causedBy($admin ?? $currentUser) ->performedOn($currentUser) ->event('admin.impersonation.stopped') ->withProperties([ 'admin_id' => $admin?->id, 'impersonated_user_id' => $currentUser->id, ]) ->log('Stopped impersonating user ' . $currentUser->full_name); Cache::forget("impersonation:{$currentToken->id}"); $currentToken->delete(); if (! $admin) { abort(400, 'Could not resolve original admin session.'); } return $admin; } }