From eea70797761d6e870538d800ac326e42b28db701 Mon Sep 17 00:00:00 2001 From: Brian Manifold Date: Thu, 16 Jan 2025 19:13:45 -0500 Subject: [PATCH] fix(portal): Catch seat limit error in API fallback controller (#7783) Why: * The fallback controller in the API was not catching `{:error, :seat_limit_reached}` being returned and was then generating a 500 response when this happened. This commit adds the condition in the fallback controller and adds a new template for a more specific error message in the returned JSON. --- .../api/lib/api/controllers/error_json.ex | 4 ++ .../api/controllers/fallback_controller.ex | 14 +++++ .../api/controllers/actor_controller_test.exs | 52 +++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/elixir/apps/api/lib/api/controllers/error_json.ex b/elixir/apps/api/lib/api/controllers/error_json.ex index 67228173d..61cdadd02 100644 --- a/elixir/apps/api/lib/api/controllers/error_json.ex +++ b/elixir/apps/api/lib/api/controllers/error_json.ex @@ -1,4 +1,8 @@ defmodule API.ErrorJSON do + def render(_template, %{reason: reason} = _assigns) do + %{error: %{reason: reason}} + end + def render(template, _assigns) do %{error: %{reason: Phoenix.Controller.status_message_from_template(template)}} end diff --git a/elixir/apps/api/lib/api/controllers/fallback_controller.ex b/elixir/apps/api/lib/api/controllers/fallback_controller.ex index f08047aa3..4b0c29023 100644 --- a/elixir/apps/api/lib/api/controllers/fallback_controller.ex +++ b/elixir/apps/api/lib/api/controllers/fallback_controller.ex @@ -29,6 +29,20 @@ defmodule API.FallbackController do |> render(:"422") end + def call(conn, {:error, :seats_limit_reached}) do + conn + |> put_status(:unprocessable_entity) + |> put_view(json: API.ErrorJSON) + |> render(:error, reason: "Seat Limit Reached") + end + + def call(conn, {:error, :service_accounts_limit_reached}) do + conn + |> put_status(:unprocessable_entity) + |> put_view(json: API.ErrorJSON) + |> render(:error, reason: "Service Accounts Limit Reached") + end + def call(conn, {:error, %Ecto.Changeset{} = changeset}) do conn |> put_status(:unprocessable_entity) diff --git a/elixir/apps/api/test/api/controllers/actor_controller_test.exs b/elixir/apps/api/test/api/controllers/actor_controller_test.exs index 90dad7393..f42932b88 100644 --- a/elixir/apps/api/test/api/controllers/actor_controller_test.exs +++ b/elixir/apps/api/test/api/controllers/actor_controller_test.exs @@ -145,6 +145,58 @@ defmodule API.ActorControllerTest do } end + test "returns error when user seat limit hit", %{ + conn: conn, + account: account, + actor: api_actor + } do + Domain.Accounts.update_account(account, %{ + limits: %{users_count: 1} + }) + + Fixtures.Actors.create_actor(type: :account_user, account: account) + + attrs = %{ + "name" => "Test User", + "type" => "account_user" + } + + conn = + conn + |> authorize_conn(api_actor) + |> put_req_header("content-type", "application/json") + |> post("/actors", actor: attrs) + + assert resp = json_response(conn, 422) + assert resp == %{"error" => %{"reason" => "Seat Limit Reached"}} + end + + test "returns error when service account seat limit hit", %{ + conn: conn, + account: account, + actor: api_actor + } do + Domain.Accounts.update_account(account, %{ + limits: %{service_accounts_count: 1} + }) + + Fixtures.Actors.create_actor(type: :service_account, account: account) + + attrs = %{ + "name" => "Test Service Account", + "type" => "service_account" + } + + conn = + conn + |> authorize_conn(api_actor) + |> put_req_header("content-type", "application/json") + |> post("/actors", actor: attrs) + + assert resp = json_response(conn, 422) + assert resp == %{"error" => %{"reason" => "Service Accounts Limit Reached"}} + end + test "creates a actor with valid attrs", %{conn: conn, actor: api_actor} do # TODO: At the moment, API clients aren't allowed to create admin users attrs = %{