diff --git a/lib/plausible_web/plugs/authorize_stats_api.ex b/lib/plausible_web/plugs/authorize_stats_api.ex index e16ce6437a..d98e3ae2a3 100644 --- a/lib/plausible_web/plugs/authorize_stats_api.ex +++ b/lib/plausible_web/plugs/authorize_stats_api.ex @@ -46,9 +46,11 @@ defmodule PlausibleWeb.AuthorizeStatsApiPlug do defp verify_access(api_key, site_id) do site = Repo.get_by(Plausible.Site, domain: site_id) is_member = site && Plausible.Sites.is_member?(api_key.user_id, site) + is_admin = api_key.user_id in admin_user_ids() cond do site && is_member -> {:ok, site} + site && is_admin -> {:ok, site} true -> {:error, :invalid_api_key} end end @@ -77,4 +79,8 @@ defmodule PlausibleWeb.AuthorizeStatsApiPlug do {:deny, _} -> {:error, :rate_limit, api_key.hourly_request_limit} end end + + defp admin_user_ids() do + Application.get_env(:plausible, :admin_user_ids) + end end diff --git a/test/plausible_web/controllers/api/external_stats_controller/auth_test.exs b/test/plausible_web/controllers/api/external_stats_controller/auth_test.exs index ce65e91b70..6f40b52c1f 100644 --- a/test/plausible_web/controllers/api/external_stats_controller/auth_test.exs +++ b/test/plausible_web/controllers/api/external_stats_controller/auth_test.exs @@ -52,6 +52,33 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AuthTest do } end + test "can access with correct API key and site ID", %{conn: conn, user: user, api_key: api_key} do + site = insert(:site, members: [user]) + + conn = + conn + |> Plug.Conn.put_req_header("authorization", "Bearer #{api_key}") + |> get("/api/v1/stats/aggregate", %{"site_id" => site.domain, "metrics" => "pageviews"}) + + assert json_response(conn, 200) == %{ + "results" => %{"pageviews" => %{"value" => 0}} + } + end + + test "can access as an admin", %{conn: conn, user: user, api_key: api_key} do + Application.put_env(:plausible, :admin_user_ids, [user.id]) + site = insert(:site) + + conn = + conn + |> Plug.Conn.put_req_header("authorization", "Bearer #{api_key}") + |> get("/api/v1/stats/aggregate", %{"site_id" => site.domain, "metrics" => "pageviews"}) + + assert json_response(conn, 200) == %{ + "results" => %{"pageviews" => %{"value" => 0}} + } + end + test "limits the rate of API requests", %{user: user} do api_key = insert(:api_key, user_id: user.id, hourly_request_limit: 3)