diff --git a/.changeset/dirty-wolves-wash.md b/.changeset/dirty-wolves-wash.md new file mode 100644 index 0000000000..4ffbb89725 --- /dev/null +++ b/.changeset/dirty-wolves-wash.md @@ -0,0 +1,5 @@ +--- +"@core/sync-service": patch +--- + +Fix root table parameter validation to return 400 when missing diff --git a/packages/sync-service/lib/electric/plug/serve_shape_plug.ex b/packages/sync-service/lib/electric/plug/serve_shape_plug.ex index 7fca9241f7..bad8e694b8 100644 --- a/packages/sync-service/lib/electric/plug/serve_shape_plug.ex +++ b/packages/sync-service/lib/electric/plug/serve_shape_plug.ex @@ -153,6 +153,8 @@ defmodule Electric.Plug.ServeShapePlug do end end + def cast_root_table(%Ecto.Changeset{valid?: false} = changeset, _), do: changeset + def cast_root_table(%Ecto.Changeset{} = changeset, opts) do table = fetch_change!(changeset, :table) where = fetch_field!(changeset, :where) diff --git a/packages/sync-service/test/electric/plug/serve_shape_plug_test.exs b/packages/sync-service/test/electric/plug/serve_shape_plug_test.exs index 0b98c8c1bb..cf395216a5 100644 --- a/packages/sync-service/test/electric/plug/serve_shape_plug_test.exs +++ b/packages/sync-service/test/electric/plug/serve_shape_plug_test.exs @@ -152,22 +152,43 @@ defmodule Electric.Plug.ServeShapePlugTest do :with_tenant_id ] - test "returns 400 for invalid params", ctx do + test "returns 400 for invalid table", ctx do conn = ctx - |> conn(:get, %{"table" => ".invalid_shape"}, "?offset=invalid") + |> conn(:get, %{"table" => ".invalid_shape"}, "?offset=-1") |> ServeShapePlug.call([]) assert conn.status == 400 assert Jason.decode!(conn.resp_body) == %{ - "offset" => ["has invalid format"], "table" => [ "Invalid zero-length delimited identifier" ] } end + test "returns 400 for invalid offset", ctx do + conn = + ctx + |> conn(:get, %{"table" => "foo"}, "?offset=invalid") + |> ServeShapePlug.call([]) + + assert conn.status == 400 + + assert Jason.decode!(conn.resp_body) == %{"offset" => ["has invalid format"]} + end + + test "returns 400 when table param is missing", ctx do + conn = + ctx + |> conn(:get, %{}, "?offset=-1") + |> ServeShapePlug.call([]) + + assert conn.status == 400 + + assert %{"table" => ["can't be blank"]} = Jason.decode!(conn.resp_body) + end + test "returns 400 when table does not exist", ctx do # this will pass table name validation # but will fail to find the table