lib/mix/tasks/qs.gen.init_assigns.ex

defmodule Mix.Tasks.Qs.Gen.InitAssigns do
  use Mix.Task

  require Mix.Generator

  Mix.Generator.embed_template(:init_assigns, """
  defmodule <%= @web_module %>.InitAssigns do
    import Phoenix.LiveView
    alias <%= @context_module %>.Accounts

    def on_mount(:default, _params, session, socket) do
      {:cont,
      assign_new(socket, :current_user, fn ->
        Accounts.get_user_by_session_token(session["user_token"])
      end)}
    end

    def on_mount(:admin, _params, session, socket) do
      socket =
        assign_new(socket, :current_user, fn ->
          Accounts.get_user_by_session_token(session["user_token"])
        end)

      case :admin in socket.assigns.current_user.roles do
        true -> {:cont, socket}
        false -> {:halt, redirect(socket, to: "/login")}
      end
    end
  end
  """)

  @impl Mix.Task
  def run(_args) do
    base_name = Mix.Project.config() |> Keyword.fetch!(:app) |> to_string()
    context_module_path = base_name
    web_module_path = "#{base_name}_web"
    web_module = Macro.camelize(web_module_path)
    context_module = Macro.camelize(context_module_path)

    Mix.Generator.create_file(
      "lib/#{web_module_path}/live/init_assigns.ex",
      init_assigns_template(
        web_module: web_module,
        context_module: context_module
      )
    )

    Mix.shell().info("""
      Add to router.exs

      live_session :admin, on_mount: {#{web_module}.InitAssigns, :admin} do
        scope "/", #{web_module} do
          pipe_through [:browser, :require_authenticated_user]

          live "/example", ExampleLive.Index, :index
        end
      end
    """)
  end
end