elixirphoenix-frameworkphoenix-live-view

How to serve a different controller/liveviews from one route for different users roles


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?


Solution

  • 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