defmodule MicrowavepropWeb.UserResetPasswordController do use MicrowavepropWeb, :controller alias Microwaveprop.Accounts plug :get_user_by_reset_password_token when action in [:edit, :update] @spec new(Plug.Conn.t(), map()) :: Plug.Conn.t() def new(conn, _params) do render(conn, :new) end @spec create(Plug.Conn.t(), map()) :: Plug.Conn.t() def create(conn, %{"user" => %{"email" => email}}) do _ = if user = Accounts.get_user_by_email(email) do {:ok, _email} = Accounts.deliver_user_reset_password_instructions( user, &url(~p"/users/reset-password/#{&1}") ) end # Always respond the same way whether or not the email exists — this is # a deliberate anti-enumeration measure. If we redirected differently on # a miss, an attacker could iterate emails to discover registered accounts. conn |> put_flash( :info, "If your email is in our system, you will receive instructions to reset your password shortly." ) |> redirect(to: ~p"/users/log-in") end @spec edit(Plug.Conn.t(), map()) :: Plug.Conn.t() def edit(conn, _params) do render(conn, :edit, changeset: Accounts.change_user_password(conn.assigns.user), token: conn.assigns.token ) end @spec update(Plug.Conn.t(), map()) :: Plug.Conn.t() def update(conn, %{"user" => user_params}) do case Accounts.reset_user_password(conn.assigns.user, user_params) do {:ok, _} -> conn |> put_flash(:info, "Password reset successfully.") |> redirect(to: ~p"/users/log-in") {:error, changeset} -> render(conn, :edit, changeset: changeset, token: conn.assigns.token) end end defp get_user_by_reset_password_token(conn, _opts) do %{"token" => token} = conn.params if user = Accounts.get_user_by_reset_password_token(token) do conn |> assign(:user, user) |> assign(:token, token) else conn |> put_flash(:error, "Reset link is invalid or it has expired.") |> redirect(to: ~p"/users/reset-password") |> halt() end end end