Pass ip_address as parameter to provider option

Hello, I’m trying to get the client IP address on login and pass it to provider_option so I can send it in the email as an information to the user, it’s a standard swoosh/postmark email workflow.

Current setup for auth_plug and login method are:

auth_plug.ex

  def call(conn, _opts) do
    uid = get_session(conn, :user_id)

    unless uid do
      conn
      |> Phoenix.Controller.redirect(to: "/login")
      |> halt
    else
      user = Example.Account.User.find!(uid)

      conn
      |> assign(:user, user)
      |> put_ip_address
    end
  end

  def put_ip_address(conn) do
    ip_address =
    List.first(get_req_header(conn, "x-forwared-for")) || "0.0.0.0"

    conn
    |> put_private(:ip_address, ip_address)
  end

user.ex

  def login(email, password) do
    user =
      User
      |> where([t], t.email == ^email and not(is_nil(t.password_hash)))
      |> Repo.one

    has_valid_password = Bcrypt.verify_pass(password, (if user, do: user.password_hash, else: ""))

    if user && has_valid_password do

      new()
      |> Swoosh.Email.from("foo@bar.com")
      |> to(email)
      |> put_provider_option(:template_id, "123124")
      |> put_provider_option(:template_alias, "login-email")
      |> put_provider_option(:template_model, %{user: user.name, ip_address: ip_address})
      |> Example.Mailer.deliver()

      {:ok, user}
    else
      {:error, "Invalid email or password"}
    end
  en

In auth_plug I’ve created a custom function for fetching ip_address and I’m passing it into call function. How can I use put_ip_address in my login method and pass it to put_provider_option?

That is not going to work like this.
auth_plug - checks if the user is logged in and it puts the IP address in conn only if user is logged in. (In that case you will never call User.login)
What you have to do is in your Session/LoginController, on create or whatever action you have to do the same thing (extract ip_address from conn) and pass it to User.login.

in LoginController

def create(conn, %{“email” => user, “password” => pass}) do
  ip_address = List.first(get_req_header(conn, "x-forwared-for")) || "0.0.0.0"
  User.login(email, password, ip_address)
  ...
1 Like

@tspenov thanks for the suggestion, I need to work on this.