From 42813160136d54bc06b6fd15ec0d8cfaa03a2f46 Mon Sep 17 00:00:00 2001 From: A K Date: Wed, 3 Apr 2024 13:43:35 +0200 Subject: [PATCH 1/2] fix type issue if the user model has attribute with data name --- lib/pow/ecto/schema/changeset.ex | 8 +++---- test/pow/ecto/schema/changeset_test.exs | 29 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/pow/ecto/schema/changeset.ex b/lib/pow/ecto/schema/changeset.ex index 2f1574a1..2ab39c03 100644 --- a/lib/pow/ecto/schema/changeset.ex +++ b/lib/pow/ecto/schema/changeset.ex @@ -161,7 +161,7 @@ defmodule Pow.Ecto.Schema.Changeset do |> Changeset.prepare_changes(&Changeset.delete_change(&1, :current_password)) end - defp reset_current_password_field(%{data: user} = changeset) do + defp reset_current_password_field(%Changeset{data: user} = changeset) do %{changeset | data: reset_current_password_field(user)} end defp reset_current_password_field(user) do @@ -181,7 +181,7 @@ defmodule Pow.Ecto.Schema.Changeset do end defp maybe_validate_email_format(changeset, _type, _config), do: changeset - defp maybe_validate_current_password(%{data: %{password_hash: nil}} = changeset, _config), + defp maybe_validate_current_password(%Changeset{data: %{password_hash: nil}} = changeset, _config), do: changeset defp maybe_validate_current_password(changeset, config) do changeset = Changeset.validate_required(changeset, [:current_password]) @@ -192,7 +192,7 @@ defmodule Pow.Ecto.Schema.Changeset do end end - defp validate_current_password(%{data: user, changes: %{current_password: password}} = changeset, config) do + defp validate_current_password(%Changeset{data: user, changes: %{current_password: password}} = changeset, config) do user |> verify_password(password, config) |> case do @@ -226,7 +226,7 @@ defmodule Pow.Ecto.Schema.Changeset do apply_password_verify_function(config, [password, password_hash]) end - defp maybe_require_password(%{data: %{password_hash: nil}} = changeset) do + defp maybe_require_password(%Changeset{data: %{password_hash: nil}} = changeset) do Changeset.validate_required(changeset, [:password]) end defp maybe_require_password(changeset), do: changeset diff --git a/test/pow/ecto/schema/changeset_test.exs b/test/pow/ecto/schema/changeset_test.exs index c05567f3..aa230755 100644 --- a/test/pow/ecto/schema/changeset_test.exs +++ b/test/pow/ecto/schema/changeset_test.exs @@ -418,4 +418,33 @@ defmodule Pow.Ecto.Schema.ChangesetTest do assert Changeset.validate_email("john.doe@#{String.duplicate("x", 64)}.com") == {:error, "dns label too long"} assert Changeset.validate_email("john.doe@#{String.duplicate("x", 64)}.example.com") == {:error, "dns label too long"} end + + defmodule UserDataAttribute do + @moduledoc false + use Ecto.Schema + use Pow.Ecto.Schema + + schema "users" do + pow_user_fields() + + field(:data, :string) + end + end + + describe "User struct with data field" do + @password "password" + + test "pow_current_password_changeset/2" do + password_hash = Password.pbkdf2_hash(@password) + + user = %UserDataAttribute{password_hash: password_hash} + + assert UserDataAttribute.changeset(user, %{}) + assert UserDataAttribute.pow_changeset(user, %{}) + assert UserDataAttribute.pow_verify_password(user, @password) + assert UserDataAttribute.pow_user_id_field_changeset(user, %{}) + assert UserDataAttribute.pow_password_changeset(user, %{}) + assert UserDataAttribute.pow_current_password_changeset(user, %{"current_password" => @password}) + end + end end From 03c9d333fdba75c47d5672cc1d467ea35a5d38a3 Mon Sep 17 00:00:00 2001 From: Dan Schultzer <1254724+danschultzer@users.noreply.github.com> Date: Thu, 11 Apr 2024 04:28:12 -0700 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 6 ++++++ lib/pow/ecto/schema/changeset.ex | 9 +++++++++ test/pow/ecto/schema/changeset_test.exs | 5 +++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3595049..06e40616 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v1.0.38 (TBA) + +### Bug fixes + +* [`Pow.Ecto.Schema.Changeset`] Fixed issue with schemas having a `:data` field not being handled correctly in changeset functions + ## v1.0.37 (2024-03-03) ### Bug fixes diff --git a/lib/pow/ecto/schema/changeset.ex b/lib/pow/ecto/schema/changeset.ex index 2ab39c03..f34b60a3 100644 --- a/lib/pow/ecto/schema/changeset.ex +++ b/lib/pow/ecto/schema/changeset.ex @@ -111,6 +111,7 @@ defmodule Pow.Ecto.Schema.Changeset do do_confirm_password_changeset(user_or_changeset, params) end + def confirm_password_changeset(user_or_changeset, %{"confirm_password" => password_confirmation} = params, _config) do params = params @@ -119,6 +120,7 @@ defmodule Pow.Ecto.Schema.Changeset do convert_confirm_password_param(user_or_changeset, params) end + def confirm_password_changeset(user_or_changeset, params, _config), do: do_confirm_password_changeset(user_or_changeset, params) @@ -164,6 +166,7 @@ defmodule Pow.Ecto.Schema.Changeset do defp reset_current_password_field(%Changeset{data: user} = changeset) do %{changeset | data: reset_current_password_field(user)} end + defp reset_current_password_field(user) do %{user | current_password: nil} end @@ -183,6 +186,7 @@ defmodule Pow.Ecto.Schema.Changeset do defp maybe_validate_current_password(%Changeset{data: %{password_hash: nil}} = changeset, _config), do: changeset + defp maybe_validate_current_password(changeset, config) do changeset = Changeset.validate_required(changeset, [:current_password]) @@ -222,6 +226,7 @@ defmodule Pow.Ecto.Schema.Changeset do false end + def verify_password(%{password_hash: password_hash}, password, config) do apply_password_verify_function(config, [password, password_hash]) end @@ -229,6 +234,7 @@ defmodule Pow.Ecto.Schema.Changeset do defp maybe_require_password(%Changeset{data: %{password_hash: nil}} = changeset) do Changeset.validate_required(changeset, [:password]) end + defp maybe_require_password(changeset), do: changeset defp maybe_validate_password(changeset, config) do @@ -250,11 +256,13 @@ defmodule Pow.Ecto.Schema.Changeset do defp maybe_put_password_hash(%Changeset{valid?: true, changes: %{password: password}} = changeset, config) do Changeset.put_change(changeset, :password_hash, hash_password(password, config)) end + defp maybe_put_password_hash(changeset, _config), do: changeset defp maybe_validate_password_hash(%Changeset{valid?: true} = changeset) do Changeset.validate_required(changeset, [:password_hash]) end + defp maybe_validate_password_hash(changeset), do: changeset defp hash_password(password, config) do @@ -413,6 +421,7 @@ defmodule Pow.Ecto.Schema.Changeset do _label, error -> {:halt, error} end) end + defp validate_dns_labels({:error, error}), do: {:error, error} defp validate_dns_label(label) do diff --git a/test/pow/ecto/schema/changeset_test.exs b/test/pow/ecto/schema/changeset_test.exs index aa230755..cf7f3afb 100644 --- a/test/pow/ecto/schema/changeset_test.exs +++ b/test/pow/ecto/schema/changeset_test.exs @@ -424,10 +424,12 @@ defmodule Pow.Ecto.Schema.ChangesetTest do use Ecto.Schema use Pow.Ecto.Schema + @ecto_derive_inspect_for_redacted_fields false + schema "users" do pow_user_fields() - field(:data, :string) + field :data, :string end end @@ -436,7 +438,6 @@ defmodule Pow.Ecto.Schema.ChangesetTest do test "pow_current_password_changeset/2" do password_hash = Password.pbkdf2_hash(@password) - user = %UserDataAttribute{password_hash: password_hash} assert UserDataAttribute.changeset(user, %{})