Am I doing anything wrong with the pattern matching?
with {:ok, %User{} = user} <- Accounts.update_user(user, %{verify_email: true}) do
text conn, "Email verified!"
end
or is it the update_user function?
def update_user(%User{} = user, attrs) do
user
|> User.changeset(attrs)
|> Repo.update()
end
Why do all the fields get updated though only verify_email is set to true? Thus, the password is also updated into a new hashed phrase, making the users unable to log in every time after verifying the email. Or do I have to create a separate changeset for verify_email?
[debug] QUERY OK db=2.9ms
UPDATE "users" SET "password" = $1, "verify_email" = $2, "updated_at" = $3 WHERE "id" = $4
["$pbkdf2-sha512$12345$SoMeNeWlYuPdAtEdHaShedKeY", true, {{2018, 7, 6}, {19, 36, 0, 301940}}, 171]
put_change(changeset, :password, password) – adds a “password” change into for every “valid” changeset, thus resulting in the UPDATE sql query you posted in OP.
Try checking if the password has been changed before hashing it again.
defp hash_password(%{valid?: true, changes: %{password: new_password}} = changeset) do
put_change(changeset, :password, Pbkdf2.hashpwsalt(new_password))
end
defp hash_password(changeset), do: changeset
Off-topic: maybe it’s time to switch from pbkdf2 to bcrypt or even argon. And maybe don’t handle both hashed and unhashed passwords under the same name (:password, in your case) – you might not notice some small change in your code base, and boom! some of the password in your database are stored in plaintext.
no function clause matching in Monitor.Accounts.User.hash_password/1
Called with 1 arguments
#Ecto.Changeset<action: nil, changes: %{verify_email: true}, errors: [], data: #Monitor.Accounts.User<>, valid?: true>
It returns this error.
Maybe, I think I will just create a separate changeset and custom function for updating verify_email.
This potentially opens up your app to “hacker” attacks – updating “private” values that shouldn’t be updated (casted), like foreign keys. Especially so if you “blindly” pass the controller’s “params” into this function as “attrs”. Changesets at least mildly protect from that by using selective cast.