diff --git a/lib/code_corps/emails/forgot_password_email.ex b/lib/code_corps/emails/forgot_password_email.ex new file mode 100644 index 000000000..f0d72106f --- /dev/null +++ b/lib/code_corps/emails/forgot_password_email.ex @@ -0,0 +1,14 @@ +defmodule CodeCorps.Emails.ForgotPasswordEmail do + import Bamboo.Email + import Bamboo.PostmarkHelper + + alias CodeCorps.Emails.BaseEmail + + def create(user) do + BaseEmail.create + |> to(user.email) + |> template(template_id(), {}) + end + + defp template_id, do: Application.get_env(:code_corps, :postmark_receipt_template) +end diff --git a/test/controllers/password_controller_test.exs b/test/controllers/password_controller_test.exs new file mode 100644 index 000000000..82b20427b --- /dev/null +++ b/test/controllers/password_controller_test.exs @@ -0,0 +1,25 @@ +defmodule CodeCorps.PasswordControllerTest do + @moduledoc false + + use CodeCorps.ApiCase, resource_name: :password + use Bamboo.Test + + test "creates and renders resource when email is valid", %{conn: conn} do + user = insert(:user) + attrs = %{"email" => user.email} + conn = post conn, password_path(conn, :forgot_password), attrs + response = json_response(conn, 200) + assert response == %{ "email" => user.email } + assert_delivered_email CodeCorps.Emails.ForgotPasswordEmail.create(user) + end + + test "does not create resource and renders 200 when email is invalid", %{conn: conn} do + user = insert(:user) + attrs = %{"email" => "random_email@gmail.com"} + conn = post conn, password_path(conn, :forgot_password), attrs + response = json_response(conn, 200) + assert response == %{ "email" => nil } + refute_delivered_email CodeCorps.Emails.ForgotPasswordEmail.create(user) + end + +end diff --git a/test/lib/code_corps/emails/forgot_password_email_test.exs b/test/lib/code_corps/emails/forgot_password_email_test.exs new file mode 100644 index 000000000..5955bc265 --- /dev/null +++ b/test/lib/code_corps/emails/forgot_password_email_test.exs @@ -0,0 +1,14 @@ +defmodule CodeCorps.Emails.ForgotPasswordEmailTest do + use CodeCorps.ModelCase + use Bamboo.Test + + alias CodeCorps.Emails.ForgotPasswordEmail + + test "forgot password email works" do + user = insert(:user) + + email = ForgotPasswordEmail.create(user) + assert email.from == "Code Corps" + assert email.to == user.email + end +end diff --git a/web/controllers/password_controller.ex b/web/controllers/password_controller.ex new file mode 100644 index 000000000..4dcce0eec --- /dev/null +++ b/web/controllers/password_controller.ex @@ -0,0 +1,37 @@ +defmodule CodeCorps.PasswordController do + use CodeCorps.Web, :controller + + alias CodeCorps.{Emails, Mailer, User, AuthToken} + alias Ecto.Changeset + + @doc""" + forgot_password should take an email and generate an AuthToken model and send an email + """ + def forgot_password(conn, %{"email" => email}) do + with %User{} = user <- Repo.get_by(User, email: email), + %Changeset{valid?: true} <- AuthToken.changeset(%AuthToken{}, user) do + + try_create_forgot_password(user) + |> send_forgot_password_email + + conn + |> put_status(200) + |> render("show.json", email: user.email) + + else + nil -> + conn + |> put_status(200) + |> render("show.json", email: nil) + end + end + + defp try_create_forgot_password(user) do + Emails.ForgotPasswordEmail.create(user) + end + + defp send_forgot_password_email(email) do + email |> Mailer.deliver_now + end + +end diff --git a/web/controllers/password_reset_controller.ex b/web/controllers/password_reset_controller.ex index 14f3e5704..1fa6f0a31 100644 --- a/web/controllers/password_reset_controller.ex +++ b/web/controllers/password_reset_controller.ex @@ -12,7 +12,7 @@ defmodule CodeCorps.PasswordResetController do """ def reset_password(conn, %{"token" => token, "password" => password, "password_confirmation" => password_confirmation}) do user = conn.assigns.current_user - with %AuthToken{value: auth_token} <- Repo.get_by(CodeCorps.AuthToken, %{ value: token, user_id: user.id }), + with %AuthToken{value: auth_token} <- Repo.get_by(AuthToken, %{ value: token, user_id: user.id }), {:ok, _} <- Phoenix.Token.verify(CodeCorps.Endpoint, "user", auth_token, max_age: 1209600) do with %Changeset{valid?: true} <- User.reset_password_changeset(user, %{password: password, password_confirmation: password_confirmation}) do diff --git a/web/router.ex b/web/router.ex index a5a786f84..5888d4768 100644 --- a/web/router.ex +++ b/web/router.ex @@ -97,6 +97,7 @@ defmodule CodeCorps.Router do resources "/comments", CommentController, only: [:index, :show] resources "/donation-goals", DonationGoalController, only: [:index, :show] resources "/organizations", OrganizationController, only: [:index, :show] + post "/password/forgot", PasswordController, :forgot_password resources "/project-categories", ProjectCategoryController, only: [:index, :show] resources "/project-skills", ProjectSkillController, only: [:index, :show] resources "/project-users", ProjectUserController, only: [:index, :show] diff --git a/web/views/password_view.ex b/web/views/password_view.ex new file mode 100644 index 000000000..e0e92f451 --- /dev/null +++ b/web/views/password_view.ex @@ -0,0 +1,10 @@ +defmodule CodeCorps.PasswordView do + use CodeCorps.Web, :view + + def render("show.json", %{email: email}) do + %{ + email: email + } + end + +end