Show username in _navbar

Good night
I am currently trying to display the username that is attached to my template.
Ex:
User will log in to my page, after logging in he will be able to see the exit button and next to his username.

I have made the following changes:
Could help me identify where the error is?

Helpers

defmodule MyprojectWeb.Helpers.Auth do
    def signed_in?(conn) do
        user_id = Plug.Conn.get_session(conn, :current_user_id)
        if user_id, do: !!Myproject.Repo.get(Myproject.Accounts.User, user_id)
    end
end

_navbar.html.eex

%= if signed_in?(@conn) do %>

          **<%= if signed_in?(@conn) == @conn.assigns[:users] do %>**
**          <h1> <%= link signed_in?(@conn).nome %></h1>**
**          <% end %></span>&ensp;**

<%= link "Sair", to: session_path(@conn, :delete), method: :delete, class: "btn btn-outline-success my-2 my-sm-0" %>
<% else %>
<%= link "Login", to: session_path(@conn, :new), class: "btn btn-outline-success my-2 my-sm-0" %>
<% end %>

At the moment the only thing that is not working and get the name of the user.

Instead of fetching user and throwing it away, fetch user record from user id and assign it to something, you’ll probably want to do it in a plug. Then just use:

user = Myproject.Repo.get(Myproject.Accounts.User, user_id)
Plug.Conn.assign(:current_user, user)

…

conn.assigns[:current_user].name

Myproject.Repo.get might return nil, and which would make conn.assigns[:current_user].name evaluate to nil.name which would fail with a not-quite-obvious error message. Or if :current_user assign is not set, conn.assigns[:current_user].name would again evaluate to nil.name.

So I’d suggest to add a helper function like into the view module that renders the navbar

@spec current_user_name(Plug.Conn.t()) :: String.t() | nil
def current_user_name(conn) do
  if current_user = conn.assigns[:current_user] do
    current_user.name
  end
end
1 Like

Usually it’s

def logged_in?(conn)
  !!conn.assigns[:current_user]
end

def current_user(conn) do
  conn.assigns[:current_user]
end
<%= if logged_in?(@conn) do %>
 <foo> <%= current_user(@conn).name %> </foo>
<% end %>

or so

@thousandsofthem
I tried to apply as requested.
But without success.

def logged_in?(conn)
  !!conn.assigns[:current_user]
end

def current_user(conn) do
  conn.assigns[:current_user]
end
<%= if logged_in?(@conn) do %>
 <foo> <%= current_user(@conn).name %> </foo>
<% end %>

Returns the following error.

== Compilation error in file lib/myproject_web/views/indicacao_view.ex ==
** (CompileError) lib/myproject_web/views/indicacao_view.ex:70: undefined function logged_in?/1
(elixir) src/elixir_locals.erl:108: :elixir_locals.“-ensure_no_undefined_local/3-lc$^0/1-0-”/2
(elixir) src/elixir_locals.erl:109: anonymous fn/3 in :elixir_locals.ensure_no_undefined_local/3
(stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:230: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

@idi527
How would it look in the _navbar template, your example?

defmodule MyprojectWeb.IndicacaoView do
  # ...
  @spec current_user_name(Plug.Conn.t()) :: String.t() | nil
  def current_user_name(conn) do
    if current_user = conn.assigns[:current_user] do
      current_user.name
    end
  end
end
# in the template
Name: <%= current_user_name(@conn) %>
1 Like

The code passed, was able to execute without any error.

But it does not return, no value.

  1. you can import functions globally, e.g.
defmodule MyprojectWeb.FoobarView do
  def logged_in?(conn) do
....
end

in web.ex:

...
  def view do
    quote do
      ...
      import MyprojectWeb.FoobarView
   end
end

Now all the functions in MyprojectWeb.FoobarView will be available in any template

  1. Do not forget to load and set current_user value before using it. I recommend doing in a custom Plug
1 Like

Would you have any examples of how to do this?
Custom Plug

When I run it, it returns me the following error:

function nil.nome/0 is undefined

I got it, thank you
Here’s how I managed.

Inside the controller


plug :check_auth when action in [:index, :new, :create, :edit, :update, :delete]

defp check_auth(conn, _args) do
  if user_id = get_session(conn, :current_user_id) do
  current_user = Myproject.Accounts.get_user!(user_id)

  conn
    |> assign(:current_user, current_user)
  else
    conn
    |> put_flash(:error, "You need to be signed in to access that page.")
    |> redirect(to: Routes.page_path(conn, :index))
    |> halt()
  end
end

Thank you all.