danschultzer / phoenix_oauth2_provider

Get an OAuth 2 provider running in your phoenix with controllers, views and models in just two minutes
MIT License
84 stars 41 forks source link

Not able to post to oauth/applications #7

Closed suhaschitade closed 6 years ago

suhaschitade commented 6 years ago

Hi, Received below error when creating an application

expected changeset data to be a Elixir.Appointo.Accounts.User struct, got: %Appointo.Coherence.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, active: true, current_password: nil, current_sign_in_at: #Ecto.DateTime<2018-01-02 17:53:34>, current_sign_in_ip: "{127, 0, 0, 1}", email: "admin@appointo.com", failed_attempts: 0, id: 5, inserted_at: ~N[2018-01-01 10:19:07.874000], last_sign_in_at: #Ecto.DateTime<2018-01-02 17:44:40>, last_sign_in_ip: "{127, 0, 0, 1}", locked_at: nil, name: "admin", password: nil, password_confirmation: nil, password_hash: "$2b$12$6stKmoov8GslyA9C7mSy8.AnGbwWyQ4iaLubLx/FSxQaXmIq9u3MG", reset_password_sent_at: nil, reset_password_token: nil, roles: #Ecto.Association.NotLoaded<association :roles is not loaded>, sign_in_count: 9, unlock_token: nil, updated_at: ~N[2018-01-02 17:53:34.982000]}

I believe this might be due to resource_owner wrongly set. I have corrected it still issue remains

Regards,

suhaschitade commented 6 years ago

my configuration file contains

config :phoenix_oauth2_provider, PhoenixOauth2Provider,
  module: Appointo,
  current_resource_owner: :current_user,
  repo: Appointo.Repo,
  resource_owner: Appointo.Coherence.User
danschultzer commented 6 years ago

Can you post the stack trace? How does Appointo.Coherence.User look?

There's an example how a functional User module looks like here: https://github.com/danschultzer/phoenix_oauth2_provider/blob/master/test/support/user.ex

danschultzer commented 6 years ago

Since it asks for Appointo.Accounts.User struct I think there might be something in Appointo.Coherence.User causing this issue, but without a stack trace it's difficult to say.

suhaschitade commented 6 years ago
 ecto lib/ecto/changeset/relation.ex:190 Ecto.Changeset.Relation.assert_changeset_struct!/2
 ecto lib/ecto/changeset/relation.ex:148 Ecto.Changeset.Relation.do_change/4
 ecto lib/ecto/changeset/relation.ex:292 Ecto.Changeset.Relation.single_change/5
 ecto lib/ecto/changeset.ex:1049 Ecto.Changeset.put_change/7
 ecto lib/ecto/changeset.ex:1136 Ecto.Changeset.put_relation/5
 ex_oauth2_provider lib/ex_oauth2_provider/oauth_applications/oauth_applications.ex:211 ExOauth2Provider.OauthApplications.new_application_changeset/3
 ex_oauth2_provider lib/ex_oauth2_provider/oauth_applications/oauth_applications.ex:127 ExOauth2Provider.OauthApplications.create_application/2
 phoenix_oauth2_provider lib/phoenix_oauth2_provider/web/controllers/application_controller.ex:19 PhoenixOauth2Provider.ApplicationController.create/2
 phoenix_oauth2_provider lib/phoenix_oauth2_provider/web/controllers/application_controller.ex:1 PhoenixOauth2Provider.ApplicationController.action/2
 phoenix_oauth2_provider lib/phoenix_oauth2_provider/web/controllers/application_controller.ex:1 PhoenixOauth2Provider.ApplicationController.phoenix_controller_pipeline/2
 lib/appointo_web/endpoint.ex:1 AppointoWeb.Endpoint.instrument/4
 phoenix lib/phoenix/router.ex:278 Phoenix.Router.__call__/1
 lib/appointo_web/endpoint.ex:1 AppointoWeb.Endpoint.plug_builder_call/2
 lib/plug/debugger.ex:99 AppointoWeb.Endpoint."call (overridable 3)"/2
 lib/appointo_web/endpoint.ex:1 AppointoWeb.Endpoint.call/2
 plug lib/plug/adapters/cowboy/handler.ex:15 Plug.Adapters.Cowboy.Handler.upgrade/4
 cowboy c:/Users/reshmachitade/appointo/deps/cowboy/src/cowboy_protocol.erl:442 :cowboy_protocol.execute/4

Stacktrace

Coherence.User is as below

defmodule Appointo.Coherence.User do
  @moduledoc false
  use Ecto.Schema
  use Coherence.Schema
  alias Appointo.Accounts.Role

  schema "users" do
    field :name, :string
    field :email, :string
    field :active, :boolean, default: true
    many_to_many :roles, Role, join_through: "users_roles"
    coherence_schema()

    timestamps()
  end

  def changeset(model, params \\ %{}) do
    model
    |> cast(params, [:name, :email] ++ coherence_fields())
    |> validate_required([:name, :email])
    |> validate_format(:email, ~r/@/)
    |> unique_constraint(:email)
    |> validate_coherence(params)
  end

  def changeset(model, params, :password) do
    model
    |> cast(params, ~w(password password_confirmation reset_password_token reset_password_sent_at))
    |> validate_coherence_password_reset(params)
  end
end
danschultzer commented 6 years ago

Try recompile with mix deps.compile --all

suhaschitade commented 6 years ago

Tried. No luck, it results in same error.

danschultzer commented 6 years ago

Ok, so this error happens because the application resource owner has been set to Appointo.Accounts.User. The controller sends an Appointo.Coherence.User struct. But you've configured PhoenixOauth2Provider to use Appointo.Coherence.User as the resource owner, so I'm not sure where it goes wrong.

It might be a good idea to search for Appointo.Accounts.User to see where it is used, and if it interferes with the PhoenixOauth2Provider somewhere.

If you can't find the error, I can take a look at it if you create a demo repository.

suhaschitade commented 6 years ago

thank you. Here, I have setup the repo.

https://github.com/suhaschitade/appointo

Regards,

danschultzer commented 6 years ago

I've tried the repo and it works for me. I think it's just some compiled code that interferes.

You should try do a full clean and recompile (you can do the same by just deleting the _build directory):

mix clean
mix deps.clean --all
mix deps.get
mix deps.compile --all
mix compile

FWIW, I used the following controller test. It might be useful for your local testing (running mix test test/appointo_web/controllers/oauth_application_controller_test.exs):

# test/appointo_web/controllers/oauth_application_controller_test.exs
defmodule AppointoWeb.OauthApplicationControllerTest do
  use AppointoWeb.ConnCase
  alias Appointo.Coherence.User
  alias Appointo.Repo

  @create_attrs %{name: "Example", redirect_uri: "https://example.com"}

  setup %{conn: conn} do
    {:ok, user} = %User{}
    |> User.changeset(%{name: "John Doe", email: "user@example.com", password: "test", password_confirm: "test"})
    |> Repo.insert

    conn = assign conn, :current_user, user
    {:ok, conn: conn, user: user}
  end

  test "create/2 creates application and redirects to show when data is valid", %{conn: conn} do
    new_conn = post conn, oauth_application_path(conn, :create), oauth_application: @create_attrs

    assert %{uid: uid} = redirected_params(new_conn)
    assert redirected_to(new_conn) == oauth_application_path(new_conn, :show, uid)

    new_conn = get conn, oauth_application_path(conn, :show, uid)
    assert html_response(new_conn, 200) =~ "Application: "
  end
end

Also note that I found various compile/run issues, but rerunning the same commands fixed it. It could be that this is why PhoenixOauth2Provider expected the wrong struct in the first place.

suhaschitade commented 6 years ago

thank you, it worked. In nutshell, just need to clean, get and recompile everything. I can now build API wrapper to use this infrastructure ! Happy to close this.. Regards, Suhas