smpallen99 / ex_admin

ExAdmin is an auto administration package for Elixir and the Phoenix Framework
MIT License
1.2k stars 273 forks source link

ExAdmin automatically picking up my User module #361

Open davejlong opened 7 years ago

davejlong commented 7 years ago

I'm using ExAdmin with Guardian and Ueberauth. Guardian and Ueberauth uses very simple user logic for now:

# lib/kcc/user.ex
defmodule KCC.User do
  @derive [Poison.Encoder]
  defstruct email: nil, name: nil
end

defmodule KCC.UserSerializer do
  @behaviour Guardian.Serializer

  alias KCC.User

  def for_token(user = %User{}), do: Poison.encode user
  def for_token(_), do: {:error, "Unknown resource type"}

  def from_token(sub) do
    case Poison.decode(sub, as: %User{}) do
      {:ok, user} -> {:ok, user}
      {:error, _} -> {:error, "Unknown resource type"}
    end
  end
end

The authentication config for ExAdmin is also pretty simple:

defimpl ExAdmin.Authentication, for: Plug.Conn do
  alias KCC.Router.Helpers
  alias KCC.Authentication, as: Auth

  def use_authentication?(_), do: true

  def current_user(conn), do: Auth.current_user(conn)

  def current_user_name(conn), do: Auth.current_user_name(conn)

  def session_path(conn, action), do: Helpers.auth_path(conn, action)
end

defmodule KCC.Authentication do
  def current_user(conn) do
    Guardian.Plug.current_resource(conn)
  end

  def current_user_name(conn) do
    conn |> current_user |> Map.get(:name)
  end
end

And I haven't configured ExAdmin to discover my User model:

config :ex_admin,
  repo: KCC.Repo,
  module: KCC,
  modules: [
    KCC.ExAdmin.Dashboard
  ]

After logging in, I get the following error:

[error] #PID<0.488.0> running KCC.Endpoint terminated
Server: localhost:4000 (http)
Request: GET /admin
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function KCC.User.__schema__/1 is undefined or private
        (kcc) KCC.User.__schema__(:primary_key)
        (ex_admin) lib/ex_admin/schema.ex:8: ExAdmin.Schema.primary_key/1
        (ex_admin) lib/ex_admin/schema.ex:23: ExAdmin.Schema.get_id/1
        (ex_admin) lib/ex_admin/utils.ex:201: ExAdmin.Utils.admin_resource_path/3
        (ex_admin) web/templates/themes/admin_lte2/layout/header.html.eex:22: ExAdmin.AdminLte2.LayoutView."header.html"/1
        (ex_admin) web/templates/layout/admin_lte2.html.eex:41: ExAdmin.LayoutView."admin_lte2.html"/1
        (phoenix) lib/phoenix/view.ex:335: Phoenix.View.render_to_iodata/3
        (phoenix) lib/phoenix/controller.ex:646: Phoenix.Controller.do_render/4
        (ex_admin) web/controllers/admin_controller.ex:1: ExAdmin.AdminController.action/2
        (ex_admin) web/controllers/admin_controller.ex:1: ExAdmin.AdminController.phoenix_controller_pipeline/2
        (kcc) lib/kcc/endpoint.ex:1: KCC.Endpoint.instrument/4
        (kcc) lib/phoenix/router.ex:261: KCC.Router.dispatch/2
        (kcc) web/router.ex:1: KCC.Router.do_call/2
        (kcc) lib/kcc/endpoint.ex:1: KCC.Endpoint.phoenix_pipeline/1
        (kcc) lib/plug/debugger.ex:123: KCC.Endpoint."call (overridable 3)"/2
        (kcc) lib/kcc/endpoint.ex:1: KCC.Endpoint.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) /Users/david/Projects/nde/kcc/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

So my question is what would cause ExAdmin to be trying to discover the schema of %KCC.User{}?

smpallen99 commented 7 years ago

The user is coming from Guardian.Plug.current_resource(conn). I suspect that its returning a simple struct and not an Ecto.Schema. Add an IO.inspect to verify.

defmodule KCC.Authentication do
  def current_user(conn) do
    Guardian.Plug.current_resource(conn)
    |> IO.inspect  # add this
  end
  # ...
end

If you have another schema for the user model, then you need to fetch it so the current_user above returns is.

davejlong commented 7 years ago

@smpallen99 my User module is not an Ecto schema. I was able to make it look like it by added __schema__/1 to my module, but I'm wondering if ExAdmin should be requiring the current_user object to be an Ecto model?

smpallen99 commented 7 years ago

If your up contributing a PR, you could test the current_user for __schema__ here and skip the profile menu item if its not set. Also needs to be done for the active_admin theme too.