Current section

Files

Jump to
ex_admin_runtime web plugs swich_user.ex
Raw

web/plugs/swich_user.ex

defmodule ExAdmin.Plug.SwitchUser do
@moduledoc """
Allow users to switch to a different login.
Adds a drop down menu item on the page header with a list of all users.
Selecting a user, automatically logs out the current user and logs in
the selected user.
The login is automatic without requiring a password to be entered.
Use of this feature should be restricted to dev and test environments.
## Configuration
add the following to your project's `config/dev.exs` file
config :ex_admin_runtime,
logout_user: {Coherence.ControllerHelpers, :logout_user},
login_user: {Coherence.ControllerHelpers, :login_user}
add the following to your `web/route.ex` file
pipeline :protected do
plug :accepts, ["html"]
# ...
if Mix.env == :dev do
plug ExAdmin.Plug.SwitchUser
end
end
by default, the user's name for each entry in the drop down list is fetched
with the `:name` field of the user schema. See the following for examples on
how to change this default:
# change the field in `config/dev.exs`
config :ex_admin_runtime,
current_user_name: :full_name,
current_user_name: &MyProject.User.user_name/1,
current_user_name: {MyProject.User, :user_name}
# as an option to the plug call in `web/router.ex`
plug ExAdmin.Plug.SwitchUser, current_user_name: :full_name
plug ExAdmin.Plug.SwitchUser, &MyProject.User.user_name/1
plug ExAdmin.Plug.SwitchUser, {MyProject.User, :user_name}
"""
@behaviour Plug
import Plug.Conn
import ExAdmin.Authentication
alias ExAdmin.Utils
require Logger
def init(opts) do
unless Application.get_env(:ex_admin_runtime, :login_user) && Application.get_env(:ex_admin_runtime, :logout_user) do
raise """
:login_user and :logout_user must be configured to use ExAdmin.Plug.SwitchUser.
Please configure these and recompile your project.
"""
end
%{
current_user_id: opts[:current_user_id] || Application.get_env(:ex_admin_runtime, :current_user_id, :id),
current_user_name: opts[:current_user_name] || Application.get_env(:ex_admin_runtime, :current_user_name, :name),
repo: Application.get_env(:ex_admin_runtime, :repo),
}
end
def call(conn, opts) do
current_user(conn)
|> do_call(conn, opts)
end
def do_call(nil, conn, _), do: conn
def do_call(current_user, conn, opts) do
users = opts[:repo].all(current_user.__struct__)
|> Enum.map(fn user ->
name = get_user_name(user, opts[:current_user_name])
id = Map.get(user, opts[:current_user_id])
path = Utils.admin_path(:switch_user, [user.id])
{name, id, path}
end)
assign(conn, :switch_users, [Map.get(current_user, opts[:current_user_id]) | users])
end
defp get_user_name(user, name_opt) when is_function(name_opt), do: name_opt.(user)
defp get_user_name(user, name_opt) when is_atom(name_opt), do: Map.get(user, name_opt)
defp get_user_name(user, {mod, fun}), do: apply(mod, fun, [user])
end