Current user in Phoenix LiveView

So I’m stuck here with session problems. I set current user to session in a plug because there is no other way to get data from conn to live view socket.

defp current_user(conn, _) do
  put_session(conn, :current_user, conn.assigns.current_user)
end

Than I assign it into socket in mount. So far so good. But it all falls apart the moment I change pages in live view. I have just phoenix generated live views. I was not able to access the user in def handle_event("save", %{"profile" => profile_params}, socket) no matter what I did. It simply vanishes somewhere along the way. I’m not able to figure out why. I tried everything I could to IO.inspect(socket) to find out where I loose this data and I was not able to figure it out.

Don’t worry I’ve already read “Pass in session data to a live view when instigated via a live route?”. But it’s not very useful in my case. I’ve already worked around the issue mentioned there.

1 Like

This can be helpful, but I have not tested it with liveview:

Section: Override action/2 in your controllers

2 Likes

Do you assign the :current_user in mount in all of your liveviews? Since you mention that it breaks when you change pages.

There’s a very good reason for this limitation: Data passed to liveviews will be serialized, put in the html and sent back by the client to start the liveview process via the websocket connection. Therefore you want to keep the data in there as minimal as possible. For authentication usually the user id is enough. In mount you can then fetch the actual user struct.

With assign_new you also have the option to pull already loaded data (e.g. by some plug) out of conn.assigns for the static render happening in the initial http request.

2 Likes

Sure I assign it to socket. assign(socket, profiles: fetch_profiles(), user_id: session["user_id"])
Basically when I click on this link I loose all data in assigns. <%= live_patch "New Profile", to: Routes.user_profile_index_path(@socket, :new) %>

This all happens when I used mix phx.gen.live. As I can see from docs assigns don’t change right after I change URL. Phoenix.LiveView — Phoenix LiveView v0.20.2

One more thing I noticed. I don’t have assigns from index.ex in form_component.ex. This is the problem I need to solve. Unfortunately it was not obvious at first glance.

EDIT:
I didn’t look at the index.html.leex. Because I thought code this important would not be hiding in templates. Anyway I need to define it here

  <%= live_modal @socket, RoyalWeb.User.ProfileLive.FormComponent,
+   user_id: @user_id, 
    id: @profile.id || :new,
    title: @page_title,
    action: @live_action,
    profile: @profile,
    return_to: Routes.user_profile_index_path(@socket, :index) %>
<% end %>
4 Likes

I had the exact same issue today. Same solution too. Had to pass the user_id thru the template.
Now I was wondering if this kind of data could be kept only on the back end side without passing to the client which he surely not need to know or edit. Would like to keep the user_id only attached to the beam process state on the backend site.

Up to 0.18.13, the doc of Phoenix LiveView has a dedicated section on this topic, you can check it out:

https://hexdocs.pm/phoenix_live_view/0.18.13/security-model.html

1 Like