Skip to content

Instantly share code, notes, and snippets.

@morgz
Last active November 29, 2019 12:23
Show Gist options
  • Save morgz/a754c75f501d27dfce64d427333ece0d to your computer and use it in GitHub Desktop.
Save morgz/a754c75f501d27dfce64d427333ece0d to your computer and use it in GitHub Desktop.
PowAssent.Phoenix.ViewHelpers - Enabling adding params to link generation and restructuring the link methods so view can just access paths for greater flexibility.
defmodule PowAssent.Phoenix.ViewHelpers do
@moduledoc """
View helpers to render authorization links.
"""
alias PowAssent.Plug
alias PowAssent.Phoenix.AuthorizationController
alias Phoenix.{HTML, HTML.Link}
import Logger
@doc """
Generates list of authorization links for all configured providers.
The list of providers will be fetched from the configuration, and
`authorization_link/2` will be called on each.
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.
"""
@spec provider_links(Conn.t()) :: [HTML.safe()]
def provider_links(conn, link_params \\ []) 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_params)
{provider, false} -> authorization_link(conn, provider, link_params)
end)
end
@doc """
Generates list of tuples with provider, authorization path and a message for all configured providers.
[{provider, message, path}, ...]
The list of providers will be fetched from the configuration, and
`authorization_path/2` will be called on each.
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_path/2` will be used for any already authorized providers.
"""
def provider_paths(conn) 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} -> {provider, deauthorization_message(conn, provider), deauthorization_path(conn, provider)}
{provider, false} -> {provider, authorization_message(conn, provider), authorization_path(conn, provider)}
end)
end
def authorization_path(conn, provider) do
query_params = invitation_token_query_params(conn) ++ request_path_query_params(conn)
AuthorizationController.routes(conn).path_for(conn, AuthorizationController, :new, [provider], query_params)
end
def authorization_message(conn, provider) do
query_params = invitation_token_query_params(conn) ++ request_path_query_params(conn)
AuthorizationController.extension_messages(conn).login_with_provider(%{conn | params: %{"provider" => provider}})
end
@doc """
Generates an authorization link for a provider.
The link is used to sign up or register a user using a provider. If
`:invited_user` is assigned to the conn, the invitation token will be passed
on through the URL query params.
"""
@spec authorization_link(Conn.t(), atom()) :: HTML.safe()
def authorization_link(conn, provider, link_params \\ []) do
query_params = invitation_token_query_params(conn) ++ request_path_query_params(conn)
msg = authorization_message(conn, provider)
path = authorization_path(conn, provider)
Link.link(msg, [to: path] |> Keyword.merge(link_params))
end
defp invitation_token_query_params(%{assigns: %{invited_user: %{invitation_token: token}}}), do: [invitation_token: token]
defp invitation_token_query_params(_conn), do: []
defp request_path_query_params(%{assigns: %{request_path: request_path}}), do: [request_path: request_path]
defp request_path_query_params(_conn), do: []
def deauthorization_path(conn, provider) do
query_params = invitation_token_query_params(conn) ++ request_path_query_params(conn)
AuthorizationController.routes(conn).path_for(conn, AuthorizationController, :new, [provider], query_params)
end
def deauthorization_message(conn, provider) do
AuthorizationController.extension_messages(conn).remove_provider_authentication(%{conn | params: %{"provider" => provider}})
end
def deauthorization_path(conn, provider) do
AuthorizationController.routes(conn).path_for(conn, AuthorizationController, :delete, [provider])
end
@doc """
Generates a provider deauthorization link.
The link is used to remove authorization with the provider.
"""
@spec deauthorization_link(Conn.t(), atom()) :: HTML.safe()
def deauthorization_link(conn, provider, link_params \\ []) do
msg = deauthorization_message(conn, provider)
path = deauthorization_path(conn, provider)
Link.link(msg, [to: path, method: :delete] |> Keyword.merge(link_params))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment