Add validations

This commit is contained in:
Uku Taht 2021-04-14 15:04:25 +03:00
parent d473accf40
commit 80abfa6ef6
5 changed files with 63 additions and 34 deletions

View File

@ -3,6 +3,7 @@ defmodule Plausible.Auth.ApiKey do
import Ecto.Changeset import Ecto.Changeset
@required [:user_id, :key, :name] @required [:user_id, :key, :name]
@optional [:scopes]
schema "api_keys" do schema "api_keys" do
field :name, :string field :name, :string
field :scopes, {:array, :string}, default: ["stats:read:*"] field :scopes, {:array, :string}, default: ["stats:read:*"]
@ -18,7 +19,7 @@ defmodule Plausible.Auth.ApiKey do
def changeset(schema, attrs \\ %{}) do def changeset(schema, attrs \\ %{}) do
schema schema
|> cast(attrs, @required) |> cast(attrs, @required ++ @optional)
|> validate_required(@required) |> validate_required(@required)
|> process_key |> process_key
end end

View File

@ -38,14 +38,16 @@ defmodule Plausible.Sites do
base <> domain <> "?auth=" <> link.slug base <> domain <> "?auth=" <> link.slug
end end
def get_for_user!(user_id, domain) do def get_for_user!(user_id, domain), do: Repo.one!(get_for_user_q(user_id, domain))
Repo.one!( def get_for_user(user_id, domain), do: Repo.one(get_for_user_q(user_id, domain))
from s in Plausible.Site,
join: sm in Plausible.Site.Membership, def get_for_user_q(user_id, domain) do
on: sm.site_id == s.id, from(s in Plausible.Site,
where: sm.user_id == ^user_id, join: sm in Plausible.Site.Membership,
where: s.domain == ^domain, on: sm.site_id == s.id,
select: s where: sm.user_id == ^user_id,
where: s.domain == ^domain,
select: s
) )
end end

View File

@ -6,9 +6,8 @@ defmodule PlausibleWeb.Api.ExternalSitesController do
def create_site(conn, params) do def create_site(conn, params) do
user_id = conn.assigns[:current_user_id] user_id = conn.assigns[:current_user_id]
site_params = Map.get(params, "site", %{})
case Sites.create(user_id, site_params) do case Sites.create(user_id, params) do
{:ok, %{site: site}} -> {:ok, %{site: site}} ->
json(conn, site) json(conn, site)
@ -19,22 +18,39 @@ defmodule PlausibleWeb.Api.ExternalSitesController do
end end
end end
def find_or_create_shared_link(conn, %{"domain" => domain, "link_name" => link_name}) do def find_or_create_shared_link(conn, %{"link_name" => link_name} = params) do
site = Sites.get_for_user!(conn.assigns[:current_user_id], domain) with {:ok, site_id} <- Map.fetch(params, "site_id"),
shared_link = Repo.get_by(Plausible.Site.SharedLink, site_id: site.id, name: link_name) site when not is_nil(site) <- Sites.get_for_user(conn.assigns[:current_user_id], site_id) do
shared_link = Repo.get_by(Plausible.Site.SharedLink, site_id: site.id, name: link_name)
shared_link =
case shared_link do
nil -> Sites.create_shared_link(site, link_name)
link -> {:ok, link}
end
shared_link =
case shared_link do case shared_link do
nil -> Sites.create_shared_link(site, link_name) {:ok, link} ->
link -> {:ok, link} json(conn, %{
name: link.name,
url: Sites.shared_link_url(site, link)
})
end end
else
nil ->
conn
|> put_status(404)
|> json(%{error: "Site could not be found"})
case shared_link do :error ->
{:ok, link} -> conn
json(conn, %{ |> put_status(400)
name: link.name, |> json(%{error: "Query parameter `site_id` is required to create a shared link"})
url: Sites.shared_link_url(site, link)
}) e ->
conn
|> put_status(400)
|> json(%{error: "Something went wrong: #{inspect(e)}"})
end end
end end

View File

@ -84,7 +84,7 @@ defmodule PlausibleWeb.Router do
pipe_through [:public_api, PlausibleWeb.AuthorizeSitesApiPlug] pipe_through [:public_api, PlausibleWeb.AuthorizeSitesApiPlug]
post "/", ExternalSitesController, :create_site post "/", ExternalSitesController, :create_site
put "/:domain/shared-links/:link_name", ExternalSitesController, :find_or_create_shared_link put "/shared-links/:link_name", ExternalSitesController, :find_or_create_shared_link
end end
scope "/api", PlausibleWeb do scope "/api", PlausibleWeb do

View File

@ -13,10 +13,8 @@ defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
test "can create a site", %{conn: conn} do test "can create a site", %{conn: conn} do
conn = conn =
post(conn, "/api/v1/sites", %{ post(conn, "/api/v1/sites", %{
"site" => %{ "domain" => "some-site.domain",
"domain" => "some-site.domain", "timezone" => "Europe/Tallinn"
"timezone" => "Europe/Tallinn"
}
}) })
assert json_response(conn, 200) == %{ assert json_response(conn, 200) == %{
@ -28,9 +26,7 @@ defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
test "timezone defaults to Etc/Greenwich", %{conn: conn} do test "timezone defaults to Etc/Greenwich", %{conn: conn} do
conn = conn =
post(conn, "/api/v1/sites", %{ post(conn, "/api/v1/sites", %{
"site" => %{ "domain" => "some-site.domain"
"domain" => "some-site.domain"
}
}) })
assert json_response(conn, 200) == %{ assert json_response(conn, 200) == %{
@ -66,7 +62,7 @@ defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
setup :create_site setup :create_site
test "can add a shared link to a site", %{conn: conn, site: site} do test "can add a shared link to a site", %{conn: conn, site: site} do
conn = put(conn, "/api/v1/sites/#{site.domain}/shared-links/Wordpress") conn = put(conn, "/api/v1/sites/shared-links/Wordpress?site_id=#{site.domain}")
res = json_response(conn, 200) res = json_response(conn, 200)
assert res["name"] == "Wordpress" assert res["name"] == "Wordpress"
@ -74,13 +70,27 @@ defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
end end
test "is idempotent find or create op", %{conn: conn, site: site} do test "is idempotent find or create op", %{conn: conn, site: site} do
conn = put(conn, "/api/v1/sites/#{site.domain}/shared-links/Wordpress") conn = put(conn, "/api/v1/sites/shared-links/Wordpress?site_id=#{site.domain}")
%{"url" => url} = json_response(conn, 200) %{"url" => url} = json_response(conn, 200)
conn = put(conn, "/api/v1/sites/#{site.domain}/shared-links/Wordpress") conn = put(conn, "/api/v1/sites/shared-links/Wordpress?site_id=#{site.domain}")
assert %{"url" => ^url} = json_response(conn, 200) assert %{"url" => ^url} = json_response(conn, 200)
end end
test "returns 400 when site id missing", %{conn: conn} do
conn = put(conn, "/api/v1/sites/shared-links/Wordpress")
res = json_response(conn, 400)
assert res["error"] == "Query parameter `site_id` is required to create a shared link"
end
test "returns 404 when site id is non existent", %{conn: conn} do
conn = put(conn, "/api/v1/sites/shared-links/Wordpress?site_id=bad")
res = json_response(conn, 404)
assert res["error"] == "Site could not be found"
end
end end
end end