Fix impersonation to show correct user data and banner
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
This commit is contained in:
parent
a1e163d3ee
commit
806b293ead
13 changed files with 47 additions and 15 deletions
|
|
@ -1,4 +1,4 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={nil}>
|
||||
<Layouts.authenticated flash={@flash} current_scope={@current_scope} current_organization={nil}>
|
||||
<div class="text-center">
|
||||
<.header>
|
||||
Account Settings
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@current_organization}
|
||||
active_page="alerts"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@current_organization}
|
||||
active_page="dashboard"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={@organization}>
|
||||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@organization}
|
||||
>
|
||||
<div class="mb-4">
|
||||
<.link
|
||||
navigate={
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@current_organization}
|
||||
active_page="equipment"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@current_organization}
|
||||
active_page="equipment"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@current_organization}
|
||||
active_page="equipment"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={nil}>
|
||||
<Layouts.authenticated flash={@flash} current_scope={@current_scope} current_organization={nil}>
|
||||
<.header>
|
||||
{@page_title}
|
||||
<:actions>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={nil}>
|
||||
<Layouts.authenticated flash={@flash} current_scope={@current_scope} current_organization={nil}>
|
||||
<.header>
|
||||
{@page_title}
|
||||
<:subtitle>Create a new organization to manage your sites and equipment</:subtitle>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<Layouts.authenticated flash={@flash} current_organization={@organization}>
|
||||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@organization}
|
||||
>
|
||||
<div class="mb-4">
|
||||
<.link
|
||||
navigate={
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@current_organization}
|
||||
active_page="sites"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<Layouts.authenticated
|
||||
flash={@flash}
|
||||
current_scope={@current_scope}
|
||||
current_organization={@current_organization}
|
||||
active_page="sites"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -72,16 +72,17 @@ defmodule ToweropsWeb.UserAuth do
|
|||
# Check if currently impersonating
|
||||
if get_session(conn, :impersonating) do
|
||||
superuser_id = get_session(conn, :superuser_id)
|
||||
target_user_id = get_session(conn, :target_user_id)
|
||||
|
||||
with {token, conn} <- ensure_user_token(conn),
|
||||
{user, _token_inserted_at} <- Accounts.get_user_by_session_token(token),
|
||||
superuser when not is_nil(superuser) <- Accounts.get_user(superuser_id) do
|
||||
assign(conn, :current_scope, Scope.for_impersonation(superuser, user))
|
||||
with superuser when not is_nil(superuser) <- Accounts.get_user(superuser_id),
|
||||
target_user when not is_nil(target_user) <- Accounts.get_user(target_user_id) do
|
||||
assign(conn, :current_scope, Scope.for_impersonation(superuser, target_user))
|
||||
else
|
||||
_ ->
|
||||
# Impersonation invalid, clear it
|
||||
conn
|
||||
|> delete_session(:superuser_id)
|
||||
|> delete_session(:target_user_id)
|
||||
|> delete_session(:impersonating)
|
||||
|> assign(:current_scope, Scope.for_user(nil))
|
||||
end
|
||||
|
|
@ -388,13 +389,27 @@ defmodule ToweropsWeb.UserAuth do
|
|||
|
||||
defp mount_current_scope(socket, session) do
|
||||
Phoenix.Component.assign_new(socket, :current_scope, fn ->
|
||||
if user_token = session["user_token"] do
|
||||
case Accounts.get_user_by_session_token(user_token) do
|
||||
{user, _token_inserted_at} -> Scope.for_user(user)
|
||||
nil -> Scope.for_user(nil)
|
||||
# Check if currently impersonating
|
||||
if session["impersonating"] do
|
||||
superuser_id = session["superuser_id"]
|
||||
target_user_id = session["target_user_id"]
|
||||
|
||||
with superuser when not is_nil(superuser) <- Accounts.get_user(superuser_id),
|
||||
target_user when not is_nil(target_user) <- Accounts.get_user(target_user_id) do
|
||||
Scope.for_impersonation(superuser, target_user)
|
||||
else
|
||||
_ -> Scope.for_user(nil)
|
||||
end
|
||||
else
|
||||
Scope.for_user(nil)
|
||||
# Normal authentication flow
|
||||
if user_token = session["user_token"] do
|
||||
case Accounts.get_user_by_session_token(user_token) do
|
||||
{user, _token_inserted_at} -> Scope.for_user(user)
|
||||
nil -> Scope.for_user(nil)
|
||||
end
|
||||
else
|
||||
Scope.for_user(nil)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
@ -431,9 +446,10 @@ defmodule ToweropsWeb.UserAuth do
|
|||
ip_address: ip
|
||||
})
|
||||
|
||||
# Store superuser ID in session and update scope
|
||||
# Store superuser ID and target user ID in session and update scope
|
||||
conn
|
||||
|> put_session(:superuser_id, superuser.id)
|
||||
|> put_session(:target_user_id, target_user.id)
|
||||
|> put_session(:impersonating, true)
|
||||
|> assign(:current_scope, Scope.for_impersonation(superuser, target_user))
|
||||
|> put_flash(:info, "Now impersonating #{target_user.email}")
|
||||
|
|
@ -467,6 +483,7 @@ defmodule ToweropsWeb.UserAuth do
|
|||
# Restore superuser session
|
||||
conn
|
||||
|> delete_session(:superuser_id)
|
||||
|> delete_session(:target_user_id)
|
||||
|> delete_session(:impersonating)
|
||||
|> assign(:current_scope, Scope.for_user(superuser))
|
||||
|> put_flash(:info, "Stopped impersonating")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue