From 7ddb1ed35fb18e0639a0117714c75a312eb3e57c Mon Sep 17 00:00:00 2001 From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Date: Sat, 11 Jul 2026 01:01:18 -0700 Subject: [PATCH] fix: return 400 instead of 500 for malformed task_ids on task pack create --- .../lib/codebattle/forms/task_pack.ex | 12 +- .../controllers/task_pack_controller_test.exs | 118 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/apps/codebattle/lib/codebattle/forms/task_pack.ex b/apps/codebattle/lib/codebattle/forms/task_pack.ex index 0cbb8a4ba..fff67aabd 100644 --- a/apps/codebattle/lib/codebattle/forms/task_pack.ex +++ b/apps/codebattle/lib/codebattle/forms/task_pack.ex @@ -6,6 +6,8 @@ defmodule Codebattle.TaskPackForm do alias Codebattle.Repo alias Codebattle.TaskPack + @task_id_range 1..2_147_483_647 + def create(params, user) do new_params = Map.merge(params, %{"state" => "draft", "creator_id" => user.id}) @@ -51,7 +53,15 @@ defmodule Codebattle.TaskPackForm do |> Enum.map(&String.trim/1) |> Enum.map(&String.to_integer/1) - put_change(changeset, :task_ids, task_ids) + if Enum.all?(task_ids, &(&1 in @task_id_range)) do + put_change(changeset, :task_ids, task_ids) + else + add_error( + changeset, + :task_ids, + "Please provide integers between 1 and 2147483647 with comma separated values" + ) + end rescue _ -> add_error(changeset, :task_ids, "Please provide only integers with comma separated values") diff --git a/apps/codebattle/test/codebattle_web/controllers/task_pack_controller_test.exs b/apps/codebattle/test/codebattle_web/controllers/task_pack_controller_test.exs index fbfd8b8e0..b21ab095c 100644 --- a/apps/codebattle/test/codebattle_web/controllers/task_pack_controller_test.exs +++ b/apps/codebattle/test/codebattle_web/controllers/task_pack_controller_test.exs @@ -113,6 +113,80 @@ defmodule CodebattleWeb.TaskPackControllerTest do } = task_pack end + test ".create with non-numeric task ids", %{conn: conn} do + user = insert(:user) + + params = %{ + "name" => "mega_pack", + "task_ids" => "It is string", + "visibility" => "public" + } + + conn = + conn + |> put_session(:user_id, user.id) + |> post(Routes.task_pack_path(conn, :create), task_pack: params) + + response = html_response(conn, 200) + + assert response =~ "Create your own task pack" + assert response =~ "Please provide only integers with comma separated values" + end + + test ".create with out-of-range task ids", %{conn: conn} do + user = insert(:user) + + params = %{ + "name" => "mega_pack", + "task_ids" => "999999999999999999", + "visibility" => "public" + } + + conn = + conn + |> put_session(:user_id, user.id) + |> post(Routes.task_pack_path(conn, :create), task_pack: params) + + response = html_response(conn, 200) + + assert response =~ "Create your own task pack" + + assert response =~ + "Please provide integers between 1 and 2147483647 with comma separated values" + end + + test ".create validates task id range boundaries", %{conn: conn} do + user = insert(:user) + + conn = put_session(conn, :user_id, user.id) + + valid_conn = + post(conn, Routes.task_pack_path(conn, :create), + task_pack: %{ + "name" => "max_task_id_pack", + "task_ids" => "2147483647", + "visibility" => "public" + } + ) + + assert %{id: id} = redirected_params(valid_conn) + assert %{task_ids: [2_147_483_647]} = Codebattle.TaskPack.get!(id) + + Enum.each(["0", "1,2147483648,3"], fn task_ids -> + invalid_conn = + post(conn, Routes.task_pack_path(conn, :create), + task_pack: %{ + "name" => "invalid_task_id_pack", + "task_ids" => task_ids, + "visibility" => "public" + } + ) + + assert html_response(invalid_conn, 200) =~ + "Please provide integers between 1 and 2147483647 with comma separated values" + end) + end + test ".update", %{conn: conn} do user = insert(:user) task_pack = insert(:task_pack, creator_id: user.id) @@ -136,6 +210,50 @@ defmodule CodebattleWeb.TaskPackControllerTest do assert %{name: "new_mega_task_pack", task_ids: [22]} = task_pack end + test ".update with non-numeric task ids", %{conn: conn} do + user = insert(:user) + task_pack = insert(:task_pack, creator_id: user.id) + + params = %{ + "name" => "new_mega_task_pack", + "task_ids" => "It is string", + "visibility" => "public" + } + + conn = + conn + |> put_session(:user_id, user.id) + |> patch(Routes.task_pack_path(conn, :update, task_pack), task_pack: params) + + response = html_response(conn, 200) + + assert response =~ "Edit task pack" + assert response =~ "Please provide only integers with comma separated values" + end + + test ".update with out-of-range task ids", %{conn: conn} do + user = insert(:user) + task_pack = insert(:task_pack, creator_id: user.id) + + params = %{ + "name" => "new_mega_task_pack", + "task_ids" => "999999999999999999", + "visibility" => "public" + } + + conn = + conn + |> put_session(:user_id, user.id) + |> patch(Routes.task_pack_path(conn, :update, task_pack), task_pack: params) + + response = html_response(conn, 200) + + assert response =~ "Edit task pack" + + assert response =~ + "Please provide integers between 1 and 2147483647 with comma separated values" + end + test ".activate", %{conn: conn} do user = insert(:user) admin = insert(:admin)