Created a very basic Liveview application with phx.gen.auth.
scope "/", AppWeb do
pipe_through [:browser, :require_authenticated_user]
live_session :require_authenticated_user,
on_mount: [{AppWeb.UserAuth, :ensure_authenticated}] do
live "/users/settings", UserSettingsLive, :edit
end
end
scope "/", AppWeb do
pipe_through [:browser]
live_session :current_user,
on_mount: [{AppWeb.UserAuth, :mount_current_user}] do
live "/game/:slug", GameLive.Show
end
On the Game liveview page, if the user is logged in I just show if he’s favorited the game or not. But that same page can also be seen by anonymous users.
So far it all works perfectly.
But a nasty side effect of having two different live_session’s is that with navigating from the settings page to the game page, it triggers a full page reload.
What strategies do you recommend to address this situation?
After some noodling I ended up with this approach.
I moved all of my routes to the live_session :current_user to avoid the full page reloads. The site is much snappier now.
In the pages that I know require an authenticated user, I added this:
use MyAppWeb, :live_view
on_mount {MyAppWeb.UserAuth, [:ensure_authenticated, "/super-secret-page"]}
The string parameter is a redirect post-login so that people are sent back to where they were.
Finally in the user_auth.ex file, I pattern matched for this case.
def on_mount([:ensure_authenticated, user_return_to], _params, session, socket) do
socket = mount_current_user(session, socket)
if socket.assigns.current_user do
{:cont, socket}
else
socket =
socket
|> Phoenix.LiveView.put_flash(:error, "You must log in to access this page.")
|> Phoenix.LiveView.redirect(to: ~p"/users/log_in?continue=#{user_return_to}")
{:halt, socket}
end
end