mirror of
https://github.com/team-alembic/ash_authentication_phoenix.git
synced 2024-09-19 13:03:50 +12:00
improvement: pass context down to all actions
This commit is contained in:
parent
9f5feedc7d
commit
a51bab698f
13 changed files with 142 additions and 18 deletions
|
@ -40,6 +40,7 @@ defmodule AshAuthentication.Phoenix.Components.MagicLink do
|
|||
required(:strategy) => AshAuthentication.Strategy.t(),
|
||||
optional(:overrides) => [module],
|
||||
optional(:current_tenant) => String.t(),
|
||||
optional(:context) => map(),
|
||||
optional(:auth_routes_prefix) => String.t()
|
||||
}
|
||||
|
||||
|
@ -50,7 +51,7 @@ defmodule AshAuthentication.Phoenix.Components.MagicLink do
|
|||
strategy = assigns.strategy
|
||||
subject_name = Info.authentication_subject_name!(strategy.resource)
|
||||
|
||||
form = blank_form(strategy)
|
||||
form = blank_form(strategy, assigns[:context] || %{})
|
||||
|
||||
socket =
|
||||
socket
|
||||
|
@ -59,6 +60,7 @@ defmodule AshAuthentication.Phoenix.Components.MagicLink do
|
|||
|> assign_new(:overrides, fn -> [AshAuthentication.Phoenix.Overrides.Default] end)
|
||||
|> assign_new(:label, fn -> nil end)
|
||||
|> assign_new(:current_tenant, fn -> nil end)
|
||||
|> assign_new(:context, fn -> %{} end)
|
||||
|> assign_new(:auth_routes_prefix, fn -> nil end)
|
||||
|
||||
{:ok, socket}
|
||||
|
@ -130,7 +132,7 @@ defmodule AshAuthentication.Phoenix.Components.MagicLink do
|
|||
|
||||
socket =
|
||||
socket
|
||||
|> assign(:form, blank_form(strategy))
|
||||
|> assign(:form, blank_form(strategy, socket.assigns[:context] || %{}))
|
||||
|
||||
socket =
|
||||
if flash do
|
||||
|
@ -153,7 +155,7 @@ defmodule AshAuthentication.Phoenix.Components.MagicLink do
|
|||
Map.get(params, param_key, %{})
|
||||
end
|
||||
|
||||
defp blank_form(strategy) do
|
||||
defp blank_form(strategy, context) do
|
||||
api = Info.authentication_domain!(strategy.resource)
|
||||
subject_name = Info.authentication_subject_name!(strategy.resource)
|
||||
|
||||
|
@ -163,7 +165,11 @@ defmodule AshAuthentication.Phoenix.Components.MagicLink do
|
|||
as: subject_name |> to_string(),
|
||||
id:
|
||||
"#{subject_name}-#{Strategy.name(strategy)}-#{strategy.request_action_name}" |> slugify(),
|
||||
context: %{strategy: strategy, private: %{ash_authentication?: true}}
|
||||
context:
|
||||
Ash.Helpers.deep_merge_maps(context, %{
|
||||
strategy: strategy,
|
||||
private: %{ash_authentication?: true}
|
||||
})
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -83,7 +83,8 @@ defmodule AshAuthentication.Phoenix.Components.Password do
|
|||
optional(:overrides) => [module],
|
||||
optional(:live_action) => :sign_in | :register,
|
||||
optional(:path) => String.t(),
|
||||
optional(:current_tenant) => String.t()
|
||||
optional(:current_tenant) => String.t(),
|
||||
optional(:context) => map()
|
||||
}
|
||||
|
||||
slot :sign_in_extra
|
||||
|
@ -143,6 +144,7 @@ defmodule AshAuthentication.Phoenix.Components.Password do
|
|||
|> assign_new(:reset_path, fn -> nil end)
|
||||
|> assign_new(:register_path, fn -> nil end)
|
||||
|> assign_new(:current_tenant, fn -> nil end)
|
||||
|> assign_new(:context, fn -> %{} end)
|
||||
|> assign_new(:auth_routes_prefix, fn -> nil end)
|
||||
|
||||
show =
|
||||
|
@ -167,6 +169,7 @@ defmodule AshAuthentication.Phoenix.Components.Password do
|
|||
label={false}
|
||||
overrides={@overrides}
|
||||
current_tenant={@current_tenant}
|
||||
context={@context}
|
||||
>
|
||||
<%= if @sign_in_extra do %>
|
||||
<div class={override_for(@overrides, :slot_class)}>
|
||||
|
@ -212,6 +215,7 @@ defmodule AshAuthentication.Phoenix.Components.Password do
|
|||
label={false}
|
||||
overrides={@overrides}
|
||||
current_tenant={@current_tenant}
|
||||
context={@context}
|
||||
>
|
||||
<%= if @register_extra do %>
|
||||
<div class={override_for(@overrides, :slot_class)}>
|
||||
|
@ -254,6 +258,7 @@ defmodule AshAuthentication.Phoenix.Components.Password do
|
|||
label={false}
|
||||
overrides={@overrides}
|
||||
current_tenant={@current_tenant}
|
||||
context={@context}
|
||||
>
|
||||
<%= if @reset_extra do %>
|
||||
<div class={override_for(@overrides, :slot_class)}>
|
||||
|
|
|
@ -45,6 +45,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.RegisterForm do
|
|||
optional(:overrides) => [module],
|
||||
optional(:live_action) => :sign_in | :register,
|
||||
optional(:current_tenant) => String.t(),
|
||||
optional(:context) => map(),
|
||||
optional(:auth_routes_prefix) => String.t()
|
||||
}
|
||||
|
||||
|
@ -80,6 +81,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.RegisterForm do
|
|||
|> assign_new(:inner_block, fn -> nil end)
|
||||
|> assign_new(:overrides, fn -> [AshAuthentication.Phoenix.Overrides.Default] end)
|
||||
|> assign_new(:current_tenant, fn -> nil end)
|
||||
|> assign_new(:context, fn -> %{} end)
|
||||
|> assign_new(:auth_routes_prefix, fn -> nil end)
|
||||
|
||||
{:ok, socket}
|
||||
|
@ -158,6 +160,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.RegisterForm do
|
|||
before_submit: fn changeset ->
|
||||
changeset
|
||||
|> Ash.Changeset.set_context(%{token_type: :sign_in})
|
||||
|> Ash.Changeset.set_context(socket.assigns[:context] || %{})
|
||||
|> Ash.Changeset.set_tenant(socket.assigns.current_tenant)
|
||||
end
|
||||
) do
|
||||
|
|
|
@ -46,6 +46,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.ResetForm do
|
|||
optional(:label) => String.t() | false,
|
||||
optional(:overrides) => [module],
|
||||
optional(:current_tenant) => String.t(),
|
||||
optional(:context) => map(),
|
||||
optional(:auth_routes_prefix) => String.t()
|
||||
}
|
||||
|
||||
|
@ -54,7 +55,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.ResetForm do
|
|||
@spec update(props, Socket.t()) :: {:ok, Socket.t()}
|
||||
def update(assigns, socket) do
|
||||
strategy = assigns.strategy
|
||||
form = blank_form(strategy)
|
||||
form = blank_form(strategy, assigns[:context] || %{})
|
||||
|
||||
socket =
|
||||
socket
|
||||
|
@ -64,6 +65,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.ResetForm do
|
|||
|> assign_new(:inner_block, fn -> nil end)
|
||||
|> assign_new(:overrides, fn -> [AshAuthentication.Phoenix.Overrides.Default] end)
|
||||
|> assign_new(:current_tenant, fn -> nil end)
|
||||
|> assign_new(:context, fn -> nil end)
|
||||
|> assign_new(:auth_routes_prefix, fn -> nil end)
|
||||
|
||||
{:ok, socket}
|
||||
|
@ -143,7 +145,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.ResetForm do
|
|||
|
||||
socket =
|
||||
socket
|
||||
|> assign(:form, blank_form(strategy))
|
||||
|> assign(:form, blank_form(strategy, socket.assigns[:context] || %{}))
|
||||
|
||||
socket =
|
||||
if flash do
|
||||
|
@ -166,7 +168,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.ResetForm do
|
|||
Map.get(params, param_key, %{})
|
||||
end
|
||||
|
||||
defp blank_form(%{resettable: resettable} = strategy) when not is_nil(resettable) do
|
||||
defp blank_form(%{resettable: resettable} = strategy, context) when not is_nil(resettable) do
|
||||
api = Info.authentication_domain!(strategy.resource)
|
||||
subject_name = Info.authentication_subject_name!(strategy.resource)
|
||||
|
||||
|
@ -177,7 +179,11 @@ defmodule AshAuthentication.Phoenix.Components.Password.ResetForm do
|
|||
id:
|
||||
"#{subject_name}-#{Strategy.name(strategy)}-#{resettable.request_password_reset_action_name}"
|
||||
|> slugify(),
|
||||
context: %{strategy: strategy, private: %{ash_authentication?: true}}
|
||||
context:
|
||||
Ash.Helpers.deep_merge_maps(context, %{
|
||||
strategy: strategy,
|
||||
private: %{ash_authentication?: true}
|
||||
})
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -47,6 +47,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.SignInForm do
|
|||
optional(:label) => String.t() | false,
|
||||
optional(:overrides) => [module],
|
||||
optional(:current_tenant) => String.t(),
|
||||
optional(:context) => map(),
|
||||
optional(:auth_routes_prefix) => String.t()
|
||||
}
|
||||
|
||||
|
@ -66,8 +67,12 @@ defmodule AshAuthentication.Phoenix.Components.Password.SignInForm do
|
|||
id:
|
||||
"#{subject_name}-#{Strategy.name(strategy)}-#{strategy.sign_in_action_name}"
|
||||
|> slugify(),
|
||||
tenant: socket.assigns[:current_tenant],
|
||||
context: %{strategy: strategy, private: %{ash_authentication?: true}}
|
||||
tenant: assigns[:current_tenant],
|
||||
context:
|
||||
Ash.Helpers.deep_merge_maps(assigns[:context] || %{}, %{
|
||||
strategy: strategy,
|
||||
private: %{ash_authentication?: true}
|
||||
})
|
||||
)
|
||||
|
||||
socket =
|
||||
|
@ -78,6 +83,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.SignInForm do
|
|||
|> assign_new(:inner_block, fn -> nil end)
|
||||
|> assign_new(:overrides, fn -> [AshAuthentication.Phoenix.Overrides.Default] end)
|
||||
|> assign_new(:current_tenant, fn -> nil end)
|
||||
|> assign_new(:context, fn -> %{} end)
|
||||
|> assign_new(:auth_routes_prefix, fn -> nil end)
|
||||
|
||||
{:ok, socket}
|
||||
|
@ -96,6 +102,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.SignInForm do
|
|||
<.form
|
||||
:let={form}
|
||||
for={@form}
|
||||
id={@form.id}
|
||||
phx-change="change"
|
||||
phx-submit="submit"
|
||||
phx-trigger-action={@trigger_action}
|
||||
|
@ -115,6 +122,7 @@ defmodule AshAuthentication.Phoenix.Components.Password.SignInForm do
|
|||
|
||||
<Password.Input.submit
|
||||
strategy={@strategy}
|
||||
id={@form.id <> "-submit"}
|
||||
form={form}
|
||||
action={:sign_in}
|
||||
disable_text={override_for(@overrides, :disable_button_text)}
|
||||
|
|
|
@ -50,7 +50,8 @@ defmodule AshAuthentication.Phoenix.Components.SignIn do
|
|||
optional(:path) => String.t(),
|
||||
optional(:reset_path) => String.t(),
|
||||
optional(:register_path) => String.t(),
|
||||
optional(:current_tenant) => String.t()
|
||||
optional(:current_tenant) => String.t(),
|
||||
optional(:context) => map()
|
||||
}
|
||||
|
||||
@doc false
|
||||
|
@ -81,6 +82,7 @@ defmodule AshAuthentication.Phoenix.Components.SignIn do
|
|||
|> assign_new(:reset_path, fn -> nil end)
|
||||
|> assign_new(:register_path, fn -> nil end)
|
||||
|> assign_new(:current_tenant, fn -> nil end)
|
||||
|> assign_new(:context, fn -> %{} end)
|
||||
|> assign_new(:auth_routes_prefix, fn -> nil end)
|
||||
|
||||
{:ok, socket}
|
||||
|
@ -109,6 +111,7 @@ defmodule AshAuthentication.Phoenix.Components.SignIn do
|
|||
register_path={@register_path}
|
||||
overrides={@overrides}
|
||||
current_tenant={@current_tenant}
|
||||
context={@context}
|
||||
/>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
@ -133,6 +136,7 @@ defmodule AshAuthentication.Phoenix.Components.SignIn do
|
|||
register_path={@register_path}
|
||||
overrides={@overrides}
|
||||
current_tenant={@current_tenant}
|
||||
context={@context}
|
||||
/>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
@ -155,6 +159,7 @@ defmodule AshAuthentication.Phoenix.Components.SignIn do
|
|||
live_action={@live_action}
|
||||
overrides={@overrides}
|
||||
current_tenant={@current_tenant}
|
||||
context={@context}
|
||||
/>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -99,6 +99,7 @@ defmodule AshAuthentication.Phoenix.LiveSession do
|
|||
tenant = session["tenant"]
|
||||
|
||||
socket = assign(socket, current_tenant: tenant)
|
||||
context = session["context"] || %{}
|
||||
|
||||
socket =
|
||||
socket
|
||||
|
@ -115,7 +116,10 @@ defmodule AshAuthentication.Phoenix.LiveSession do
|
|||
assign_new(socket, current_subject_name, fn ->
|
||||
if value = session[subject_name] do
|
||||
# credo:disable-for-next-line Credo.Check.Refactor.Nesting
|
||||
case AshAuthentication.subject_to_user(value, resource, tenant: tenant) do
|
||||
case AshAuthentication.subject_to_user(value, resource,
|
||||
tenant: tenant,
|
||||
context: context
|
||||
) do
|
||||
{:ok, user} -> user
|
||||
_ -> nil
|
||||
end
|
||||
|
@ -155,10 +159,12 @@ defmodule AshAuthentication.Phoenix.LiveSession do
|
|||
session
|
||||
|> Map.put(subject_name, AshAuthentication.user_to_subject(user))
|
||||
|> Map.put("tenant", Ash.PlugHelpers.get_tenant(conn))
|
||||
|> Map.put("context", Ash.PlugHelpers.get_context(conn))
|
||||
|
||||
_ ->
|
||||
session
|
||||
|> Map.put("tenant", Ash.PlugHelpers.get_tenant(conn))
|
||||
|> Map.put("context", Ash.PlugHelpers.get_context(conn))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -32,6 +32,7 @@ defmodule AshAuthentication.Phoenix.ResetLive do
|
|||
|> assign(overrides: overrides)
|
||||
|> assign_new(:otp_app, fn -> nil end)
|
||||
|> assign(:current_tenant, session["tenant"])
|
||||
|> assign(:context, session["context"] || %{})
|
||||
|
||||
{:ok, socket}
|
||||
end
|
||||
|
@ -56,6 +57,7 @@ defmodule AshAuthentication.Phoenix.ResetLive do
|
|||
token={@token}
|
||||
overrides={@overrides}
|
||||
current_tenant={@current_tenant}
|
||||
context={@context}
|
||||
/>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -403,6 +403,8 @@ defmodule AshAuthentication.Phoenix.Router do
|
|||
|
||||
@doc false
|
||||
def generate_session(conn, session) do
|
||||
Map.put(session, "tenant", Ash.PlugHelpers.get_tenant(conn))
|
||||
session
|
||||
|> Map.put("tenant", Ash.PlugHelpers.get_tenant(conn))
|
||||
|> Map.put("context", Ash.PlugHelpers.get_context(conn))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,6 +37,7 @@ defmodule AshAuthentication.Phoenix.SignInLive do
|
|||
|> assign(:reset_path, session["reset_path"])
|
||||
|> assign(:register_path, session["register_path"])
|
||||
|> assign(:current_tenant, session["tenant"])
|
||||
|> assign(:context, session["context"] || %{})
|
||||
|> assign(:auth_routes_prefix, session["auth_routes_prefix"])
|
||||
|
||||
{:ok, socket}
|
||||
|
@ -64,6 +65,7 @@ defmodule AshAuthentication.Phoenix.SignInLive do
|
|||
id={override_for(@overrides, :sign_in_id, "sign-in")}
|
||||
overrides={@overrides}
|
||||
current_tenant={@current_tenant}
|
||||
context={@context}
|
||||
/>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
defmodule AshAuthentication.Phoenix.SignInTest do
|
||||
@moduledoc false
|
||||
use ExUnit.Case
|
||||
use ExUnit.Case, async: false
|
||||
import Phoenix.ConnTest
|
||||
import Phoenix.LiveViewTest
|
||||
require Ash.Query
|
||||
|
||||
@endpoint AshAuthentication.Phoenix.Test.Endpoint
|
||||
|
||||
setup do
|
||||
|
@ -15,4 +17,57 @@ defmodule AshAuthentication.Phoenix.SignInTest do
|
|||
assert {:ok, _view, html} = live(conn)
|
||||
assert html =~ "Sign in"
|
||||
end
|
||||
|
||||
test "sign_in routes allow a user to sign in", %{conn: conn} do
|
||||
Example.Accounts.User
|
||||
|> Ash.Changeset.for_create(:register_with_password, %{
|
||||
email: "zach@example.com",
|
||||
password: "so-secure!",
|
||||
password_confirmation: "so-secure!"
|
||||
})
|
||||
|> Ash.create!()
|
||||
|
||||
conn = get(conn, "/sign-in")
|
||||
assert {:ok, lv, _html} = live(conn)
|
||||
|
||||
lv
|
||||
|> form("#user-password-sign-in-with-password", %{
|
||||
"user" => %{
|
||||
"email" => "zach@example.com",
|
||||
"password" => "so-secure!"
|
||||
}
|
||||
})
|
||||
|> render_submit()
|
||||
|
||||
assert_received {_ref, {:redirect, _topic, %{to: new_to}}}
|
||||
assert %{path: "/auth/user/password/sign_in_with_token"} = URI.parse(new_to)
|
||||
end
|
||||
|
||||
describe "context" do
|
||||
setup do
|
||||
Application.put_env(:ash_authentication_phoenix, :test_context, %{should_fail: true})
|
||||
|
||||
on_exit(fn ->
|
||||
Application.put_env(:ash_authentication_phoenix, :test_context, nil)
|
||||
end)
|
||||
end
|
||||
|
||||
test "context is preserved across requests", %{conn: conn} do
|
||||
Process.put(:test_context, %{should_fail: true})
|
||||
conn = get(conn, "/sign-in")
|
||||
assert {:ok, lv, _html} = live(conn)
|
||||
|
||||
result =
|
||||
lv
|
||||
|> form("#user-password-sign-in-with-password", %{
|
||||
"user" => %{
|
||||
"email" => "zach@example.com",
|
||||
"password" => "so-secure!"
|
||||
}
|
||||
})
|
||||
|> render_submit()
|
||||
|
||||
assert result =~ "I cant let you do that dave"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,6 +51,22 @@ defmodule Example.Accounts.User do
|
|||
end
|
||||
end
|
||||
|
||||
preparations do
|
||||
prepare fn query, _ ->
|
||||
if query.action.name == :sign_in_with_password && query.context[:should_fail] do
|
||||
Ash.Query.add_error(
|
||||
query,
|
||||
Ash.Error.Query.InvalidArgument.exception(
|
||||
field: :email,
|
||||
message: "I cant let you do that dave."
|
||||
)
|
||||
)
|
||||
else
|
||||
query
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key :id
|
||||
|
||||
|
@ -111,10 +127,9 @@ defmodule Example.Accounts.User do
|
|||
tokens do
|
||||
enabled?(true)
|
||||
token_resource(Example.Accounts.Token)
|
||||
store_all_tokens? true
|
||||
|
||||
signing_secret(fn _, _ ->
|
||||
Application.fetch_env(:ash_authentication_phoenix, :signing_secret)
|
||||
end)
|
||||
signing_secret("fake_secret")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ defmodule AshAuthentication.Phoenix.Test.Router do
|
|||
plug :put_secure_browser_headers
|
||||
|
||||
plug :load_from_session
|
||||
plug :put_test_context
|
||||
end
|
||||
|
||||
scope "/", AshAuthentication.Phoenix.Test do
|
||||
|
@ -85,6 +86,14 @@ defmodule AshAuthentication.Phoenix.Test.Router do
|
|||
|
||||
live("/", HomeLive, :index)
|
||||
end
|
||||
|
||||
@doc false
|
||||
def put_test_context(conn, _) do
|
||||
case Application.get_env(:ash_authentication_phoenix, :test_context) do
|
||||
nil -> conn
|
||||
context -> Ash.PlugHelpers.set_context(conn, context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmodule AshAuthentication.Phoenix.Test.Endpoint do
|
||||
|
|
Loading…
Reference in a new issue