Guy14

Guy14

AshAuthentication.Errors.AuthenticationFailed does not implement the AshPhoenix.FormData.Error protocol

Hello community!

I encounter a warning saying that AshAuthentication.Errors.AuthenticationFailed does not implement the AshPhoenix.FormData.Error protocol while running tests (with an voluntary wrong password) for a Phoenix Liveview.

...12:06:14.730 [warning] Unhandled error in form submission for Prepair.AshDomains.Accounts.User.change_password

This error was unhandled because AshAuthentication.Errors.AuthenticationFailed does not implement the `AshPhoenix.FormData.Error` protocol.

** (AshAuthentication.Errors.AuthenticationFailed) Authentication failed

I’ve read this issue: This error was unhandled because it did not implement the `AshPhoenix.FormData.Error` protocol. · Issue #516 · ash-project/ash · GitHub and tried the proposed solution, but it didn’t worked for me.

Here is my change_password action:

update :change_password do
      # Use this action to allow users to change their password by providing
      # their current password and a new password.

      require_atomic? false
      accept []
      argument :current_password, :string, sensitive?: true, allow_nil?: false

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

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

      validate confirm(:password, :password_confirmation)

      validate {AshAuthentication.Strategy.Password.PasswordValidation,
                strategy_name: :password, password_argument: :current_password}

      change {AshAuthentication.Strategy.Password.HashPasswordChange,
              strategy_name: :password}
    end

I tried to add change set_context(%{strategy_name: :password}) before the other change call, but it didn’t solved the warning.

Here are the current uses and imports on my resource:

defmodule Prepair.AshDomains.Accounts.User do
  use Ash.Resource,
    domain: Prepair.AshDomains.Accounts,
    data_layer: AshPostgres.DataLayer,
    authorizers: [Ash.Policy.Authorizer],
    extensions: [AshAuthentication]

  alias Prepair.AshDomains.Profiles.Profile

  import Prepair.AshDomains.ValidationMacros

Here are the current uses and imports in my domain (which exposes the code interfaces then used in the liveview).

I wonder if I should add AshPhoenix there.

defmodule Prepair.AshDomains.Accounts do
  use Ash.Domain

And here is my handle_event function for the save action in the Liveview:

def handle_event("save", %{"user" => params}, socket) do
    current_user = socket.assigns.current_user

    form =
      AshPhoenix.Form.for_update(current_user, :change_password,
        domain: Accounts,
        as: "user"
      )
      |> AshPhoenix.Form.validate(params)

    case AshPhoenix.Form.submit(form, params: params) do
      {:ok, _user} ->
        {:noreply,
         socket
         |> put_flash(:info, "Password updated successfully")
         |> redirect(to: ~p"/")}

      {:error, form} ->
        {:noreply,
         socket |> assign(:form, to_form(form)) |> assign(check_errors: true)}
    end
  end

Marked As Solved

Guy14

Guy14

I ended by implementing the AshPhoenix.FormData.Error for AshAuthentication.Errors.AuthenticationFailed. I’m not sure it is a good practice, but for now it does the job.

defimpl AshPhoenix.FormData.Error,
  for: AshAuthentication.Errors.AuthenticationFailed do
  def to_form_error(error) do
    {error.field, "authentication failed", []}
  end
end

Also Liked

FlyingNoodle

FlyingNoodle

  1. You need the pass the current_user as actor.
  2. You don’t need the call to validate since submit will validate your form anyway.
  3. I assume you assign you form to the socket in some other callback. In that case you can just do: AshPhoenix.Form.submit(socket.assigns.my_form_that_i_assigned, params: params, actor: current_user)

Where Next?

Popular in Questions Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New

We're in Beta

About us Mission Statement