analytics/test/plausible_web/controllers/api/external_sites_controller_test.exs
Uku Taht e71de6dc1f
Invitations (#1122)
* Invite existing user to a site

* Add invitation flow for non-existing users

* Accept and reject invitations

* Use invitation flow for existing users

* Locking mechanism for sites

* Authorization for site settings

* Show usage based on site ownership

* Add ability to remove members from a site

* Do not show settings link to viewer roles

* Ability to remove invitations

* Remove `Plausible.Sites.count_for/1`

* Fix tests

* Do not show the trial banner after the trial

* Correct trial emails

* Transfer ownership

* Send invitation email to existing user

* Add invitation email flows

* Add plug for role-based authorization

* Rename AuthorizeStatsPlug -> AuthorizeSiteAccess

* Add email flow for ownership transfer

* Fix URLs in emails

* Fix small copy issues

* Make 'People' its own section in site settings

* Notify user via email if their access has been removed

* Check site lock status when invitation is accepted

* Check lock status when user subscribes

* Make sure only admins and owners can create shared links

* Changelog

* Add LockSites to daily cron

* Clean invitations after 48 hours

* Add notices about expiry

* Add invitation expired page

* Add doc link
2021-06-16 15:00:07 +03:00

157 lines
4.5 KiB
Elixir

defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
use PlausibleWeb.ConnCase
use Plausible.Repo
import Plausible.TestUtils
setup %{conn: conn} do
user = insert(:user)
api_key = insert(:api_key, user: user, scopes: ["sites:provision:*"])
conn = Plug.Conn.put_req_header(conn, "authorization", "Bearer #{api_key.key}")
{:ok, user: user, api_key: api_key, conn: conn}
end
describe "POST /api/v1/sites" do
test "can create a site", %{conn: conn} do
conn =
post(conn, "/api/v1/sites", %{
"domain" => "some-site.domain",
"timezone" => "Europe/Tallinn"
})
assert json_response(conn, 200) == %{
"domain" => "some-site.domain",
"timezone" => "Europe/Tallinn"
}
end
test "timezone defaults to Etc/UTC", %{conn: conn} do
conn =
post(conn, "/api/v1/sites", %{
"domain" => "some-site.domain"
})
assert json_response(conn, 200) == %{
"domain" => "some-site.domain",
"timezone" => "Etc/UTC"
}
end
test "domain is required", %{conn: conn} do
conn = post(conn, "/api/v1/sites", %{})
assert json_response(conn, 400) == %{
"error" => "domain can't be blank"
}
end
test "does not allow creating more sites than the limit", %{conn: conn, user: user} do
Application.put_env(:plausible, :site_limit, 3)
insert(:site, members: [user])
insert(:site, members: [user])
insert(:site, members: [user])
conn =
post(conn, "/api/v1/sites", %{
"domain" => "some-site.domain",
"timezone" => "Europe/Tallinn"
})
assert json_response(conn, 403) == %{
"error" =>
"Your account has reached the limit of 3 sites per account. Please contact hello@plausible.io to unlock more sites."
}
end
test "cannot access with a bad API key scope", %{conn: conn, user: user} do
api_key = insert(:api_key, user: user, scopes: ["stats:read:*"])
conn =
conn
|> Plug.Conn.put_req_header("authorization", "Bearer #{api_key.key}")
|> post("/api/v1/sites", %{"site" => %{"domain" => "domain.com"}})
assert json_response(conn, 401) == %{
"error" =>
"Invalid API key. Please make sure you're using a valid API key with access to the resource you've requested."
}
end
end
describe "PUT /api/v1/sites/shared-links" do
setup :create_site
test "can add a shared link to a site", %{conn: conn, site: site} do
conn =
put(conn, "/api/v1/sites/shared-links", %{
site_id: site.domain,
name: "Wordpress"
})
res = json_response(conn, 200)
assert res["name"] == "Wordpress"
assert String.starts_with?(res["url"], "http://")
end
test "is idempotent find or create op", %{conn: conn, site: site} do
conn =
put(conn, "/api/v1/sites/shared-links", %{
site_id: site.domain,
name: "Wordpress"
})
%{"url" => url} = json_response(conn, 200)
conn =
put(conn, "/api/v1/sites/shared-links", %{
site_id: site.domain,
name: "Wordpress"
})
assert %{"url" => ^url} = json_response(conn, 200)
end
test "returns 400 when site id missing", %{conn: conn} do
conn =
put(conn, "/api/v1/sites/shared-links", %{
name: "Wordpress"
})
res = json_response(conn, 400)
assert res["error"] == "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", %{
name: "Wordpress",
site_id: "bad"
})
res = json_response(conn, 404)
assert res["error"] == "Site could not be found"
end
test "returns 404 when api key owner does not have permissions to create a shared link", %{
conn: conn,
site: site,
user: user
} do
Repo.update_all(
from(sm in Plausible.Site.Membership,
where: sm.site_id == ^site.id and sm.user_id == ^user.id
),
set: [role: :viewer]
)
conn =
put(conn, "/api/v1/sites/shared-links", %{
site_id: site.domain,
name: "Wordpress"
})
res = json_response(conn, 404)
assert res["error"] == "Site could not be found"
end
end
end