analytics/lib/plausible_web/plugs/authorize_api_stats.ex
Uku Taht a29ac44434
Api improvements (#723)
* Require date parameter with custom period

* Validate format of the `date` param with custom period

* Return proper status codes for auth failures

* Add breakdown endpoint

* Fix pagination

* Add API validations for breakdown call

* Change the breakdown endpoint to return an object instead of an array

* Remove change to aggregate call

* Change timeseries call
2021-02-22 10:21:25 +02:00

74 lines
1.9 KiB
Elixir

defmodule PlausibleWeb.AuthorizeApiStatsPlug do
import Plug.Conn
use Plausible.Repo
alias Plausible.Auth.ApiKey
def init(options) do
options
end
def call(conn, _opts) do
with {:ok, api_key} <- get_bearer_token(conn),
{:ok, site} <- verify_access(api_key, conn.params["site_id"]) do
assign(conn, :site, site)
else
{:error, :missing_api_key} ->
unauthorized(
conn,
"Missing API key. Please use a valid Plausible API key as a Bearer Token."
)
{:error, :missing_site_id} ->
bad_request(
conn,
"Missing site ID. Please provide the required site_id parameter with your request."
)
{:error, :invalid_api_key} ->
unauthorized(
conn,
"Invalid API key or site ID. Please make sure you're using a valid API key with access to the site you've requested."
)
end
end
defp verify_access(_api_key, nil), do: {:error, :missing_site_id}
defp verify_access(api_key, site_id) do
hashed_key = ApiKey.do_hash(api_key)
found_key = Repo.get_by(ApiKey, key_hash: hashed_key)
site = Repo.get_by(Plausible.Site, domain: site_id)
is_owner = site && found_key && Plausible.Sites.is_owner?(found_key.user_id, site)
cond do
found_key && site && is_owner -> {:ok, site}
true -> {:error, :invalid_api_key}
end
end
defp get_bearer_token(conn) do
authorization_header =
Plug.Conn.get_req_header(conn, "authorization")
|> List.first()
case authorization_header do
"Bearer " <> token -> {:ok, String.trim(token)}
_ -> {:error, :missing_api_key}
end
end
defp bad_request(conn, msg) do
conn
|> put_status(400)
|> Phoenix.Controller.json(%{error: msg})
|> halt()
end
defp unauthorized(conn, msg) do
conn
|> put_status(401)
|> Phoenix.Controller.json(%{error: msg})
|> halt()
end
end