pow-auth / pow_assent

Multi-provider authentication for your Pow enabled app
https://powauth.com
MIT License
325 stars 50 forks source link

Messages aren't replaced with custom messages #120

Closed praveenperera closed 4 years ago

praveenperera commented 4 years ago

I tried to add a custom message using login_with_provider() following instructions that are here:

https://hexdocs.pm/pow_assent/PowAssent.Phoenix.Messages.html#content

I added it as a messages_backend

Here is my module:

defmodule TunevuPlayer.Pow.Messages do
  use Pow.Phoenix.Messages

  use Pow.Extension.Phoenix.Messages,
    extensions: [PowAssent]

  def login_with_provider(_conn) do
    "Twitter"
  end
end

However, when using the view helpers I get "Sign in with Twitter" instead of just "Twitter"

This is how I made it work manually:

defmodule TunevuPlayer.Pow.Messages do
  use Pow.Phoenix.Messages

  defmodule PowAssent.Phoenix.Messages do
    alias Phoenix.Naming
    alias Plug.Conn
    alias PowAssent.Phoenix.Messages

    @type message :: Messages.message()

    @spec signed_in(Conn.t()) :: message()
    def signed_in(_conn), do: nil

    @spec could_not_sign_in(Conn.t()) :: message()
    def could_not_sign_in(_conn),
      do: "Something went wrong, and you couldn't be signed in. Please try again."

    @spec user_has_been_created(Conn.t()) :: message()
    def user_has_been_created(_conn), do: nil

    @spec account_already_bound_to_other_user(Conn.t()) :: message()
    def account_already_bound_to_other_user(conn),
      do:
        interpolate("The %{provider} account is already bound to another user.",
          provider: Naming.humanize(conn.params["provider"])
        )

    @spec authentication_has_been_removed(Conn.t()) :: message()
    def authentication_has_been_removed(conn),
      do:
        interpolate("Authentication with %{provider} has been removed",
          provider: Naming.humanize(conn.params["provider"])
        )

    @spec identity_cannot_be_removed_missing_user_password(Conn.t()) :: message()
    def identity_cannot_be_removed_missing_user_password(_conn),
      do: "Authentication cannot be removed until you've entered a password for your account."

    @spec invalid_request(Conn.t()) :: message()
    def invalid_request(_conn), do: "Invalid Request."

    @spec login_with_provider(Conn.t()) :: message()
    def login_with_provider(_conn) do
      "Twitter"
    end

    @spec remove_provider_authentication(Conn.t()) :: message()
    def remove_provider_authentication(conn),
      do:
        interpolate("Remove %{provider} authentication",
          provider: Naming.humanize(conn.params["provider"])
        )

    # Simple mock method for interpolations
    defp interpolate(msg, opts) do
      Enum.reduce(opts, msg, fn {key, value}, msg ->
        token = "%{#{key}}"

        case String.contains?(msg, token) do
          true -> String.replace(msg, token, to_string(value), global: false)
          false -> msg
        end
      end)
    end
  end
end
danschultzer commented 4 years ago

You have to use the pow_assent_login_with_provider/1 method name:

defmodule TunevuPlayer.Pow.Messages do
  use Pow.Phoenix.Messages
  use Pow.Extension.Phoenix.Messages,
    extensions: [PowAssent]

  def pow_assent_login_with_provider(conn), do: Phoenix.Naming.humanize(conn.params["provider"])
end

And set messages_backend: TunevuPlayer.Pow.Messages in the config.

Using Phoenix.Naming.humanize(conn.params["provider"]) would mean that it says Twitter for the :twitter strategy. It's better in case you add more providers in the future.

praveenperera commented 4 years ago

Oh I see now, I have to change

defmodule TunevuPlayer.Pow.Messages do
  use Pow.Phoenix.Messages

  use Pow.Extension.Phoenix.Messages,
    extensions: [PowAssent]

  def login_with_provider(_conn) do
    "Twitter"
  end
end

TO

defmodule TunevuPlayer.Pow.Messages do
  use Pow.Phoenix.Messages

  use Pow.Extension.Phoenix.Messages,
    extensions: [PowAssent]

  def pow_assent_login_with_provider(_conn) do
    "Twitter"
  end
end
danschultzer commented 4 years ago

Yup, extension messages require that you add the extension namespace to the method name. It's to prevent name collision.

praveenperera commented 4 years ago

Yes that makes sense, I should have deduced that when I saw the example function was pow_assent_signed_in, but I overlooked it.

I ended up copying the function name I thought I needed (login_with_provider) directly.

What do you think about me adding a note to the PowAssent docs saying you have to add the extension namespace to the function name?

danschultzer commented 4 years ago

Yeah, it isn't clear from the docs at all. I'm updating them, thanks!

praveenperera commented 4 years ago

Glad I could help 😊

danschultzer commented 4 years ago

Done #123 :rocket: