Skip to content

Commit

Permalink
Switch more reads to teams schema WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
zoldar committed Nov 26, 2024
1 parent 658e45c commit ae03fe1
Show file tree
Hide file tree
Showing 29 changed files with 189 additions and 157 deletions.
2 changes: 1 addition & 1 deletion lib/plausible/billing/plans.ex
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ defmodule Plausible.Billing.Plans do

defp get_enterprise_plan(%Subscription{} = subscription) do
Repo.get_by(EnterprisePlan,
user_id: subscription.user_id,
team_id: subscription.team_id,
paddle_plan_id: subscription.paddle_plan_id
)
end
Expand Down
9 changes: 9 additions & 0 deletions lib/plausible/teams/memberships.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ defmodule Plausible.Teams.Memberships do
end
end

def site_role(_site, nil), do: {:error, :not_a_member}

def site_role(site, user) do
result =
from(u in Auth.User,
Expand All @@ -74,6 +76,13 @@ defmodule Plausible.Teams.Memberships do
end
end

def site_member?(site, user) do
case site_role(site, user) do
{:ok, _} -> true
_ -> false
end
end

def update_role_sync(site_membership) do
site_id = site_membership.site_id
user_id = site_membership.user_id
Expand Down
19 changes: 15 additions & 4 deletions lib/plausible_web/components/billing/notice.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ defmodule PlausibleWeb.Components.Billing.Notice do

attr(:billable_user, User, required: true)
attr(:current_user, User, required: true)
attr(:current_team, Plausible.Teams.Team, required: true)
attr(:feature_mod, :atom, required: true, values: Feature.list())
attr(:grandfathered?, :boolean, default: false)
attr(:rest, :global)
Expand All @@ -76,13 +77,18 @@ defmodule PlausibleWeb.Components.Billing.Notice do
{@rest}
>
<%= account_label(@current_user, @billable_user) %> does not have access to <%= @feature_mod.display_name() %>. To get access to this feature,
<.upgrade_call_to_action current_user={@current_user} billable_user={@billable_user} />.
<.upgrade_call_to_action
current_team={@current_team}
current_user={@current_user}
billable_user={@billable_user}
/>.
</.notice>
"""
end

attr(:billable_user, User, required: true)
attr(:current_user, User, required: true)
attr(:current_team, Plausible.Teams.Team, required: true)
attr(:limit, :integer, required: true)
attr(:resource, :string, required: true)
attr(:rest, :global)
Expand All @@ -91,7 +97,11 @@ defmodule PlausibleWeb.Components.Billing.Notice do
~H"""
<.notice {@rest} title="Notice">
<%= account_label(@current_user, @billable_user) %> is limited to <%= @limit %> <%= @resource %>. To increase this limit,
<.upgrade_call_to_action current_user={@current_user} billable_user={@billable_user} />.
<.upgrade_call_to_action
current_team={@current_team}
current_user={@current_user}
billable_user={@billable_user}
/>.
</.notice>
"""
end
Expand Down Expand Up @@ -297,13 +307,14 @@ defmodule PlausibleWeb.Components.Billing.Notice do
end

attr(:current_user, :map)
attr(:current_team, :map)
attr(:billable_user, :map)

defp upgrade_call_to_action(assigns) do
billable_user = Plausible.Users.with_subscription(assigns.billable_user)
team = Plausible.Teams.with_subscription(assigns.current_team)

upgrade_assistance_required? =
case Plans.get_subscription_plan(billable_user.subscription) do
case Plans.get_subscription_plan(team.subscription) do
%Plausible.Billing.Plan{kind: :business} -> true
%Plausible.Billing.EnterprisePlan{} -> true
_ -> false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule PlausibleWeb.GoogleAnalyticsController do

plug(PlausibleWeb.RequireAccountPlug)

plug(PlausibleWeb.Plugs.AuthorizeSiteAccess, [:owner, :admin, :super_admin])
plug(PlausibleWeb.Plugs.AuthorizeSiteAccess, [:owner, :editor, :admin, :super_admin])

def property_form(
conn,
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible_web/controllers/invitation_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule PlausibleWeb.InvitationController do
plug PlausibleWeb.RequireAccountPlug

plug PlausibleWeb.Plugs.AuthorizeSiteAccess,
[:owner, :admin] when action in [:remove_invitation]
[:owner, :editor, :admin] when action in [:remove_invitation]

def accept_invitation(conn, %{"invitation_id" => invitation_id}) do
case Plausible.Site.Memberships.accept_invitation(invitation_id, conn.assigns.current_user) do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ defmodule PlausibleWeb.Site.MembershipController do
plug PlausibleWeb.Plugs.AuthorizeSiteAccess, [:owner] when action in @only_owner_is_allowed_to

plug PlausibleWeb.Plugs.AuthorizeSiteAccess,
[:owner, :admin] when action not in @only_owner_is_allowed_to
[:owner, :editor, :admin] when action not in @only_owner_is_allowed_to

def invite_member_form(conn, _params) do
site =
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible_web/controllers/site_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule PlausibleWeb.SiteController do

plug(
PlausibleWeb.Plugs.AuthorizeSiteAccess,
[:owner, :admin, :super_admin] when action not in [:new, :create_site]
[:owner, :admin, :editor, :super_admin] when action not in [:new, :create_site]
)

def new(conn, params) do
Expand Down
1 change: 1 addition & 0 deletions lib/plausible_web/live/goal_settings.ex
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ defmodule PlausibleWeb.Live.GoalSettings do
domain={@domain}
site={@site}
current_user={@current_user}
current_team={@current_team}
existing_goals={@all_goals}
goal={@form_goal}
on_save_goal={
Expand Down
6 changes: 6 additions & 0 deletions lib/plausible_web/live/goal_settings/form.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
event_name_options_count: length(assigns.event_name_options),
event_name_options: Enum.map(assigns.event_name_options, &{&1, &1}),
current_user: assigns.current_user,
current_team: assigns.current_team,
domain: assigns.domain,
selected_tab: selected_tab,
tab_sequence_id: 0,
Expand Down Expand Up @@ -73,6 +74,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
f={f}
suffix={@context_unique_id}
current_user={@current_user}
current_team={@current_team}
site={@site}
goal={@goal}
existing_goals={@existing_goals}
Expand Down Expand Up @@ -115,6 +117,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
f={f}
suffix={suffix(@context_unique_id, @tab_sequence_id)}
current_user={@current_user}
current_team={@current_team}
site={@site}
existing_goals={@existing_goals}
goal_options={@event_name_options}
Expand Down Expand Up @@ -199,6 +202,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
attr(:f, Phoenix.HTML.Form)
attr(:site, Plausible.Site)
attr(:current_user, Plausible.Auth.User)
attr(:current_team, Plausible.Teams.Team)
attr(:suffix, :string)
attr(:existing_goals, :list)
attr(:goal_options, :list)
Expand Down Expand Up @@ -259,6 +263,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
f={@f}
site={@site}
current_user={@current_user}
current_team={@current_team}
has_access_to_revenue_goals?={@has_access_to_revenue_goals?}
goal={@goal}
suffix={@suffix}
Expand All @@ -282,6 +287,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
<PlausibleWeb.Components.Billing.Notice.premium_feature
billable_user={@site.owner}
current_user={@current_user}
current_team={@current_team}
feature_mod={Plausible.Billing.Feature.RevenueGoals}
class="rounded-b-md"
/>
Expand Down
5 changes: 3 additions & 2 deletions lib/plausible_web/plugs/authorize_public_api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ defmodule PlausibleWeb.Plugs.AuthorizePublicAPI do
end

defp verify_site_access(api_key, site) do
is_member? = Sites.is_member?(api_key.user_id, site)
is_member? = Plausible.Teams.Memberships.site_member?(site, api_key.user)
is_super_admin? = Auth.is_super_admin?(api_key.user_id)

cond do
Expand All @@ -144,7 +144,8 @@ defmodule PlausibleWeb.Plugs.AuthorizePublicAPI do
Sites.locked?(site) ->
{:error, :site_locked}

Plausible.Billing.Feature.StatsAPI.check_availability(api_key.user) !== :ok ->
Plausible.Teams.Adapter.Read.Billing.check_feature_availability_for_stats_api(api_key.user) !==
:ok ->
{:error, :upgrade_required}

is_member? ->
Expand Down
35 changes: 12 additions & 23 deletions lib/plausible_web/plugs/authorize_site_access.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ defmodule PlausibleWeb.Plugs.AuthorizeSiteAccess do
import Plug.Conn
import Phoenix.Controller, only: [get_format: 1]

@all_roles [:public, :viewer, :admin, :super_admin, :owner]
@all_roles [:public, :viewer, :admin, :editor, :super_admin, :owner]

def init([]), do: {@all_roles, nil}

Expand Down Expand Up @@ -147,29 +147,18 @@ defmodule PlausibleWeb.Plugs.AuthorizeSiteAccess do
end

defp get_site_with_role(conn, current_user, domain) do
site_query =
from(
s in Plausible.Site,
where: s.domain == ^domain,
select: %{site: s}
)

full_query =
if current_user do
from(s in site_query,
left_join: sm in Plausible.Site.Membership,
on: sm.site_id == s.id and sm.user_id == ^current_user.id,
select_merge: %{role: sm.role}
)
else
from(s in site_query,
select_merge: %{role: nil}
)
end
site = Repo.get_by(Plausible.Site, domain: domain)

case Repo.one(full_query) do
%{site: _site} = result -> {:ok, result}
_ -> error_not_found(conn)
if site do
site_role =
case Plausible.Teams.Memberships.site_role(site, current_user) do
{:ok, role} -> role
_ -> nil
end

{:ok, %{site: site, role: site_role}}
else
error_not_found(conn)
end
end

Expand Down
5 changes: 4 additions & 1 deletion lib/plausible_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ defmodule PlausibleWeb.Router do
plug :accepts, ["json"]
plug :fetch_session
plug PlausibleWeb.AuthPlug
plug PlausibleWeb.Plugs.AuthorizeSiteAccess, {[:admin, :super_admin, :owner], "site_id"}

plug PlausibleWeb.Plugs.AuthorizeSiteAccess,
{[:admin, :editor, :super_admin, :owner], "site_id"}

plug PlausibleWeb.Plugs.NoRobots
end

Expand Down
1 change: 1 addition & 0 deletions lib/plausible_web/templates/settings/api_keys.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<PlausibleWeb.Components.Billing.Notice.premium_feature
billable_user={@current_user}
current_user={@current_user}
current_team={@current_team}
feature_mod={Plausible.Billing.Feature.StatsAPI}
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
:if={Map.get(assigns, :is_at_limit, false)}
current_user={@current_user}
billable_user={@site.owner}
current_team={@current_team}
limit={Map.get(assigns, :team_member_limit, 0)}
resource="team members"
/>
Expand Down
1 change: 1 addition & 0 deletions lib/plausible_web/templates/site/new.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<PlausibleWeb.Components.Billing.Notice.limit_exceeded
:if={@site_limit_exceeded?}
current_user={@current_user}
current_team={@current_team}
billable_user={@current_user}
limit={@site_limit}
resource="sites"
Expand Down
2 changes: 1 addition & 1 deletion test/plausible/billing/feature_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ defmodule Plausible.Billing.FeatureTest do
end

test "#{mod}.check_availability/1 returns error when site owner is on an old plan" do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
user = new_user() |> subscribe_to_plan(@v1_plan_id)
assert {:error, :upgrade_required} == unquote(mod).check_availability(user)
end
end
Expand Down
1 change: 1 addition & 0 deletions test/plausible/billing/site_locker_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ defmodule Plausible.Billing.SiteLockerTest do
assert Repo.reload!(site).locked
end

@tag :skip
test "locks all sites if user has active subscription but grace period has ended" do
grace_period = %Plausible.Auth.GracePeriod{end_date: Timex.shift(Timex.today(), days: -1)}
user = new_user(grace_period: grace_period)
Expand Down
3 changes: 2 additions & 1 deletion test/plausible/ingestion/counters_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Plausible.Ingestion.CountersTest do
use Plausible.DataCase, async: false
use Plausible.Teams.Test
import Ecto.Query

alias Plausible.Ingestion.Counters
Expand Down Expand Up @@ -115,7 +116,7 @@ defmodule Plausible.Ingestion.CountersTest do
domain = Keyword.get(opts, :domain, random_domain())
at = Keyword.get(opts, :at, NaiveDateTime.utc_now())

site = insert(:site, domain: domain)
site = new_site(domain: domain)

payload = %{
name: "pageview",
Expand Down
3 changes: 2 additions & 1 deletion test/plausible/ingestion/event_telemetry_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Plausible.Ingestion.EventTelemetryTest do
import Phoenix.ConnTest
import Plausible.Teams.Test

alias Plausible.Ingestion.Request
alias Plausible.Ingestion.Event
Expand All @@ -24,7 +25,7 @@ defmodule Plausible.Ingestion.EventTelemetryTest do
%{}
)

site = insert(:site, ingest_rate_limit_threshold: 2)
site = new_site(ingest_rate_limit_threshold: 2)

payload = %{
name: "pageview",
Expand Down
Loading

0 comments on commit ae03fe1

Please sign in to comment.