How can I define my Plug/Phoenix routes so that I have a single set of URLs, but show different content depending on what kind of user is logged in?
Eg, a user should visit /home
and see a list of posts, an admin should visit /home
and see a list of users, or children see a list of activities and parents see a list of test scores.
The pages should have wildly different content and behaviours, different root layouts, functionality and features, etc.
Do I have to dispatch to one "global" HomeController(Live)
and mix it all in together?
Since you can't forward controller actions using plugs
from your router
, the cleanest option would be having 3 routes, eg: /home
, /admin/home
and /user/home
then handling the redirect. You can also reduce to 2 routes and handle the redirect from the user one.
Eg: /home
forwards to HomeController#index
When user is marked as an admin, controller redirects to /admin/home
, otherwise renders user home's template.
Redirects could also be done better using a Plug
Otherwise, if you still want to keep only one route, you'll want to make your checks directly in the HomeController#index
then render the correct layout and template.
Eg:
defmodule MyAppWeb.HomeController do
def index(conn, _params), do: render_index(conn)
defp render_index(%{assigns: %{admin: true}}) do
conn
|> put_layout(html: {MyApp.Layouts, :admin_layout})
|> render(:admin_index)
end
defp render_index(%{assigns: %{admin: false}}) do
conn
|> put_layout(html: {MyApp.Layouts, :user_layout})
|> render(:user_index)
end
end