Two issues were preventing impersonation from working correctly:
1. Templates were not passing current_scope to Layouts.authenticated,
so the impersonation banner never displayed.
2. fetch_current_scope_for_user was looking up the user from the
session token, which always pointed to the superuser. This caused
the superuser to see their own organizations and equipment instead
of the impersonated user's data.
Changes:
- Pass current_scope={@current_scope} to all Layouts.authenticated calls
- Store target_user_id in session during impersonation
- Fetch target user directly from database using target_user_id
- Update both fetch_current_scope_for_user (for controllers) and
mount_current_scope (for LiveViews) to properly handle impersonation
- Clean up target_user_id from session when impersonation ends
Now when a superuser impersonates a user, they correctly see:
- The impersonation banner at the top with exit link
- The target user's organizations and equipment
- All data scoped to the impersonated user
76 lines
2.9 KiB
Text
76 lines
2.9 KiB
Text
<Layouts.authenticated
|
|
flash={@flash}
|
|
current_scope={@current_scope}
|
|
current_organization={@current_organization}
|
|
active_page="equipment"
|
|
>
|
|
<div class="mb-6">
|
|
<!-- Header with back button -->
|
|
<div class="flex items-center justify-between mb-6">
|
|
<div class="flex items-center gap-4">
|
|
<.link
|
|
navigate={~p"/orgs/#{@current_organization.slug}/equipment/#{@equipment_id}"}
|
|
class="text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
|
|
>
|
|
<.icon name="hero-arrow-left" class="h-5 w-5" />
|
|
</.link>
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">{@chart_title}</h1>
|
|
<p class="text-sm text-zinc-600 dark:text-zinc-400">{@equipment.name}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Date Range Selector -->
|
|
<div class="flex items-center gap-2 mb-6">
|
|
<span class="text-sm font-medium text-zinc-700 dark:text-zinc-300">Time Range:</span>
|
|
<div class="flex gap-1">
|
|
<%= for {label, value} <- [{"1 Hour", "1h"}, {"6 Hours", "6h"}, {"12 Hours", "12h"}, {"24 Hours", "24h"}, {"7 Days", "7d"}, {"30 Days", "30d"}] do %>
|
|
<button
|
|
phx-click="change_range"
|
|
phx-value-range={value}
|
|
class={[
|
|
"px-3 py-1.5 text-sm font-medium rounded border transition-colors",
|
|
if @range == value do
|
|
"bg-blue-500 text-white border-blue-500"
|
|
else
|
|
"bg-white dark:bg-zinc-800 text-zinc-700 dark:text-zinc-300 border-zinc-300 dark:border-zinc-600 hover:bg-zinc-50 dark:hover:bg-zinc-700"
|
|
end
|
|
]}
|
|
>
|
|
{label}
|
|
</button>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
<!-- Large Chart -->
|
|
<%= if @chart_data do %>
|
|
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700">
|
|
<div class="p-6">
|
|
<div
|
|
id="detail-chart"
|
|
phx-hook="SensorChart"
|
|
data-chart={@chart_data}
|
|
data-unit={@unit}
|
|
data-auto-scale={to_string(@auto_scale)}
|
|
data-show-zero-line={to_string(@show_zero_line)}
|
|
style="height: 600px;"
|
|
>
|
|
<canvas></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% else %>
|
|
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 p-12">
|
|
<div class="text-center">
|
|
<.icon name="hero-chart-bar" class="mx-auto h-12 w-12 text-zinc-400" />
|
|
<h3 class="mt-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100">
|
|
No sensor data available
|
|
</h3>
|
|
<p class="mt-1 text-sm text-zinc-500 dark:text-zinc-400">
|
|
This device doesn't have any sensors of this type.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</Layouts.authenticated>
|