updating password through ash resources

trying to update the password but current_password field data vanishes as soon as i enter the data in new_password. the current_password field vanishes
12 Replies
talha-azeem
talha-azeemOPβ€’3y ago
<.header>Change Password</.header>

<.simple_form
:let={f}
id="password_form"
for={@password_form}
method="post"
phx-change="validate_password"
phx-submit="save_password"
>
<.input field={{f, :email}} type="hidden" />

<.input field={{f, :password}} type="password" label="New password" required />
<.input field={{f, :password_confirmation}} type="password" label="Confirm new password" />
<.input
field={{f, :current_password}}
name="current_password"
type="password"
label="Current password"
id="current_password_for_password"
required
/>
<:actions>
<.button phx-disable-with="Changing...">Change Password</.button>
</:actions>
</.simple_form>
<.header>Change Password</.header>

<.simple_form
:let={f}
id="password_form"
for={@password_form}
method="post"
phx-change="validate_password"
phx-submit="save_password"
>
<.input field={{f, :email}} type="hidden" />

<.input field={{f, :password}} type="password" label="New password" required />
<.input field={{f, :password_confirmation}} type="password" label="Confirm new password" />
<.input
field={{f, :current_password}}
name="current_password"
type="password"
label="Current password"
id="current_password_for_password"
required
/>
<:actions>
<.button phx-disable-with="Changing...">Change Password</.button>
</:actions>
</.simple_form>
frontend part
password_form =
AshPhoenix.Form.for_update(user, :change_password,
as: "change_password",
api: Accounts,
actor: user
)
password_form =
AshPhoenix.Form.for_update(user, :change_password,
as: "change_password",
api: Accounts,
actor: user
)
password form in mount in user.ex:
update :change_password do
accept []

argument :current_password, :string do
sensitive? true
allow_nil? false
end

argument :password, :string do
sensitive? true
allow_nil? false
end

argument :password_confirmation, :string do
sensitive? true
allow_nil? false
end

change set_context(%{strategy_name: :password})

validate confirm(:password, :password_confirmation)

validate {AshAuthentication.Strategy.Password.PasswordValidation,
strategy_name: :password, password_argument: :current_password} do
only_when_valid? true
before_action? true
end

change AshAuthentication.Strategy.Password.HashPasswordChange
end



policies do
policy action(:change_password) do
description "A logged in user can reset their password"
authorize_if expr(id == ^actor(:id))
end
end
update :change_password do
accept []

argument :current_password, :string do
sensitive? true
allow_nil? false
end

argument :password, :string do
sensitive? true
allow_nil? false
end

argument :password_confirmation, :string do
sensitive? true
allow_nil? false
end

change set_context(%{strategy_name: :password})

validate confirm(:password, :password_confirmation)

validate {AshAuthentication.Strategy.Password.PasswordValidation,
strategy_name: :password, password_argument: :current_password} do
only_when_valid? true
before_action? true
end

change AshAuthentication.Strategy.Password.HashPasswordChange
end



policies do
policy action(:change_password) do
description "A logged in user can reset their password"
authorize_if expr(id == ^actor(:id))
end
end
I tried debugging it but my current_password field is like it was never there.
ZachDaniel
ZachDanielβ€’3y ago
can I see where you are validating the form? "validate_password" that event handler
talha-azeem
talha-azeemOPβ€’3y ago
@impl true
def handle_event("validate_password", %{"change_password" => params}, socket) do
{:noreply,
assign(socket,
password_form:
AshPhoenix.Form.validate(socket.assigns.password_form, params,
errors: socket.assigns.password_form.submitted_once?
)
)}
end

@impl true
def handle_event("save_password", %{"change_password" => params}, socket) do
case AshPhoenix.Form.submit(socket.assigns.password_form, params: params) do
{:ok, _result} ->
{:noreply,
socket
|> put_flash(:info, "Password has been successfully changed.")
|> push_redirect(to: "/")}

{:error, password_form} ->
{:noreply, assign(socket, password_form: password_form)}
end
end
@impl true
def handle_event("validate_password", %{"change_password" => params}, socket) do
{:noreply,
assign(socket,
password_form:
AshPhoenix.Form.validate(socket.assigns.password_form, params,
errors: socket.assigns.password_form.submitted_once?
)
)}
end

@impl true
def handle_event("save_password", %{"change_password" => params}, socket) do
case AshPhoenix.Form.submit(socket.assigns.password_form, params: params) do
{:ok, _result} ->
{:noreply,
socket
|> put_flash(:info, "Password has been successfully changed.")
|> push_redirect(to: "/")}

{:error, password_form} ->
{:noreply, assign(socket, password_form: password_form)}
end
end
ZachDaniel
ZachDanielβ€’3y ago
πŸ€” Does it happen for password and password confirmation? or only for current_password
talha-azeem
talha-azeemOPβ€’3y ago
only for current_password at the moment
ZachDaniel
ZachDanielβ€’3y ago
Thats the only one you're setting an id for πŸ™‚ Try not setting the id and see if that works
talha-azeem
talha-azeemOPβ€’3y ago
I inspected the params in validate and they are
params => : %{
"email" => "[email protected]",
"password" => "",
"password_confirmation" => ""
}
params => : %{
"email" => "[email protected]",
"password" => "",
"password_confirmation" => ""
}
id of form?
ZachDaniel
ZachDanielβ€’3y ago
<.input
field={{f, :current_password}}
name="current_password"
type="password"
label="Current password"
id="current_password_for_password" #<- this
required
/>
<.input
field={{f, :current_password}}
name="current_password"
type="password"
label="Current password"
id="current_password_for_password" #<- this
required
/>
talha-azeem
talha-azeemOPβ€’3y ago
current_password still doesn't show up in params
ZachDaniel
ZachDanielβ€’3y ago
also this:
<.input
field={{f, :current_password}}
name="current_password" # <- remove this
type="password"
label="Current password"
required
/>
<.input
field={{f, :current_password}}
name="current_password" # <- remove this
type="password"
label="Current password"
required
/>
I think the id is actually fine to change, but the name shouldn't be changed directly Unless you do it like this name={"#{f.name}[current_password]"}
frankdugan3
frankdugan3β€’3y ago
The name is crucial to how Phoenix builds the params to return, always best to let the component helpers build the name for you.
talha-azeem
talha-azeemOPβ€’3y ago
name was the issue Thank you guys 🫢🏻 Basic User Settings Implemented using the Ash resources. Thank you to both of you 🫰🏻 @Zach Daniel @frankdugan3

Did you find this page helpful?