analytics/lib/plausible_web/controllers/api/paddle_controller.ex
Adrian Gruntkowski 9d97dc1912
Move limit enforcement to accepting site ownership transfer (#3612)
* Move limit enforcement to accepting site ownerhsip transfer

* enforce pageview limit on ownership transfer accept

* Refactor plan limit check logic

* Extract `ensure_can_take_ownership` to `Invitations` context and refactor

* Improve styling of exceeded limits notice in invitation dialog and disable button

* styling improvements to notice

* make transfer_ownership return transfer to self error

* do not allow transferring to user without active subscription WIP

* Add missing typespec and improve existing ones

* Fix formatting

* Explicitly label direct match on function argument for clarity

* Slightly refactor `CreateInvitation.bulk_transfer_ownership_direct`

* Exclude quota enforcement tests from small build test suite

* Remove unused return type from `invite_error()` union type

* Do not block plan upgrade when there's pending ownership transfer

* Don't block and only warn about missing features on transfer

* Remove `x-init` attribute used for debugging

* Add tests for `Quota.monthly_pageview_usage/2`

* Test and improve site admin ownership transfer actions

* Extend tests for `AcceptInvitation.transfer_ownership`

* Test transfer ownership controller level accept action error cases

* Test choosing plan by user without sites but with a pending ownership transfer

* Test invitation x-data in sites LV

* Remove sitelocker trigger in invitation acceptance code and simplify logic

* Add Quota test for `user.allow_next_upgrade_override` being set

* ignore pageview limit only when subscribing to plan

* Use sandbox Paddle instance for staging

* Use sandbox paddle key for staging and dev

---------

Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
2023-12-20 14:56:49 +00:00

87 lines
2.4 KiB
Elixir

defmodule PlausibleWeb.Api.PaddleController do
use PlausibleWeb, :controller
use Plausible.Repo
require Logger
plug :verify_signature
def webhook(conn, %{"alert_name" => "subscription_created"} = params) do
Plausible.Billing.subscription_created(params)
|> webhook_response(conn, params)
end
def webhook(conn, %{"alert_name" => "subscription_updated"} = params) do
Plausible.Billing.subscription_updated(params)
|> webhook_response(conn, params)
end
def webhook(conn, %{"alert_name" => "subscription_cancelled"} = params) do
Plausible.Billing.subscription_cancelled(params)
|> webhook_response(conn, params)
end
def webhook(conn, %{"alert_name" => "subscription_payment_succeeded"} = params) do
Plausible.Billing.subscription_payment_succeeded(params)
|> webhook_response(conn, params)
end
def webhook(conn, _params) do
send_resp(conn, 404, "") |> halt
end
def verify_signature(conn, _opts) do
signature = Base.decode64!(conn.params["p_signature"])
msg =
Map.delete(conn.params, "p_signature")
|> Enum.map(fn {key, val} -> {key, "#{val}"} end)
|> List.keysort(0)
|> PhpSerializer.serialize()
[key_entry] = :public_key.pem_decode(get_paddle_key())
public_key = :public_key.pem_entry_decode(key_entry)
if :public_key.verify(msg, :sha, signature, public_key) do
conn
else
send_resp(conn, 400, "") |> halt
end
end
def verified_signature?(params) do
signature = Base.decode64!(params["p_signature"])
msg =
Map.delete(params, "p_signature")
|> Enum.map(fn {key, val} -> {key, "#{val}"} end)
|> List.keysort(0)
|> PhpSerializer.serialize()
[key_entry] = :public_key.pem_decode(get_paddle_key())
public_key = :public_key.pem_entry_decode(key_entry)
:public_key.verify(msg, :sha, signature, public_key)
end
@paddle_prod_key File.read!("priv/paddle.pem")
@paddle_sandbox_key File.read!("priv/paddle_sandbox.pem")
defp get_paddle_key() do
if Application.get_env(:plausible, :environment) in ["dev", "staging"] do
@paddle_sandbox_key
else
@paddle_prod_key
end
end
defp webhook_response({:ok, _}, conn, _params) do
json(conn, "")
end
defp webhook_response({:error, details}, conn, _params) do
Logger.error("Error processing Paddle webhook: #{inspect(details)}")
conn |> send_resp(400, "") |> halt
end
end