Add :payment_required policy to GateKeeper (#3628)

* Migration: Add `accept_traffic_until` to "sites"

* Drop traffic from sites where `accept_traffic_until` is passed
This commit is contained in:
hq1 2023-12-13 14:52:32 +01:00 committed by GitHub
parent 3f5eecf15f
commit 8d85c38047
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 12 deletions

View File

@ -21,6 +21,7 @@ defmodule Plausible.Site do
field :conversions_enabled, :boolean, default: true
field :props_enabled, :boolean, default: true
field :funnels_enabled, :boolean, default: true
field :accept_traffic_until, :naive_datetime
field :ingest_rate_limit_scale_seconds, :integer, default: 60
# default is set via changeset/2

View File

@ -56,6 +56,7 @@ defmodule Plausible.Site.Cache do
domain_changed_from
ingest_rate_limit_scale_seconds
ingest_rate_limit_threshold
accept_traffic_until
)a
@type t() :: Site.t()

View File

@ -1,5 +1,5 @@
defmodule Plausible.Site.GateKeeper do
@type policy() :: :allow | :not_found | :block | :throttle
@type policy() :: :allow | :not_found | :block | :throttle | :payment_required
@policy_for_non_existing_sites :not_found
@type t() :: {:allow, Plausible.Site.t()} | {:deny, policy()}
@ -43,16 +43,18 @@ defmodule Plausible.Site.GateKeeper do
end
defp policy(domain, opts) when is_binary(domain) do
result =
case Cache.get(domain, Keyword.get(opts, :cache_opts, [])) do
nil ->
@policy_for_non_existing_sites
%Site{} = site ->
check_rate_limit(site, opts)
with from_cache <- Cache.get(domain, Keyword.get(opts, :cache_opts, [])),
site = %Site{accept_traffic_until: accept_traffic_until} <- from_cache do
if not is_nil(accept_traffic_until) and
NaiveDateTime.after?(NaiveDateTime.utc_now(), accept_traffic_until) do
:payment_required
else
check_rate_limit(site, opts)
end
result
else
_ ->
@policy_for_non_existing_sites
end
end
defp check_rate_limit(%Site{ingest_rate_limit_threshold: nil} = site, _opts) do

View File

@ -100,6 +100,23 @@ defmodule Plausible.Ingestion.EventTest do
assert dropped.drop_reason == :throttle
end
test "event pipeline drops events for site with accept_trafic_until in the past" do
yesterday = NaiveDateTime.add(NaiveDateTime.utc_now(), -1, :day)
site = insert(:site, ingest_rate_limit_threshold: 1, accept_traffic_until: yesterday)
payload = %{
name: "pageview",
url: "http://dummy.site",
d: "#{site.domain}"
}
conn = build_conn(:post, "/api/events", payload)
assert {:ok, request} = Request.build(conn)
assert {:ok, %{buffered: [], dropped: [dropped]}} = Event.build_and_buffer(request)
assert dropped.drop_reason == :payment_required
end
@tag :full_build_only
test "saves revenue amount" do
site = insert(:site)

View File

@ -34,7 +34,9 @@ defmodule Plausible.Site.CacheTest do
)
%{id: first_id} = site1 = insert(:site, domain: "site1.example.com")
_ = insert(:site, domain: "site2.example.com")
_ =
insert(:site, domain: "site2.example.com", accept_traffic_until: ~N[2021-01-01 00:00:00])
:ok = Cache.refresh_all(cache_name: test)
@ -48,7 +50,8 @@ defmodule Plausible.Site.CacheTest do
assert %Site{from_cache?: true} =
Cache.get("site2.example.com", force?: true, cache_name: test)
assert %Site{from_cache?: false} = Cache.get("site2.example.com", cache_name: test)
assert %Site{from_cache?: false, accept_traffic_until: ~N[2021-01-01 00:00:00]} =
Cache.get("site2.example.com", cache_name: test)
refute Cache.get("site3.example.com", cache_name: test, force?: true)
end

View File

@ -14,6 +14,15 @@ defmodule Plausible.Site.GateKeeperTest do
assert {:deny, :not_found} = GateKeeper.check("example.com", opts)
end
test "sites with accepted_traffic_until < now are denied", %{test: test, opts: opts} do
domain = "expired.example.com"
yesterday = NaiveDateTime.utc_now() |> NaiveDateTime.add(-1, :day)
%{id: _} = add_site_and_refresh_cache(test, domain: domain, accept_traffic_until: yesterday)
assert {:deny, :payment_required} = GateKeeper.check(domain, opts)
end
test "site from cache with no ingest_rate_limit_threshold is allowed", %{test: test, opts: opts} do
domain = "site1.example.com"
@ -92,6 +101,7 @@ defmodule Plausible.Site.GateKeeperTest do
defp add_site_and_refresh_cache(cache_name, site_data) do
site = insert(:site, site_data)
Cache.refresh_updated_recently(cache_name: cache_name, force?: true)
site
end