From 7782870cc12f794feda7a6131b7bb97f80c3ae10 Mon Sep 17 00:00:00 2001 From: T Floyd Wright Date: Mon, 10 Aug 2026 10:00:06 -0800 Subject: [PATCH] fix: normalize invalid pagination params in the url An invalid page/per/sort query param raised Ecto.InvalidChangesetError, 500ing the resource view. Fall back to defaults when casting these params, and redirect to the canonical URL so an invalid value is transparently replaced rather than left mismatched in the address bar. --- lib/live_admin/components/container.ex | 13 ++++++++++--- test/live_admin/components/container_test.exs | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/live_admin/components/container.ex b/lib/live_admin/components/container.ex index 39a80fe..0883465 100644 --- a/lib/live_admin/components/container.ex +++ b/lib/live_admin/components/container.ex @@ -263,14 +263,21 @@ defmodule LiveAdmin.Components.Container do params = {defaults, types} |> Ecto.Changeset.cast(params, Map.keys(types)) - |> Ecto.Changeset.apply_action!(:update) + |> Ecto.Changeset.apply_changes() assign(socket, params) end defp redirect_with_params(socket, params) do - if Enum.all?(["per", "page", "sort-attr", "sort-dir"], &Map.has_key?(params, &1)) && - Map.get(params, "prefix") == socket.assigns.prefix do + canonical = %{ + "page" => to_string(socket.assigns.page), + "per" => to_string(socket.assigns.per), + "sort-attr" => to_string(socket.assigns.sort_attr), + "sort-dir" => to_string(socket.assigns.sort_dir), + "prefix" => socket.assigns.prefix + } + + if Enum.all?(canonical, fn {key, val} -> Map.get(params, key) == val end) do socket else push_navigate(socket, diff --git a/test/live_admin/components/container_test.exs b/test/live_admin/components/container_test.exs index ba85295..dd0acb2 100644 --- a/test/live_admin/components/container_test.exs +++ b/test/live_admin/components/container_test.exs @@ -100,6 +100,23 @@ defmodule LiveAdmin.Components.ContainerTest do end end + describe "list resource with invalid page param" do + setup %{conn: conn} do + Repo.insert!(%User{}) + + {:error, {:live_redirect, %{to: redirect_to}}} = + live(conn, "/user?prefix=public&per=10&page=abc&sort-attr=id&sort-dir=asc") + + %{redirect_to: redirect_to} + end + + test "redirects to url with the invalid param replaced by the default", %{ + redirect_to: redirect_to + } do + assert redirect_to =~ ~r/page=1(?![0-9])/ + end + end + describe "list resource with search param not matching any records" do setup %{conn: conn} do Repo.insert!(%User{name: "Tom"})