diff --git a/priv/templates/phx.gen.auth/context_functions.ex b/priv/templates/phx.gen.auth/context_functions.ex index 2bdcbcdb5e..6060b736ee 100644 --- a/priv/templates/phx.gen.auth/context_functions.ex +++ b/priv/templates/phx.gen.auth/context_functions.ex @@ -200,14 +200,7 @@ |> <%= inspect schema.alias %>.password_changeset(attrs) |> <%= inspect schema.alias %>.validate_current_password(password) - Ecto.Multi.new() - |> Ecto.Multi.update(:<%= schema.singular %>, changeset) - |> Ecto.Multi.delete_all(:tokens, <%= inspect schema.alias %>Token.by_<%= schema.singular %>_and_contexts_query(<%= schema.singular %>, :all)) - |> Repo.transaction() - |> case do - {:ok, %{<%= schema.singular %>: <%= schema.singular %>}} -> {:ok, <%= schema.singular %>} - {:error, :<%= schema.singular %>, changeset, _} -> {:error, changeset} - end + update_password(<%= schema.singular %>, changeset) end ## Session @@ -336,9 +329,15 @@ """ def reset_<%= schema.singular %>_password(<%= schema.singular %>, attrs) do + update_password(<%= schema.singular %>, <%= inspect schema.alias %>.password_changeset(<%= schema.singular %>, attrs)) + end + + defp update_password(<%= schema.singular %>, changeset) do + tokens_query = <%= inspect schema.alias %>Token.by_<%= schema.singular %>_except_contexts_query(<%= schema.singular %>, ["confirm"]) + Ecto.Multi.new() - |> Ecto.Multi.update(:<%= schema.singular %>, <%= inspect schema.alias %>.password_changeset(<%= schema.singular %>, attrs)) - |> Ecto.Multi.delete_all(:tokens, <%= inspect schema.alias %>Token.by_<%= schema.singular %>_and_contexts_query(<%= schema.singular %>, :all)) + |> Ecto.Multi.update(:<%= schema.singular %>, changeset) + |> Ecto.Multi.delete_all(:tokens, tokens_query) |> Repo.transaction() |> case do {:ok, %{<%= schema.singular %>: <%= schema.singular %>}} -> {:ok, <%= schema.singular %>} diff --git a/priv/templates/phx.gen.auth/schema_token.ex b/priv/templates/phx.gen.auth/schema_token.ex index f7a792a664..1a9d991213 100644 --- a/priv/templates/phx.gen.auth/schema_token.ex +++ b/priv/templates/phx.gen.auth/schema_token.ex @@ -169,12 +169,22 @@ defmodule <%= inspect schema.module %>Token do end @doc """ - Gets all tokens for the given <%= schema.singular %> for the given contexts. + Gets all tokens for the given <%= schema.singular %>. """ - def by_<%= schema.singular %>_and_contexts_query(<%= schema.singular %>, :all) do + def by_<%= schema.singular %>_query(<%= schema.singular %>) do from t in <%= inspect schema.alias %>Token, where: t.<%= schema.singular %>_id == ^<%= schema.singular %>.id end + @doc """ + Gets all tokens for the given <%= schema.singular %> except the given contexts. + """ + def by_<%= schema.singular %>_except_contexts_query(<%= schema.singular %>, [_ | _] = contexts) do + from t in <%= inspect schema.alias %>Token, where: t.<%= schema.singular %>_id == ^<%= schema.singular %>.id and t.context not in ^contexts + end + + @doc """ + Gets all tokens for the given <%= schema.singular %> for the given contexts. + """ def by_<%= schema.singular %>_and_contexts_query(<%= schema.singular %>, [_ | _] = contexts) do from t in <%= inspect schema.alias %>Token, where: t.<%= schema.singular %>_id == ^<%= schema.singular %>.id and t.context in ^contexts end diff --git a/priv/templates/phx.gen.auth/test_cases.exs b/priv/templates/phx.gen.auth/test_cases.exs index 2542791a6a..f2cf0aac44 100644 --- a/priv/templates/phx.gen.auth/test_cases.exs +++ b/priv/templates/phx.gen.auth/test_cases.exs @@ -202,16 +202,21 @@ end test "updates the email with a valid token", %{<%= schema.singular %>: <%= schema.singular %>, token: token, email: email} do - <%= inspect context.alias %>.deliver_<%= schema.singular %>_confirmation_instructions(<%= schema.singular %>, & &1) - <%= inspect context.alias %>.deliver_<%= schema.singular %>_reset_password_instructions(<%= schema.singular %>, & &1) - assert <%= inspect context.alias %>.update_<%= schema.singular %>_email(<%= schema.singular %>, token) == :ok changed_<%= schema.singular %> = Repo.get!(<%= inspect schema.alias %>, <%= schema.singular %>.id) assert changed_<%= schema.singular %>.email != <%= schema.singular %>.email assert changed_<%= schema.singular %>.email == email assert changed_<%= schema.singular %>.confirmed_at assert changed_<%= schema.singular %>.confirmed_at != <%= schema.singular %>.confirmed_at - refute Repo.get_by(<%= inspect schema.alias %>Token, <%= schema.singular %>_id: <%= schema.singular %>.id) + end + + test "deletes all tokens sent to email for the given <%= schema.singular %>", %{<%= schema.singular %>: <%= schema.singular %>, token: token} do + _ = <%= inspect context.alias %>.generate_<%= schema.singular %>_session_token(<%= schema.singular %>) + _ = <%= inspect context.alias %>.deliver_<%= schema.singular %>_reset_password_instructions(<%= schema.singular %>, & &1) + _ = <%= inspect context.alias %>.deliver_<%= schema.singular %>_confirmation_instructions(<%= schema.singular %>, & &1) + + :ok = <%= inspect context.alias %>.update_<%= schema.singular %>_email(<%= schema.singular %>, token) + assert [%<%= inspect schema.alias %>Token{context: "session"}] = Repo.all(<%= inspect schema.alias %>Token.by_<%= schema.singular %>_query(<%= schema.singular %>)) end test "does not update email with invalid token", %{<%= schema.singular %>: <%= schema.singular %>} do @@ -296,15 +301,17 @@ assert <%= inspect context.alias %>.get_<%= schema.singular %>_by_email_and_password(<%= schema.singular %>.email, "new valid password") end - test "deletes all tokens for the given <%= schema.singular %>", %{<%= schema.singular %>: <%= schema.singular %>} do + test "deletes all tokens except confirmation for the given <%= schema.singular %>", %{<%= schema.singular %>: <%= schema.singular %>} do _ = <%= inspect context.alias %>.generate_<%= schema.singular %>_session_token(<%= schema.singular %>) + _ = <%= inspect context.alias %>.deliver_<%= schema.singular %>_reset_password_instructions(<%= schema.singular %>, & &1) + _ = <%= inspect context.alias %>.deliver_<%= schema.singular %>_confirmation_instructions(<%= schema.singular %>, & &1) {:ok, _} = <%= inspect context.alias %>.update_<%= schema.singular %>_password(<%= schema.singular %>, valid_<%= schema.singular %>_password(), %{ password: "new valid password" }) - refute Repo.get_by(<%= inspect schema.alias %>Token, <%= schema.singular %>_id: <%= schema.singular %>.id) + assert [%<%= inspect schema.alias %>Token{context: "confirm"}] = Repo.all(<%= inspect schema.alias %>Token.by_<%= schema.singular %>_query(<%= schema.singular %>)) end end @@ -491,10 +498,13 @@ assert <%= inspect context.alias %>.get_<%= schema.singular %>_by_email_and_password(<%= schema.singular %>.email, "new valid password") end - test "deletes all tokens for the given <%= schema.singular %>", %{<%= schema.singular %>: <%= schema.singular %>} do + test "deletes all tokens except confirmation for the given <%= schema.singular %>", %{<%= schema.singular %>: <%= schema.singular %>} do _ = <%= inspect context.alias %>.generate_<%= schema.singular %>_session_token(<%= schema.singular %>) + _ = <%= inspect context.alias %>.deliver_<%= schema.singular %>_reset_password_instructions(<%= schema.singular %>, & &1) + _ = <%= inspect context.alias %>.deliver_<%= schema.singular %>_confirmation_instructions(<%= schema.singular %>, & &1) + {:ok, _} = <%= inspect context.alias %>.reset_<%= schema.singular %>_password(<%= schema.singular %>, %{password: "new valid password"}) - refute Repo.get_by(<%= inspect schema.alias %>Token, <%= schema.singular %>_id: <%= schema.singular %>.id) + assert [%<%= inspect schema.alias %>Token{context: "confirm"}] = Repo.all(<%= inspect schema.alias %>Token.by_<%= schema.singular %>_query(<%= schema.singular %>)) end end