Refactor Paddle webhook (#4938)
* Refactor Paddle webhook handler * Make Paddle webhook work with both old and new format and add EE prefix * Don't send EE enabled prefix from CE
This commit is contained in:
parent
c29b93f30c
commit
27fac66808
|
|
@ -17,7 +17,8 @@ defmodule Mix.Tasks.CreateFreeSubscription do
|
||||||
user = Repo.get(Plausible.Auth.User, user_id)
|
user = Repo.get(Plausible.Auth.User, user_id)
|
||||||
{:ok, team} = Plausible.Teams.get_or_create(user)
|
{:ok, team} = Plausible.Teams.get_or_create(user)
|
||||||
|
|
||||||
Subscription.free(%{team_id: team.id})
|
team
|
||||||
|
|> Subscription.free()
|
||||||
|> Repo.insert!()
|
|> Repo.insert!()
|
||||||
|
|
||||||
IO.puts("Created a free subscription for user: #{user.name}")
|
IO.puts("Created a free subscription for user: #{user.name}")
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ defmodule Plausible.Billing do
|
||||||
use Plausible
|
use Plausible
|
||||||
use Plausible.Repo
|
use Plausible.Repo
|
||||||
require Plausible.Billing.Subscription.Status
|
require Plausible.Billing.Subscription.Status
|
||||||
|
alias Plausible.Auth
|
||||||
alias Plausible.Billing.Subscription
|
alias Plausible.Billing.Subscription
|
||||||
alias Plausible.Auth.User
|
|
||||||
alias Plausible.Teams
|
alias Plausible.Teams
|
||||||
|
|
||||||
def subscription_created(params) do
|
def subscription_created(params) do
|
||||||
|
|
@ -44,25 +44,15 @@ defmodule Plausible.Billing do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_subscription_created(params) do
|
defp handle_subscription_created(params) do
|
||||||
params =
|
team = get_team!(params)
|
||||||
if present?(params["passthrough"]) do
|
|
||||||
format_params(params)
|
|
||||||
else
|
|
||||||
user = Repo.get_by!(User, email: params["email"])
|
|
||||||
{:ok, team} = Plausible.Teams.get_or_create(user)
|
|
||||||
|
|
||||||
params
|
|
||||||
|> Map.put("passthrough", user.id)
|
|
||||||
|> Map.put("team_id", team.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
subscription_params =
|
subscription_params =
|
||||||
params
|
params
|
||||||
|> format_subscription()
|
|> format_subscription()
|
||||||
|> add_last_bill_date(params)
|
|> add_last_bill_date(params)
|
||||||
|
|
||||||
%Subscription{}
|
team
|
||||||
|> Subscription.changeset(subscription_params)
|
|> Subscription.create_changeset(subscription_params)
|
||||||
|> Repo.insert!()
|
|> Repo.insert!()
|
||||||
|> after_subscription_update()
|
|> after_subscription_update()
|
||||||
end
|
end
|
||||||
|
|
@ -86,10 +76,7 @@ defmodule Plausible.Billing do
|
||||||
irrelevant? = params["old_status"] == "paused" && params["status"] == "past_due"
|
irrelevant? = params["old_status"] == "paused" && params["status"] == "past_due"
|
||||||
|
|
||||||
if subscription && not irrelevant? do
|
if subscription && not irrelevant? do
|
||||||
params =
|
params = format_subscription(params)
|
||||||
params
|
|
||||||
|> format_params()
|
|
||||||
|> format_subscription()
|
|
||||||
|
|
||||||
subscription
|
subscription
|
||||||
|> Subscription.changeset(params)
|
|> Subscription.changeset(params)
|
||||||
|
|
@ -145,42 +132,66 @@ defmodule Plausible.Billing do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_params(%{"passthrough" => passthrough} = params) do
|
defp get_team!(%{"passthrough" => passthrough}) do
|
||||||
case String.split(to_string(passthrough), ";") do
|
case parse_passthrough!(passthrough) do
|
||||||
[user_id] ->
|
{:team_id, team_id} ->
|
||||||
user = Repo.get!(User, user_id)
|
Teams.get!(team_id)
|
||||||
{:ok, team} = Plausible.Teams.get_or_create(user)
|
|
||||||
Map.put(params, "team_id", team.id)
|
|
||||||
|
|
||||||
["user:" <> user_id, "team:" <> team_id] ->
|
{:user_id, user_id} ->
|
||||||
params
|
user = Repo.get!(Auth.User, user_id)
|
||||||
|> Map.put("passthrough", user_id)
|
{:ok, team} = Teams.get_or_create(user)
|
||||||
|> Map.put("team_id", team_id)
|
team
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_params(params) do
|
defp get_team!(_params) do
|
||||||
params
|
raise "Missing passthrough"
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_passthrough!(passthrough) do
|
||||||
|
{user_id, team_id} =
|
||||||
|
case String.split(to_string(passthrough), ";") do
|
||||||
|
["ee:true", "user:" <> user_id, "team:" <> team_id] ->
|
||||||
|
{user_id, team_id}
|
||||||
|
|
||||||
|
["ee:true", "user:" <> user_id] ->
|
||||||
|
{user_id, "0"}
|
||||||
|
|
||||||
|
# NOTE: legacy pattern, to be removed in a follow-up
|
||||||
|
["user:" <> user_id, "team:" <> team_id] ->
|
||||||
|
{user_id, team_id}
|
||||||
|
|
||||||
|
# NOTE: legacy pattern, to be removed in a follow-up
|
||||||
|
[user_id] ->
|
||||||
|
{user_id, "0"}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
raise "Invalid passthrough sent via Paddle: #{inspect(passthrough)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
case {Integer.parse(user_id), Integer.parse(team_id)} do
|
||||||
|
{{user_id, ""}, {0, ""}} when user_id > 0 ->
|
||||||
|
{:user_id, user_id}
|
||||||
|
|
||||||
|
{{_user_id, ""}, {team_id, ""}} when team_id > 0 ->
|
||||||
|
{:team_id, team_id}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
raise "Invalid passthrough sent via Paddle: #{inspect(passthrough)}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_subscription(params) do
|
defp format_subscription(params) do
|
||||||
subscription_params = %{
|
%{
|
||||||
paddle_subscription_id: params["subscription_id"],
|
paddle_subscription_id: params["subscription_id"],
|
||||||
paddle_plan_id: params["subscription_plan_id"],
|
paddle_plan_id: params["subscription_plan_id"],
|
||||||
cancel_url: params["cancel_url"],
|
cancel_url: params["cancel_url"],
|
||||||
update_url: params["update_url"],
|
update_url: params["update_url"],
|
||||||
user_id: params["passthrough"],
|
|
||||||
status: params["status"],
|
status: params["status"],
|
||||||
next_bill_date: params["next_bill_date"],
|
next_bill_date: params["next_bill_date"],
|
||||||
next_bill_amount: params["unit_price"] || params["new_unit_price"],
|
next_bill_amount: params["unit_price"] || params["new_unit_price"],
|
||||||
currency_code: params["currency"]
|
currency_code: params["currency"]
|
||||||
}
|
}
|
||||||
|
|
||||||
if team_id = params["team_id"] do
|
|
||||||
Map.put(subscription_params, :team_id, team_id)
|
|
||||||
else
|
|
||||||
subscription_params
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp add_last_bill_date(subscription_params, paddle_params) do
|
defp add_last_bill_date(subscription_params, paddle_params) do
|
||||||
|
|
@ -193,10 +204,6 @@ defmodule Plausible.Billing do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp present?(""), do: false
|
|
||||||
defp present?(nil), do: false
|
|
||||||
defp present?(_), do: true
|
|
||||||
|
|
||||||
@spec format_price(Money.t()) :: String.t()
|
@spec format_price(Money.t()) :: String.t()
|
||||||
def format_price(money) do
|
def format_price(money) do
|
||||||
Money.to_string!(money, fractional_digits: 2, no_fraction_if_integer: true)
|
Money.to_string!(money, fractional_digits: 2, no_fraction_if_integer: true)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ defmodule Plausible.Billing.Subscription do
|
||||||
:currency_code
|
:currency_code
|
||||||
]
|
]
|
||||||
|
|
||||||
@optional_fields [:last_bill_date, :team_id]
|
@optional_fields [:last_bill_date]
|
||||||
|
|
||||||
schema "subscriptions" do
|
schema "subscriptions" do
|
||||||
field :paddle_subscription_id, :string
|
field :paddle_subscription_id, :string
|
||||||
|
|
@ -37,14 +37,20 @@ defmodule Plausible.Billing.Subscription do
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
def changeset(model, attrs \\ %{}) do
|
def create_changeset(team, attrs \\ %{}) do
|
||||||
model
|
%__MODULE__{}
|
||||||
|
|> changeset(attrs)
|
||||||
|
|> put_assoc(:team, team)
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(subscription, attrs \\ %{}) do
|
||||||
|
subscription
|
||||||
|> cast(attrs, @required_fields ++ @optional_fields)
|
|> cast(attrs, @required_fields ++ @optional_fields)
|
||||||
|> validate_required(@required_fields)
|
|> validate_required(@required_fields)
|
||||||
|> unique_constraint(:paddle_subscription_id)
|
|> unique_constraint(:paddle_subscription_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def free(attrs \\ %{}) do
|
def free(team, attrs \\ %{}) do
|
||||||
%__MODULE__{
|
%__MODULE__{
|
||||||
paddle_plan_id: "free_10k",
|
paddle_plan_id: "free_10k",
|
||||||
status: Subscription.Status.active(),
|
status: Subscription.Status.active(),
|
||||||
|
|
@ -52,7 +58,7 @@ defmodule Plausible.Billing.Subscription do
|
||||||
currency_code: "EUR"
|
currency_code: "EUR"
|
||||||
}
|
}
|
||||||
|> cast(attrs, @required_fields ++ @optional_fields)
|
|> cast(attrs, @required_fields ++ @optional_fields)
|
||||||
|> validate_required([:team_id])
|
|> put_assoc(:team, team)
|
||||||
|> unique_constraint(:paddle_subscription_id)
|
|> unique_constraint(:paddle_subscription_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ defmodule Plausible.Teams do
|
||||||
|
|
||||||
@accept_traffic_until_free ~D[2135-01-01]
|
@accept_traffic_until_free ~D[2135-01-01]
|
||||||
|
|
||||||
|
@spec get!(pos_integer()) :: Teams.Team.t()
|
||||||
|
def get!(team_id) do
|
||||||
|
Repo.get!(Teams.Team, team_id)
|
||||||
|
end
|
||||||
|
|
||||||
@spec get_owner(Teams.Team.t()) ::
|
@spec get_owner(Teams.Team.t()) ::
|
||||||
{:ok, Plausible.Auth.User.t()} | {:error, :no_owner | :multiple_owners}
|
{:ok, Plausible.Auth.User.t()} | {:error, :no_owner | :multiple_owners}
|
||||||
def get_owner(team) do
|
def get_owner(team) do
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use PlausibleWeb, :component
|
use PlausibleWeb, :component
|
||||||
|
use Plausible
|
||||||
|
|
||||||
require Plausible.Billing.Subscription.Status
|
require Plausible.Billing.Subscription.Status
|
||||||
alias Plausible.Billing.{Subscription, Subscriptions}
|
alias Plausible.Billing.{Subscription, Subscriptions}
|
||||||
|
|
@ -237,9 +238,9 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
|
|
||||||
passthrough =
|
passthrough =
|
||||||
if assigns.team do
|
if assigns.team do
|
||||||
"user:#{assigns.user.id};team:#{assigns.team.id}"
|
"ee:#{ee?()};user:#{assigns.user.id};team:#{assigns.team.id}"
|
||||||
else
|
else
|
||||||
assigns.user.id
|
"ee:#{ee?()};user:#{assigns.user.id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
assigns =
|
assigns =
|
||||||
|
|
|
||||||
|
|
@ -131,10 +131,72 @@ defmodule Plausible.BillingTest do
|
||||||
}
|
}
|
||||||
|
|
||||||
describe "subscription_created" do
|
describe "subscription_created" do
|
||||||
test "creates a subscription" do
|
test "fails on callback without passthrough" do
|
||||||
user = new_user()
|
_user = new_user()
|
||||||
|
|
||||||
%{@subscription_created_params | "passthrough" => user.id}
|
assert_raise RuntimeError, ~r/Missing passthrough/, fn ->
|
||||||
|
@subscription_created_params
|
||||||
|
|> Map.delete("passthrough")
|
||||||
|
|> Billing.subscription_created()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails on callback without valid passthrough" do
|
||||||
|
_user = new_user()
|
||||||
|
|
||||||
|
assert_raise RuntimeError, ~r/Invalid passthrough sent via Paddle/, fn ->
|
||||||
|
%{@subscription_created_params | "passthrough" => "invalid"}
|
||||||
|
|> Billing.subscription_created()
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raise RuntimeError, ~r/Invalid passthrough sent via Paddle/, fn ->
|
||||||
|
%{@subscription_created_params | "passthrough" => "ee:true;user:invalid"}
|
||||||
|
|> Billing.subscription_created()
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raise RuntimeError, ~r/Invalid passthrough sent via Paddle/, fn ->
|
||||||
|
%{@subscription_created_params | "passthrough" => "ee:true;user:123;team:invalid"}
|
||||||
|
|> Billing.subscription_created()
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raise RuntimeError, ~r/Invalid passthrough sent via Paddle/, fn ->
|
||||||
|
%{
|
||||||
|
@subscription_created_params
|
||||||
|
| "passthrough" => "ee:true;user:123;team:456;some:invalid"
|
||||||
|
}
|
||||||
|
|> Billing.subscription_created()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails on callback with non-existent user" do
|
||||||
|
user = new_user()
|
||||||
|
Repo.delete!(user)
|
||||||
|
|
||||||
|
assert_raise Ecto.NoResultsError, fn ->
|
||||||
|
%{@subscription_created_params | "passthrough" => "ee:true;user:#{user.id}"}
|
||||||
|
|> Billing.subscription_created()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails on callback with non-existent team" do
|
||||||
|
user = new_user()
|
||||||
|
{:ok, team} = Plausible.Teams.get_or_create(user)
|
||||||
|
Repo.delete!(team)
|
||||||
|
|
||||||
|
assert_raise Ecto.NoResultsError, fn ->
|
||||||
|
%{
|
||||||
|
@subscription_created_params
|
||||||
|
| "passthrough" => "ee:true;user:#{user.id};team:#{team.id}"
|
||||||
|
}
|
||||||
|
|> Billing.subscription_created()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "creates a subscription with teams passthrough" do
|
||||||
|
user = new_user()
|
||||||
|
{:ok, team} = Plausible.Teams.get_or_create(user)
|
||||||
|
|
||||||
|
%{@subscription_created_params | "passthrough" => "ee:true;user:#{user.id};team:#{team.id}"}
|
||||||
|> Billing.subscription_created()
|
|> Billing.subscription_created()
|
||||||
|
|
||||||
subscription =
|
subscription =
|
||||||
|
|
@ -147,8 +209,23 @@ defmodule Plausible.BillingTest do
|
||||||
assert subscription.currency_code == "EUR"
|
assert subscription.currency_code == "EUR"
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :teams
|
test "supports user without a team case" do
|
||||||
test "creates a subscription with teams passthrough" do
|
user = new_user()
|
||||||
|
|
||||||
|
%{@subscription_created_params | "passthrough" => "ee:true;user:#{user.id}"}
|
||||||
|
|> Billing.subscription_created()
|
||||||
|
|
||||||
|
subscription =
|
||||||
|
user |> team_of() |> Plausible.Teams.with_subscription() |> Map.fetch!(:subscription)
|
||||||
|
|
||||||
|
assert subscription.paddle_subscription_id == @subscription_id
|
||||||
|
assert subscription.next_bill_date == ~D[2019-06-01]
|
||||||
|
assert subscription.last_bill_date == ~D[2019-05-01]
|
||||||
|
assert subscription.next_bill_amount == "6.00"
|
||||||
|
assert subscription.currency_code == "EUR"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "supports old format without prefix" do
|
||||||
user = new_user()
|
user = new_user()
|
||||||
{:ok, team} = Plausible.Teams.get_or_create(user)
|
{:ok, team} = Plausible.Teams.get_or_create(user)
|
||||||
|
|
||||||
|
|
@ -158,25 +235,21 @@ defmodule Plausible.BillingTest do
|
||||||
assert user |> team_of() |> Plausible.Teams.with_subscription() |> Map.fetch!(:subscription)
|
assert user |> team_of() |> Plausible.Teams.with_subscription() |> Map.fetch!(:subscription)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "create with email address" do
|
test "supports old format without prefix for user without a team" do
|
||||||
user = new_user()
|
user = new_user()
|
||||||
|
|
||||||
%{@subscription_created_params | "email" => user.email}
|
%{@subscription_created_params | "passthrough" => user.id}
|
||||||
|> Billing.subscription_created()
|
|> Billing.subscription_created()
|
||||||
|
|
||||||
subscription = subscription_of(user)
|
assert user |> team_of() |> Plausible.Teams.with_subscription() |> Map.fetch!(:subscription)
|
||||||
|
|
||||||
assert subscription.paddle_subscription_id == @subscription_id
|
|
||||||
assert subscription.next_bill_date == ~D[2019-06-01]
|
|
||||||
assert subscription.last_bill_date == ~D[2019-05-01]
|
|
||||||
assert subscription.next_bill_amount == "6.00"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "unlocks sites if user has any locked sites" do
|
test "unlocks sites if user has any locked sites" do
|
||||||
user = new_user()
|
user = new_user()
|
||||||
site = new_site(owner: user, locked: true)
|
site = new_site(owner: user, locked: true)
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
%{@subscription_created_params | "passthrough" => user.id}
|
%{@subscription_created_params | "passthrough" => "ee:true;user:#{user.id};team:#{team.id}"}
|
||||||
|> Billing.subscription_created()
|
|> Billing.subscription_created()
|
||||||
|
|
||||||
refute Repo.reload!(site).locked
|
refute Repo.reload!(site).locked
|
||||||
|
|
@ -185,8 +258,10 @@ defmodule Plausible.BillingTest do
|
||||||
@tag :ee_only
|
@tag :ee_only
|
||||||
test "updates accept_traffic_until" do
|
test "updates accept_traffic_until" do
|
||||||
user = new_user()
|
user = new_user()
|
||||||
|
new_site(owner: user)
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
%{@subscription_created_params | "passthrough" => user.id}
|
%{@subscription_created_params | "passthrough" => "ee:true;user:#{user.id};team:#{team.id}"}
|
||||||
|> Billing.subscription_created()
|
|> Billing.subscription_created()
|
||||||
|
|
||||||
next_bill = Date.from_iso8601!(@subscription_created_params["next_bill_date"])
|
next_bill = Date.from_iso8601!(@subscription_created_params["next_bill_date"])
|
||||||
|
|
@ -197,8 +272,9 @@ defmodule Plausible.BillingTest do
|
||||||
|
|
||||||
test "sets user.allow_next_upgrade_override field to false" do
|
test "sets user.allow_next_upgrade_override field to false" do
|
||||||
user = new_user(team: [allow_next_upgrade_override: true])
|
user = new_user(team: [allow_next_upgrade_override: true])
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
%{@subscription_created_params | "passthrough" => user.id}
|
%{@subscription_created_params | "passthrough" => "ee:true;user:#{user.id};team:#{team.id}"}
|
||||||
|> Billing.subscription_created()
|
|> Billing.subscription_created()
|
||||||
|
|
||||||
refute Repo.reload!(team_of(user)).allow_next_upgrade_override
|
refute Repo.reload!(team_of(user)).allow_next_upgrade_override
|
||||||
|
|
@ -212,9 +288,11 @@ defmodule Plausible.BillingTest do
|
||||||
paddle_plan_id: @plan_id_10k
|
paddle_plan_id: @plan_id_10k
|
||||||
)
|
)
|
||||||
|
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
api_key = insert(:api_key, user: user, hourly_request_limit: 1)
|
api_key = insert(:api_key, user: user, hourly_request_limit: 1)
|
||||||
|
|
||||||
%{@subscription_created_params | "passthrough" => user.id}
|
%{@subscription_created_params | "passthrough" => "ee:true;user:#{user.id};team:#{team.id}"}
|
||||||
|> Billing.subscription_created()
|
|> Billing.subscription_created()
|
||||||
|
|
||||||
assert Repo.reload!(api_key).hourly_request_limit == 10_000
|
assert Repo.reload!(api_key).hourly_request_limit == 10_000
|
||||||
|
|
@ -225,11 +303,12 @@ defmodule Plausible.BillingTest do
|
||||||
test "updates an existing subscription" do
|
test "updates an existing subscription" do
|
||||||
user = new_user()
|
user = new_user()
|
||||||
subscribe_to_growth_plan(user)
|
subscribe_to_growth_plan(user)
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
@subscription_updated_params
|
@subscription_updated_params
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
||||||
"passthrough" => user.id
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}"
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
||||||
|
|
@ -250,7 +329,7 @@ defmodule Plausible.BillingTest do
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"next_bill_date" => "2021-01-01",
|
"next_bill_date" => "2021-01-01",
|
||||||
"subscription_id" => subscription_id,
|
"subscription_id" => subscription_id,
|
||||||
"passthrough" => "user:#{user.id};team:#{team.id}"
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}"
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
||||||
|
|
@ -263,11 +342,12 @@ defmodule Plausible.BillingTest do
|
||||||
test "status update from 'paused' to 'past_due' is ignored" do
|
test "status update from 'paused' to 'past_due' is ignored" do
|
||||||
user = new_user()
|
user = new_user()
|
||||||
subscribe_to_growth_plan(user, status: Subscription.Status.paused())
|
subscribe_to_growth_plan(user, status: Subscription.Status.paused())
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
%{@subscription_updated_params | "old_status" => "paused", "status" => "past_due"}
|
%{@subscription_updated_params | "old_status" => "paused", "status" => "past_due"}
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
||||||
"passthrough" => user.id
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}"
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
||||||
|
|
@ -278,11 +358,12 @@ defmodule Plausible.BillingTest do
|
||||||
user = new_user()
|
user = new_user()
|
||||||
subscribe_to_growth_plan(user, status: Subscription.Status.past_due())
|
subscribe_to_growth_plan(user, status: Subscription.Status.past_due())
|
||||||
site = new_site(locked: true, owner: user)
|
site = new_site(locked: true, owner: user)
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
@subscription_updated_params
|
@subscription_updated_params
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
||||||
"passthrough" => user.id,
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}",
|
||||||
"old_status" => "past_due"
|
"old_status" => "past_due"
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
@ -293,11 +374,12 @@ defmodule Plausible.BillingTest do
|
||||||
@tag :ee_only
|
@tag :ee_only
|
||||||
test "updates accept_traffic_until" do
|
test "updates accept_traffic_until" do
|
||||||
user = new_user() |> subscribe_to_growth_plan()
|
user = new_user() |> subscribe_to_growth_plan()
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
@subscription_updated_params
|
@subscription_updated_params
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
||||||
"passthrough" => user.id
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}"
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
||||||
|
|
@ -310,6 +392,7 @@ defmodule Plausible.BillingTest do
|
||||||
test "sets user.allow_next_upgrade_override field to false" do
|
test "sets user.allow_next_upgrade_override field to false" do
|
||||||
user = new_user(team: [allow_next_upgrade_override: true])
|
user = new_user(team: [allow_next_upgrade_override: true])
|
||||||
subscribe_to_growth_plan(user)
|
subscribe_to_growth_plan(user)
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
assert Repo.reload!(team_of(user)).allow_next_upgrade_override
|
assert Repo.reload!(team_of(user)).allow_next_upgrade_override
|
||||||
|
|
||||||
|
|
@ -318,7 +401,7 @@ defmodule Plausible.BillingTest do
|
||||||
@subscription_updated_params
|
@subscription_updated_params
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"subscription_id" => subscription_id,
|
"subscription_id" => subscription_id,
|
||||||
"passthrough" => user.id
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}"
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
||||||
|
|
@ -333,12 +416,14 @@ defmodule Plausible.BillingTest do
|
||||||
hourly_api_request_limit: 10_000
|
hourly_api_request_limit: 10_000
|
||||||
)
|
)
|
||||||
|
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
api_key = insert(:api_key, user: user, hourly_request_limit: 1)
|
api_key = insert(:api_key, user: user, hourly_request_limit: 1)
|
||||||
|
|
||||||
@subscription_updated_params
|
@subscription_updated_params
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
"subscription_id" => subscription_of(user).paddle_subscription_id,
|
||||||
"passthrough" => user.id,
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}",
|
||||||
"subscription_plan_id" => "new-plan-id"
|
"subscription_plan_id" => "new-plan-id"
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
@ -352,6 +437,8 @@ defmodule Plausible.BillingTest do
|
||||||
|
|
||||||
subscribe_to_growth_plan(user)
|
subscribe_to_growth_plan(user)
|
||||||
|
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
site = new_site(locked: true, owner: user)
|
site = new_site(locked: true, owner: user)
|
||||||
|
|
||||||
subscription_id = subscription_of(user).paddle_subscription_id
|
subscription_id = subscription_of(user).paddle_subscription_id
|
||||||
|
|
@ -359,7 +446,7 @@ defmodule Plausible.BillingTest do
|
||||||
@subscription_updated_params
|
@subscription_updated_params
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"subscription_id" => subscription_id,
|
"subscription_id" => subscription_id,
|
||||||
"passthrough" => user.id,
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}",
|
||||||
"subscription_plan_id" => @plan_id_100k
|
"subscription_plan_id" => @plan_id_100k
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
@ -370,12 +457,14 @@ defmodule Plausible.BillingTest do
|
||||||
|
|
||||||
test "ignores if subscription cannot be found" do
|
test "ignores if subscription cannot be found" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
_site = new_site(owner: user)
|
||||||
|
team = team_of(user)
|
||||||
|
|
||||||
res =
|
res =
|
||||||
@subscription_updated_params
|
@subscription_updated_params
|
||||||
|> Map.merge(%{
|
|> Map.merge(%{
|
||||||
"subscription_id" => "666",
|
"subscription_id" => "666",
|
||||||
"passthrough" => user.id
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}"
|
||||||
})
|
})
|
||||||
|> Billing.subscription_updated()
|
|> Billing.subscription_updated()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ defmodule PlausibleWeb.Api.PaddleControllerTest do
|
||||||
describe "webhook verification" do
|
describe "webhook verification" do
|
||||||
test "is verified when signature is correct", %{conn: conn} do
|
test "is verified when signature is correct", %{conn: conn} do
|
||||||
insert(:user, id: 235)
|
insert(:user, id: 235)
|
||||||
conn = post(conn, Routes.paddle_path(conn, :webhook), @webhook_body)
|
|
||||||
|
|
||||||
|
conn = post(conn, Routes.paddle_path(conn, :webhook), @webhook_body)
|
||||||
assert conn.status == 200
|
assert conn.status == 200
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ defmodule PlausibleWeb.BillingControllerTest do
|
||||||
assert %{
|
assert %{
|
||||||
"disableLogout" => true,
|
"disableLogout" => true,
|
||||||
"email" => user.email,
|
"email" => user.email,
|
||||||
"passthrough" => "user:#{user.id};team:#{team.id}",
|
"passthrough" => "ee:#{Plausible.ee?()};user:#{user.id};team:#{team.id}",
|
||||||
"product" => @configured_enterprise_plan_paddle_plan_id,
|
"product" => @configured_enterprise_plan_paddle_plan_id,
|
||||||
"success" => Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success),
|
"success" => Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success),
|
||||||
"theme" => "none"
|
"theme" => "none"
|
||||||
|
|
@ -337,7 +337,7 @@ defmodule PlausibleWeb.BillingControllerTest do
|
||||||
assert %{
|
assert %{
|
||||||
"disableLogout" => true,
|
"disableLogout" => true,
|
||||||
"email" => user.email,
|
"email" => user.email,
|
||||||
"passthrough" => "user:#{user.id};team:#{team.id}",
|
"passthrough" => "ee:#{Plausible.ee?()};user:#{user.id};team:#{team.id}",
|
||||||
"product" => @configured_enterprise_plan_paddle_plan_id,
|
"product" => @configured_enterprise_plan_paddle_plan_id,
|
||||||
"success" => Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success),
|
"success" => Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success),
|
||||||
"theme" => "none"
|
"theme" => "none"
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,9 @@ defmodule PlausibleWeb.SettingsControllerTest do
|
||||||
# for a free_10k subscription (without a `last_bill_date`)
|
# for a free_10k subscription (without a `last_bill_date`)
|
||||||
Repo.delete!(subscription)
|
Repo.delete!(subscription)
|
||||||
|
|
||||||
Plausible.Billing.Subscription.free(%{team_id: team_of(user).id})
|
user
|
||||||
|
|> team_of()
|
||||||
|
|> Plausible.Billing.Subscription.free()
|
||||||
|> Repo.insert!()
|
|> Repo.insert!()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|
|
@ -533,7 +535,9 @@ defmodule PlausibleWeb.SettingsControllerTest do
|
||||||
test "does not show invoice section for a free subscription", %{conn: conn, user: user} do
|
test "does not show invoice section for a free subscription", %{conn: conn, user: user} do
|
||||||
new_site(owner: user)
|
new_site(owner: user)
|
||||||
|
|
||||||
Plausible.Billing.Subscription.free(%{team_id: team_of(user).id, currency_code: "EUR"})
|
user
|
||||||
|
|> team_of()
|
||||||
|
|> Plausible.Billing.Subscription.free(%{currency_code: "EUR"})
|
||||||
|> Repo.insert!()
|
|> Repo.insert!()
|
||||||
|
|
||||||
html =
|
html =
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
|
||||||
assert %{
|
assert %{
|
||||||
"disableLogout" => true,
|
"disableLogout" => true,
|
||||||
"email" => user.email,
|
"email" => user.email,
|
||||||
"passthrough" => "user:#{user.id};team:#{team.id}",
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}",
|
||||||
"product" => @v4_growth_200k_yearly_plan_id,
|
"product" => @v4_growth_200k_yearly_plan_id,
|
||||||
"success" => Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success),
|
"success" => Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success),
|
||||||
"theme" => "none"
|
"theme" => "none"
|
||||||
|
|
@ -1034,7 +1034,7 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
|
||||||
assert %{
|
assert %{
|
||||||
"disableLogout" => true,
|
"disableLogout" => true,
|
||||||
"email" => user.email,
|
"email" => user.email,
|
||||||
"passthrough" => "user:#{user.id};team:#{team.id}",
|
"passthrough" => "ee:true;user:#{user.id};team:#{team.id}",
|
||||||
"product" => @v4_growth_200k_yearly_plan_id,
|
"product" => @v4_growth_200k_yearly_plan_id,
|
||||||
"success" => Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success),
|
"success" => Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success),
|
||||||
"theme" => "none"
|
"theme" => "none"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue