PavelZX

PavelZX

Ecto.Association.NotLoaded

In Phx 1.3 this code works, but in Phx 1.4 doesn’t want.

  def index(conn, _params) do
    current_user = Guardian.Plug.current_resource(conn)

    owned_board = current_user
      |> assoc(:owned_board)
      |> board_preload_all
      |> Repo.all

    invited_board = current_user
      |> assoc(:board)
      |> not_owned_by(current_user.id)
      |> board_preload_all
      |> Repo.all

    render(conn, "index.json", owned_board: owned_board, invited_board: invited_board)
  end

Errors are obtained.

[error] #PID<0.501.0> running ImconWeb.Endpoint (connection #PID<0.500.0>, stream id 1) terminated
Server: caix.ru:4001 (http)
Request: POST /api/v1/sessions
** (exit) an exception was raised:
    ** (ArgumentError) argument error
        :erlang.apply(%Imcon.Auth.User{__meta__: #Ecto.Schema.Metadata<:loaded, "user">, board: #Ecto.Association.NotLoaded<association :board is not loaded>, email: "john@phoenix-trello.com", encrypted_password: "$2b$12$nn1jeBQwQms.Id2JOeb6..mi8UQQka8dyWNkh0WqmAm/hN0AQX9zW", first_name: "John", id: 1, inserted_at: ~N[2019-01-02 08:36:35.417355], is_admin: false, last_name: "Doe", owned_board: #Ecto.Association.NotLoaded<association :owned_board is not loaded>, password: nil, updated_at: ~N[2019-01-02 08:36:35.426004], user_board: #Ecto.Association.NotLoaded<association :user_board is not loaded>}, :config, [])
        (guardian) lib/guardian.ex:776: Guardian.token_module/1
        (guardian) lib/guardian.ex:576: Guardian.encode_and_sign/4
        (imcon) lib/imcon_web/controllers/api/v1/session_controller.ex:9: ImconWeb.SessionController.create/2

The configuration is such here.

[
  {:phoenix, "~> 1.4.0"},
  {:phoenix_pubsub, "~> 1.1.1"},
  {:phoenix_ecto, ">= 3.2.0 and < 3.5.0"},
  {:postgrex, ">= 0.0.0"},
  {:poison, ">= 0.0.0"},
  {:phoenix_html, "~> 2.12.0"},
  {:phoenix_live_reload, "~> 1.2.0", only: :dev},
  {:gettext, "~> 0.16.1"},
  {:cowboy, "~> 2.6.0"},
  {:plug_cowboy, "~> 2.0.0"},
  {:comeonin, "~> 4.1.1"},
  {:bcrypt_elixir, "~> 1.0.9"},
  {:guardian, "~> 1.1.1"},
  {:credo, "~> 0.10.2", only: [:dev, :test]},
  {:ex_machina, "~> 2.2.2"},
  {:exactor, "~> 2.2.4"},
  {:hound, "~> 1.0.2"},
  {:mix_test_watch, "~> 0.9.0", only: :dev},
  {:poolboy, "~> 1.5.1"}
]

Most Liked

van-mronov

van-mronov

As error message said the problem occurs in create action not in index.

PavelZX

PavelZX

If Erlang himself swears, then, is the error still covered in the communication modules with the database?

  defmodule ImconWeb.SessionController do
      use ImconWeb, :controller

  plug :scrub_params, "session" when action in [:create]

  def create(conn, %{"session" => session_params}) do
    case Imcon.Auth.authenticate(session_params) do
      {:ok, user} ->
        {:ok, jwt, _full_claims} = user |> Guardian.encode_and_sign(:token)

        conn
        |> put_status(:created)
        |> render("show.json", jwt: jwt, user: user)

      :error ->
        conn
        |> put_status(:unprocessable_entity)
        |> render("error.json")
    end
  end

  def delete(conn, _) do
    {:ok, claims} = Guardian.Plug.current_claims(conn)

    conn
    |> Guardian.Plug.current_token
    |> Guardian.revoke(claims)

    conn
    |> render("delete.json")
  end


  def unauthenticated(conn, _params) do
    conn
    |> put_status(:forbidden)
    |> render(ImconWeb.SessionView, "forbidden.json", error: "Not Authenticated")
  end

end

Based on various examples, I brought the authentication to a separate new context. I want to enter roles, for users, groups (teams), adding this context.

defmodule Imcon.Auth do

  import Ecto.Changeset
  import Plug.Conn
  
  alias Comeonin.Bcrypt

  alias Imcon.Repo
  alias Imcon.Auth.User

    # ... User

  def get_user(id), do: Repo.get(User, id)

  def fetch_assoc(%User{} = user, assoc \\ [:board, :user_board, :owned_board]) do
    Repo.preload(user, assoc)
  end

  @required_fields ~w(first_name last_name email password)
  @optional_fields ~w(encrypted_password)

  def create_user(%User{} = user, attrs) do
    user
    |> cast(attrs, @required_fields, @optional_fields)
    |> validate_format(:email, ~r/@/)
    |> validate_length(:password, min: 5)
    |> validate_confirmation(:password, message: "Password does not match")
    |> unique_constraint(:email, message: "Email already taken")
    |> generate_encrypted_password
  end

  def update_user(%User{} = user, attrs) do
    user
    |> cast(attrs, [:first_name, :last_name, :email], [:password])
    |> validate_required([:first_name, :email])
    |> generate_encrypted_password
    |> unique_constraint(:email)
  end

  defp generate_encrypted_password(current_changeset) do
    case current_changeset do
      %Ecto.Changeset{valid?: true, changes: %{password: password}} ->
        put_change(current_changeset, :encrypted_password, Comeonin.Bcrypt.hashpwsalt(password))
      _ ->
        current_changeset
    end
  end

  def load_current_user(conn, _) do
    conn
    |> assign(:current_user, Guardian.Plug.current_resource(conn))
    |> put_user_token(Guardian.Plug.current_resource(conn))
  end

  defp put_user_token(conn, user) do
    token = Phoenix.Token.sign(conn, "user socket", user.id)

    conn
    |> assign(:user_token, token)
  end

  def authenticate(%{"email" => email, "password" => password}) do
    user = Repo.get_by(User, email: String.downcase(email))

    case check_password(user, password) do
      true -> {:ok, user}
      _ -> :error
    end
  end

  defp check_password(user, password) do
    case user do
      nil -> Bcrypt.dummy_checkpw()
      _ -> Bcrypt.checkpw(password, user.encrypted_password)
    end
  end

end
van-mronov

van-mronov

The issue from the first post occurs in this line:

According to guardian docs the first argument is the module implementing actual encoding in callbacks, but you pass user struct as first arg.

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; somethi...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New

Other popular topics Top

axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48475 226
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42158 114
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39523 209
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

We're in Beta

About us Mission Statement