Handling complex validation logic in changeset

Hi everyone,

I’m trying to improve the process to invite a user into our platform, right now the code is simple:

    with :ok <- Bodyguard.permit(Machines, :share_machine, current_user, machine) do
      case Users.get_user_by_email(user_email, current_user.realm_id) do
        nil ->
          conn
          |> put_status(:unprocessable_entity)
          |> json(%{message: "User not found"})

        user ->
          {:ok, _} = Machines.share_machien_with_user(user, machine)
          send_resp(conn, 204, "")
      end
    end

instead of returning a 422 with a custom message I would like to do return an error in the changeset field email.
Should I just include a function in the changeset to check for the existing user and add an error if it doesn’t exist?

In case I want the Users.get_user_by_email to be something more complex, like inviting a user, what should I do? Because in that case:

  • the user is an external entity and in that case I should probably create it via Ecto.multi I suppose
  • if the user creation/invite fails, I would still be required to use the original changeset and change it to invalid to put the user creation error in the email field, right?

Thanks in advance