Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ All notable changes to this project will be documented in this file.
- Always compare against the same time range in comparisons with "Today"
- Added vertical indicator line to graph to make it easier to see what's hovered / selected

### Fixed

- Stats API `/api/v1/stats/breakdown` now returns a `400` error for an invalid `page` parameter instead of crashing with a `500`

### Removed

- Removed the standalone team switcher page; team switching is now done from the topbar dropdown only
Expand Down
15 changes: 13 additions & 2 deletions lib/plausible_web/controllers/api/external_stats_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ defmodule PlausibleWeb.Api.ExternalStatsController do
:ok <- validate_filters(site, query.filters),
{:ok, metrics} <- parse_and_validate_metrics(params, query),
{:ok, limit} <- validate_or_default_limit(params),
{:ok, page} <- validate_or_default_page(params),
:ok <- ensure_custom_props_access(site, query) do
page = String.to_integer(Map.get(params, "page", "1"))

%{results: results, meta: meta} =
Legacy.Breakdown.breakdown(site, query, metrics, {limit, page})

Expand Down Expand Up @@ -88,6 +87,18 @@ defmodule PlausibleWeb.Api.ExternalStatsController do
@default_breakdown_limit 100
defp validate_or_default_limit(_), do: {:ok, @default_breakdown_limit}

defp validate_or_default_page(%{"page" => page}) do
case Integer.parse(page) do
{page, ""} when page > 0 ->
{:ok, page}

_ ->
{:error, "Please provide page as a number greater than 0."}
end
end

defp validate_or_default_page(_), do: {:ok, 1}

defp parse_and_validate_metrics(params, query) do
metrics =
Map.get(params, "metrics", "visitors")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2492,6 +2492,41 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
assert json_response(conn, 400) == %{"error" => @invalid_limit_message}
end

@invalid_page_message "Please provide page as a number greater than 0."

test "returns error with non-integer page", %{conn: conn, site: site} do
conn =
get(conn, "/api/v1/stats/breakdown", %{
"site_id" => site.domain,
"property" => "event:page",
"page" => "bad_page"
})

assert json_response(conn, 400) == %{"error" => @invalid_page_message}
end

test "returns error with negative integer page", %{conn: conn, site: site} do
conn =
get(conn, "/api/v1/stats/breakdown", %{
"site_id" => site.domain,
"property" => "event:page",
"page" => -1
})

assert json_response(conn, 400) == %{"error" => @invalid_page_message}
end

test "returns error with zero page", %{conn: conn, site: site} do
conn =
get(conn, "/api/v1/stats/breakdown", %{
"site_id" => site.domain,
"property" => "event:page",
"page" => 0
})

assert json_response(conn, 400) == %{"error" => @invalid_page_message}
end

test "can paginate results", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, pathname: "/a", timestamp: ~N[2021-01-01 00:00:00]),
Expand Down
Loading