Skip to content

Commit

Permalink
Dispatch feature access check from /sites to Teams-schema reads
Browse files Browse the repository at this point in the history
  • Loading branch information
aerosol committed Nov 6, 2024
1 parent 496ca7a commit d01df73
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 21 deletions.
10 changes: 9 additions & 1 deletion lib/plausible/billing/feature.ex
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ defmodule Plausible.Billing.Feature do
@doc """
Checks whether the site owner or the user plan includes the given feature.
"""
@callback check_availability(Plausible.Auth.User.t()) ::
@callback check_availability(Plausible.Auth.User.t() | Plausible.Teams.Team.t() | nil) ::
:ok | {:error, :upgrade_required} | {:error, :not_implemented}

@features [
Expand Down Expand Up @@ -137,6 +137,14 @@ defmodule Plausible.Billing.Feature do
end
end

def check_availability(team_or_nil) do
cond do
free?() -> :ok
__MODULE__ in Plausible.Teams.Billing.allowed_features_for(team_or_nil) -> :ok
true -> {:error, :upgrade_required}
end
end

@impl true
def toggle(%Plausible.Site{} = site, opts \\ []) do
if toggle_field(), do: do_toggle(site, opts), else: :ok
Expand Down
21 changes: 2 additions & 19 deletions lib/plausible/site/memberships/invitations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ defmodule Plausible.Site.Memberships.Invitations do
alias Plausible.Site
alias Plausible.Auth
alias Plausible.Repo
alias Plausible.Billing.Quota
alias Plausible.Billing.Feature

@type missing_features_error() :: {:missing_features, [Feature.t()]}
Expand Down Expand Up @@ -65,6 +64,8 @@ defmodule Plausible.Site.Memberships.Invitations do
end

on_ee do
alias Plausible.Billing.Quota

@spec ensure_can_take_ownership(Site.t(), Auth.User.t()) ::
:ok | {:error, Quota.Limits.over_limits_error() | :no_plan}
def ensure_can_take_ownership(site, new_owner) do
Expand All @@ -88,22 +89,4 @@ defmodule Plausible.Site.Memberships.Invitations do
:ok
end
end

@spec check_feature_access(Site.t(), Auth.User.t(), boolean()) ::
:ok | {:error, missing_features_error()}
def check_feature_access(_site, _new_owner, true = _selfhost?) do
:ok
end

def check_feature_access(site, new_owner, false = _selfhost?) do
missing_features =
Quota.Usage.features_usage(nil, [site.id])
|> Enum.filter(&(&1.check_availability(new_owner) != :ok))

if missing_features == [] do
:ok
else
{:error, {:missing_features, missing_features}}
end
end
end
18 changes: 18 additions & 0 deletions lib/plausible/teams.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ defmodule Plausible.Teams do

alias __MODULE__
alias Plausible.Repo
use Plausible

@spec on_trial?(Teams.Team.t()) :: boolean()
on_ee do
def on_trial?(%Teams.Team{trial_expiry_date: nil}), do: false

def on_trial?(team) do
team = with_subscription(team)
not Plausible.Billing.Subscriptions.active?(team.subscription) && trial_days_left(team) >= 0
end
else
def on_trial?(_), do: true
end

@spec trial_days_left(Teams.Team.t()) :: integer()
def trial_days_left(team) do
Date.diff(team.trial_expiry_date, Date.utc_today())
end

def read_team_schemas?(user) do
FunWithFlags.enabled?(:read_team_schemas, for: user)
Expand Down
29 changes: 29 additions & 0 deletions lib/plausible/teams/billing.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ defmodule Plausible.Teams.Billing do
alias Plausible.Repo
alias Plausible.Teams

alias Plausible.Billing.{Plan, Plans, EnterprisePlan, Feature}
alias Plausible.Billing.Feature.{Goals, Props, StatsAPI}

@team_member_limit_for_trials 3
@limit_sites_since ~D[2021-05-05]
@site_limit_for_trials 10
Expand Down Expand Up @@ -258,4 +261,30 @@ defmodule Plausible.Teams.Billing do
|> union(^team_memberships_q)
|> union(^team_invitations_q)
end

def allowed_features_for(nil) do
[Goals]
end

def allowed_features_for(team) do
team = Teams.with_subscription(team)

case Plans.get_subscription_plan(team.subscription) do
%EnterprisePlan{features: features} ->
features

%Plan{features: features} ->
features

:free_10k ->
[Goals, Props, StatsAPI]

nil ->
if Teams.on_trial?(team) do
Feature.list()
else
[Goals]
end
end
end
end
30 changes: 29 additions & 1 deletion lib/plausible_web/live/sites.ex
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,17 @@ defmodule PlausibleWeb.Live.Sites do
end

defp check_features(%{role: :owner, site: site} = invitation, user) do
case Invitations.check_feature_access(site, user, ce?()) do
user_or_team =
if Teams.read_team_schemas?(user) do
case Teams.get_by_owner(user) do
{:ok, team} -> team
{:error, _} -> nil
end
else
user
end

case check_feature_access(site, user_or_team) do
:ok ->
%{invitation: invitation}

Expand All @@ -755,6 +765,24 @@ defmodule PlausibleWeb.Live.Sites do
end
end

if ce?() do
defp check_feature_access(_site, _new_owner) do
:ok
end
else
defp check_feature_access(site, new_owner) do
missing_features =
Plausible.Billing.Quota.Usage.features_usage(nil, [site.id])
|> Enum.filter(&(&1.check_availability(new_owner) != :ok))

if missing_features == [] do
:ok
else
{:error, {:missing_features, missing_features}}
end
end
end

defp set_filter_text(socket, filter_text) do
uri = socket.assigns.uri

Expand Down

0 comments on commit d01df73

Please sign in to comment.