Accessing session values in templates

I’m making a simple passwordless authentication and I use session to persist the current logged in.

In my shared header partial template:

 <div id="user-details">
    <%= if signed_in?(@conn) do %>
        <div id="user">should be the nickname that is stored in the session</div>
        <button>Sign Out</button>
    <% else %>
        <a href="<%= Routes.session_path(@conn, :index) %>">Sign In</a>
    <% end %>
</div>

The signed_in? just checks if the :current_user session value is nil or not.

In my session controller I use put_session to store the info to the session.and redirects to home page

  def create(conn, %{"user" => %{"nickname" => nickname}}) do
    conn
    |> put_session(:current_user, nickname)
    |> redirect(to: Routes.page_path(conn, :index))
  end

My question is how do I access the session directly in the template.
I was able to find the session value through inspect conn

:plug_session => %{"_csrf_token" => "WUwySjFop7p-Que81gOnBKQq", "current_user" => "Vails"}

Any help would do.
Thank you.

I think that should do the trick:

@conn.private.plug_session["current_user"]

In your code you are using put_session. This comes from Plug.Conn.

There is also a Plug.Conn.get_session where you pass in the conn struct and a key you want to retrieve from the session.

Hope this helps

There are multiple options; (if the question is how to access the session ‘directly’)

First, via a helper inside your your_app_web.ex file for the view (should be in the lib folder), it should then exist everywhere where you are rendering a template:

# inside your_app_web.ex file 
  def view do
    quote do
     ... 

      # add this function (better to put it in another file and import it here as a helper)
      def current_user(conn) do
        Plug.Conn.get_session(conn, :current_user)
      end
    end
  end

# Now inside your templates you can use it as:
<%= current_user(@conn) %>

Second, you could also call <%= Plug.Conn.get_session(@conn, :current_user) %> raw inside your template i guess?

Third and last method; you could do is somewhere in the pipeline make a plug that pulls out the wanted session var(s) (with above line) and put it in the conn.assigns, those should then be available in the template with @current_user. This is a bit more implicit because that @current_user will be ‘magically’ be available but it’s not unreasonable to do such a thing for a couple of big ‘global’/often used variables.
It would look like this:

# in your router.ex
defmodule YourAppWeb.Router do
  use YourAppWeb, :router
  import YourAppWeb.SessionToAssignPlug

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug :expose_session_variable_as_assign, :current_user # add this line
  end
  ...

# define this 'plug' somewhere:
defmodule YourAppWeb.SessionToAssignPlug do
  import Plug.Conn

  def expose_session_variable_as_assign(conn, variable_name) do
    session_variable = get_session(conn, variable_name)
    assign(conn, variable_name, session_variable)
  end
end

# now in your templates you can just do:
<%= @current_user %>

Hope that helps!

4 Likes

This will do.
Thanks

I hadn’t ever thought of having a plug that puts them in the conn assigns. Great idea!