Skip to content

Commit

Permalink
Merge pull request #729 from oivoodoo/fix-type-bug
Browse files Browse the repository at this point in the history
Fix type issue if the user model has attribute with `data` name
  • Loading branch information
danschultzer committed Apr 11, 2024
2 parents 4245b05 + 03c9d33 commit dac675c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
17 changes: 13 additions & 4 deletions lib/pow/ecto/schema/changeset.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)

Expand Down Expand Up @@ -161,9 +163,10 @@ 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
%{user | current_password: nil}
end
Expand All @@ -181,8 +184,9 @@ 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])

Expand All @@ -192,7 +196,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
Expand Down Expand Up @@ -222,13 +226,15 @@ 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

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

defp maybe_validate_password(changeset, config) do
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
30 changes: 30 additions & 0 deletions test/pow/ecto/schema/changeset_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -418,4 +418,34 @@ 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

@ecto_derive_inspect_for_redacted_fields false

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

0 comments on commit dac675c

Please sign in to comment.