Custom reset password form has no validation when submitting

I made my own authentication forms using ash_authentication as basis so I have more flexibility especially when it comes to styling. It works for almost everything only the validations does not work for :request_password_reset_with_password. I set up my form like:

    form =
      AshPhoenix.Form.for_action(User, :request_password_reset_with_password,
        api: Account,
        as: "user",
        context: %{private: %{ash_authentication?: true}}
      |> to_form()

And it does enter my validate form:

  def handle_event("validate", %{"user" => params}, socket) do
    %{form: form} = socket.assigns
    form = AshPhoenix.Form.validate(form, params)
    {:noreply, assign(socket, form: form)}

where user has a validation on email:

  validations do
    validate match(:email, ~r/(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)/) do
      message "must be a valid email address"

And which also works for the registration form so Im not sure what Im doing wrong. Only resource I found was a discord archived support page where it was said to use:
context: %{private: %{ash_authentication?: true}}. But all of the examples of what Im trying to do can just use the validate and it seems to work, although using a bit of a different setup so if more information is needed let me know.

Interesting :thinking:. I don’t think you’ll want to use that context thing, thats kind of a hack (and likely would have no effect in this case). When you say it doesn’t work do you mean the validation is not applied? Can you show the output of Ash.Resource.Info.action(User, :request_password_reset_with_password)?

That would be:

  arguments: [
      allow_nil?: false,
      type: Ash.Type.CiString,
      name: :email,
      default: nil,
      private?: false,
      sensitive?: false,
      description: "The proposed identity to send reset instructions to.",
      constraints: [casing: nil, allow_empty?: false, trim?: true]
  description: "Send password reset instructions to a user if they exist.",
  filter: nil,
  get_by: [],
  get?: false,
  manual: nil,
  metadata: [],
  modify_query: nil,
  name: :request_password_reset_with_password,
  pagination: false,
  preparations: [
      preparation: {AshAuthentication.Strategy.Password.RequestPasswordResetPreparation,
  primary?: false,
  touches_resources: [],
  timeout: nil,
  transaction?: false,
  type: :read

Ah, okay, right. So, unfortunately, validations don’t work on read actions. I’ve been meaning to add a compatibility layer for this to allow validations to support queries in addition to change sets (essentially operating only on arguments). In the meantime, what you will need to do to work around this is add a preparation.

preparations do
  prepare ValidateEmail, where: [action_is(:request_password_reset_with_password)]

That ValidateEmail would be a standard hand-written preparation.

This is a pretty clear thing we can improve in the framework, and I hope to address this soon to make it a better experience.