Skip to content

Commit

Permalink
Handle invited user in controller
Browse files Browse the repository at this point in the history
  • Loading branch information
danschultzer committed Mar 9, 2019
1 parent 46c06af commit 2e72541
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 7 deletions.
6 changes: 5 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ config :pow_assent, PowAssent.Test.EmailConfirmation.Phoenix.Endpoint,
secret_key_base: String.duplicate("abcdefghijklmnopqrstuvxyz0123456789", 2),
render_errors: [view: PowAssent.Test.Phoenix.ErrorView, accepts: ~w(html json)]

config :pow_assent, PowAssent.Test.NoRegistration.Phoenix.Endpoint,
config :pow_assent, PowAssent.Test.Invitation.Phoenix.Endpoint,
secret_key_base: String.duplicate("abcdefghijklmnopqrstuvxyz0123456789", 2),
render_errors: [view: PowAssent.Test.Phoenix.ErrorView, accepts: ~w(html json)]

config :pow_assent, PowAssent.Test.NoRegistration.Phoenix.Endpoint,
secret_key_base: String.duplicate("abcdefghijklmnopqrstuvxyz0123456789", 2),
render_errors: [view: PowAssent.Test.Phoenix.ErrorView, accepts: ~w(html json)]

Expand Down
30 changes: 25 additions & 5 deletions lib/pow_assent/phoenix/controllers/authorization_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule PowAssent.Phoenix.AuthorizationController do

plug :require_authenticated when action in [:delete]
plug :assign_callback_url when action in [:new, :callback]
plug :load_user_by_invitation_token when action in [:callback]

@spec process_new(Conn.t(), map()) :: {:ok, binary(), Conn.t()} | {:error, any(), Conn.t()}
def process_new(conn, %{"provider" => provider}) do
Expand All @@ -19,13 +20,17 @@ defmodule PowAssent.Phoenix.AuthorizationController do
def respond_new({:ok, url, conn}) do
conn
|> maybe_store_state()
|> maybe_store_invitation_token()
|> redirect(external: url)
end
def respond_new({:error, error, _conn}), do: handle_strategy_error(error)

defp maybe_store_state(%{private: %{pow_assent_state: state}} = conn), do: store_state(conn, state)
defp maybe_store_state(conn), do: conn

defp maybe_store_invitation_token(%{params: %{"invitation_token" => token}} = conn), do: store_invitation_token(conn, token)
defp maybe_store_invitation_token(conn), do: conn

@spec process_callback(Conn.t(), map()) :: {:ok, Conn.t()} | {:error, Conn.t()} | {:error, {atom(), map()} | map(), Conn.t()}
def process_callback(conn, %{"provider" => provider} = params) do
conn
Expand All @@ -41,10 +46,13 @@ defmodule PowAssent.Phoenix.AuthorizationController do
end
end

defp handle_callback({:ok, user, conn}, provider) do
defp handle_callback({:ok, user_params, %{assigns: %{invited_user: invited_user}} = conn}, provider) do
authenticate_or_create_identity(invited_user, provider, user_params, conn)
end
defp handle_callback({:ok, user_params, conn}, provider) do
conn
|> Pow.Plug.current_user()
|> authenticate_or_create_identity(provider, user, conn)
|> authenticate_or_create_identity(provider, user_params, conn)
end
defp handle_callback({:error, error, _conn}, _provider), do: handle_strategy_error(error)

Expand Down Expand Up @@ -154,14 +162,26 @@ defmodule PowAssent.Phoenix.AuthorizationController do
assign(conn, :callback_url, url)
end

defp store_state(conn, state) do
Conn.put_session(conn, :pow_assent_state, state)
end
defp store_state(conn, state), do: Conn.put_session(conn, :pow_assent_state, state)

defp fetch_state(%{private: %{plug_session: %{"pow_assent_state" => state}}} = conn) do
{state, Conn.put_session(conn, :pow_assent_state, nil)}
end
defp fetch_state(conn), do: conn

defp store_invitation_token(conn, token), do: Conn.put_session(conn, :pow_assent_invitation_token, token)

defp load_user_by_invitation_token(%{private: %{plug_session: %{"pow_assent_invitation_token" => token}}} = conn, _opts) do
conn = Conn.delete_session(conn,:pow_assent_invitation_token)

conn
|> PowInvitation.Plug.invited_user_from_token(token)
|> case do
nil -> conn
user -> PowInvitation.Plug.assign_invited_user(conn, user)
end
end
defp load_user_by_invitation_token(conn, _opts), do: conn

defp handle_strategy_error(error), do: raise error
end
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ defmodule PowAssent.Phoenix.AuthorizationControllerTest do
assert Plug.Conn.get_session(conn, :pow_assent_state)
end

test "redirects with invitation_token saved", %{conn: conn} do
conn = get conn, Routes.pow_assent_authorization_path(conn, :new, @provider, invitation_token: "token")

assert Plug.Conn.get_session(conn, :pow_assent_invitation_token) == "token"
end

test "with error", %{conn: conn, bypass: bypass} do
put_oauth2_env(bypass, fail_authorize_url: true)

Expand Down Expand Up @@ -86,7 +92,6 @@ defmodule PowAssent.Phoenix.AuthorizationControllerTest do

assert redirected_to(conn) == "/session_created"
assert get_flash(conn, :info) == "signed_in_test_provider"
assert Pow.Plug.current_user(conn) == user
refute Plug.Conn.get_session(conn, :pow_assent_state)
end

Expand Down Expand Up @@ -167,6 +172,24 @@ defmodule PowAssent.Phoenix.AuthorizationControllerTest do
end
end

alias PowAssent.Test.Invitation.Phoenix.Endpoint, as: InvitationEndpoint
describe "GET /auth/:provider/callback as authentication with invitation" do
test "with invitation_token updates user as accepted invtation", %{conn: conn, bypass: bypass} do
expect_oauth2_flow(bypass, user: %{uid: "new_identity"})

conn =
conn
|> Plug.Conn.put_session(:pow_assent_state, "token")
|> Plug.Conn.put_session(:pow_assent_invitation_token, "token")
|> Phoenix.ConnTest.dispatch(InvitationEndpoint, :get, Routes.pow_assent_authorization_path(conn, :callback, @provider, @callback_params))

assert redirected_to(conn) == "/session_created"
assert get_flash(conn, :info) == "signed_in_test_provider"
refute Plug.Conn.get_session(conn, :pow_assent_invitation_token)
refute Plug.Conn.get_session(conn, :pow_assent_state)
end
end

alias PowAssent.Test.NoRegistration.Phoenix.Endpoint, as: NoRegistrationEndpoint
describe "GET /auth/:provider/callback as authentication with missing registration routes" do
test "can't register", %{conn: conn, bypass: bypass} do
Expand Down
33 changes: 33 additions & 0 deletions test/support/extensions/invitation/phoenix/endpoint.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule PowAssent.Test.Invitation.Phoenix.Endpoint do
@moduledoc false
use Phoenix.Endpoint, otp_app: :pow_assent

plug Plug.RequestId
plug Plug.Logger

plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Phoenix.json_library()

plug Plug.MethodOverride
plug Plug.Head

plug Plug.Session,
store: :cookie,
key: "_binaryid_key",
signing_salt: "secret"

plug Pow.Plug.Session,
user: PowAssent.Test.Invitation.Users.User,
routes_backend: PowAssent.Test.Phoenix.Routes,
messages_backend: PowAssent.Test.Phoenix.Messages,
mailer_backend: PowAssent.Test.Phoenix.MailerMock,
repo: PowAssent.Test.Invitation.RepoMock,
otp_app: :pow_assent,
pow_assent: [
user_identities_context: PowAssent.Test.UserIdentitiesMock
]

plug PowAssent.Test.Phoenix.Router
end
9 changes: 9 additions & 0 deletions test/support/extensions/invitation/repo_mock.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule PowAssent.Test.Invitation.RepoMock do
@moduledoc false

alias PowAssent.Test.Invitation.Users.User

@user %User{id: 1, email: "[email protected]"}

def get_by(User, [invitation_token: "token"]), do: %{@user | invitation_token: "token"}
end
1 change: 1 addition & 0 deletions test/test_helper.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ Ecto.Adapters.SQL.Sandbox.mode(PowAssent.Test.Ecto.Repo, :manual)

{:ok, _pid} = PowAssent.Test.Phoenix.Endpoint.start_link()
{:ok, _pid} = PowAssent.Test.EmailConfirmation.Phoenix.Endpoint.start_link()
{:ok, _pid} = PowAssent.Test.Invitation.Phoenix.Endpoint.start_link()
{:ok, _pid} = PowAssent.Test.NoRegistration.Phoenix.Endpoint.start_link()

0 comments on commit 2e72541

Please sign in to comment.