diff --git a/CHANGELOG.md b/CHANGELOG.md index 6caec86..a8c6df0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [`PowAssent.Phoenix.ViewHelpers`] `PowAssent.Phoenix.ViewHelpers.authorization_link/3` now accepts block argument * [`PowAssent.Phoenix.ViewHelpers`] `PowAssent.Phoenix.ViewHelpers.deauthorization_link/3` now accepts block argument +* [`PowAssent.Phoenix.ViewHelpers`] `PowAssent.Phoenix.ViewHelpers.authorization_links/2` now accepts link options or callback method as second argument ## v0.4.8 (2020-05-18) diff --git a/lib/pow_assent/phoenix/views/view_helpers.ex b/lib/pow_assent/phoenix/views/view_helpers.ex index 592a3b9..ed0654f 100644 --- a/lib/pow_assent/phoenix/views/view_helpers.ex +++ b/lib/pow_assent/phoenix/views/view_helpers.ex @@ -16,18 +16,43 @@ defmodule PowAssent.Phoenix.ViewHelpers do If a user is assigned to the conn, the authorized providers for a user will be looked up with `PowAssent.Plug.providers_for_current_user/1`. `deauthorization_link/2` will be used for any already authorized providers. + + The second argument may be link options passed on to `authorization_link/2` + or `deauthorization_link/2` respectively. It may also be a method that + handles render callback as seen in the example below. + + ## Example + + ViewHelpers.provider_links @conn, fn provider, providers_for_user -> + if provider in providers_for_user do + ViewHelpers.deauthorization_link @conn, provider do + Tag.content_tag(:span, "Remove \#{provider}", class: provider) + end + else + ViewHelpers.authorization_link @conn, provider do + Tag.content_tag(:span, "Sign in with \#{provider}", class: provider) + end + end + end """ - @spec provider_links(Conn.t(), keyword()) :: [HTML.safe()] - def provider_links(conn, link_opts \\ []) do - available_providers = Plug.available_providers(conn) - providers_for_user = Plug.providers_for_current_user(conn) - - available_providers - |> Enum.map(&{&1, &1 in providers_for_user}) - |> Enum.map(fn - {provider, true} -> deauthorization_link(conn, provider, link_opts) - {provider, false} -> authorization_link(conn, provider, link_opts) - end) + @spec provider_links(Conn.t(), keyword() | ({atom(), boolean()} -> Phoenix.HTML.unsafe())) :: [HTML.safe()] + def provider_links(conn, link_opts_or_callback \\ []) do + providers_for_user = Plug.providers_for_current_user(conn) + callback = render_callback(link_opts_or_callback, conn) + + conn + |> Plug.available_providers() + |> Enum.map(&callback.(&1, providers_for_user)) + end + + defp render_callback(callback, _conn) when is_function(callback), do: callback + defp render_callback(link_opts, conn) do + fn provider, providers_for_user -> + case provider in providers_for_user do + true -> deauthorization_link(conn, provider, link_opts) + false -> authorization_link(conn, provider, link_opts) + end + end end @doc """ diff --git a/test/pow_assent/phoenix/views/view_helpers_test.exs b/test/pow_assent/phoenix/views/view_helpers_test.exs index 0cb0d90..1aae142 100644 --- a/test/pow_assent/phoenix/views/view_helpers_test.exs +++ b/test/pow_assent/phoenix/views/view_helpers_test.exs @@ -2,7 +2,7 @@ defmodule PowAssent.Phoenix.ViewHelpersTest do use PowAssent.Test.Phoenix.ConnCase alias Plug.Conn - alias Phoenix.HTML.Link + alias Phoenix.HTML.{Link, Tag} alias PowAssent.Phoenix.ViewHelpers alias PowAssent.Test.{Phoenix.Router, Ecto.Users.User, RepoMock} @@ -26,7 +26,7 @@ defmodule PowAssent.Phoenix.ViewHelpersTest do {:ok, conn: conn} end - test "provider_links/1", %{conn: conn} do + test "provider_links/2", %{conn: conn} do [safe: iodata] = ViewHelpers.provider_links(conn) assert {:safe, iodata} == Link.link("Sign in with Test provider", to: "/auth/test_provider/new") @@ -36,13 +36,13 @@ defmodule PowAssent.Phoenix.ViewHelpersTest do assert {:safe, iodata} == Link.link("Remove Test provider authentication", to: "/auth/test_provider", method: "delete") end - test "provider_links/1 with link opts", %{conn: conn} do + test "provider_links/2 with link opts", %{conn: conn} do [safe: iodata] = ViewHelpers.provider_links(conn, class: "example") assert {:safe, iodata} == Link.link("Sign in with Test provider", to: "/auth/test_provider/new", class: "example") end - test "provider_links/1 with request_path", %{conn: conn} do + test "provider_links/2 with request_path", %{conn: conn} do [safe: iodata] = conn |> Conn.assign(:request_path, "/custom-url") @@ -51,13 +51,47 @@ defmodule PowAssent.Phoenix.ViewHelpersTest do assert {:safe, iodata} == Link.link("Sign in with Test provider", to: "/auth/test_provider/new?request_path=%2Fcustom-url") end - test "provider_links/1 with invited_user", %{conn: conn} do + test "provider_links/2 with invited_user", %{conn: conn} do conn = Conn.assign(conn, :invited_user, %PowAssent.Test.Invitation.Users.User{invitation_token: "token"}) [safe: iodata] = ViewHelpers.provider_links(conn) assert {:safe, iodata} == Link.link("Sign in with Test provider", to: "/auth/test_provider/new?invitation_token=token") end + test "provider_links/2 with callback", %{conn: conn} do + callback = + fn provider, providers_for_user -> + case provider in providers_for_user do + true -> + ViewHelpers.deauthorization_link(conn, :test_provider, class: "remove") do + Tag.content_tag(:span, "Provider remove", class: "test_provider") + end + + false -> + ViewHelpers.authorization_link(conn, :test_provider, class: "auth") do + Tag.content_tag(:span, "Provider auth", class: "test_provider") + end + end + end + + [safe: iodata] = ViewHelpers.provider_links(conn, callback) + + assert {:safe, iodata} == + (Link.link to: "/auth/test_provider/new", class: "auth" do + Tag.content_tag(:span, "Provider auth", class: "test_provider") + end) + + [safe: iodata] = + conn + |> Pow.Plug.assign_current_user(%User{id: 1}, []) + |> ViewHelpers.provider_links(callback) + + assert {:safe, iodata} == + (Link.link to: "/auth/test_provider", class: "remove", method: "delete" do + Tag.content_tag(:span, "Provider remove", class: "test_provider") + end) + end + test "authorization_link/4 accepts blocks", %{conn: conn} do {:safe, iodata} = ViewHelpers.authorization_link(conn, :test_provider) do "Provider auth"