Skip to content

Commit

Permalink
[WIP] Switch ownership transfer operations to read from team schemas …
Browse files Browse the repository at this point in the history
…behind FF
  • Loading branch information
zoldar committed Nov 21, 2024
1 parent 5cc3e6b commit cb27bf5
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 326 deletions.
11 changes: 9 additions & 2 deletions lib/plausible/site/admin.ex
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,16 @@ defmodule Plausible.SiteAdmin do
{:error, "Please select at least one site from the list"}
end

defp transfer_ownership_direct(_conn, sites, %{"email" => email}) do
defp transfer_ownership_direct(conn, sites, %{"email" => email}) do
inviter = conn.assigns.current_user

with {:ok, new_owner} <- Plausible.Auth.get_user_by(email: email),
{:ok, _} <- Plausible.Site.Memberships.bulk_transfer_ownership_direct(sites, new_owner) do
{:ok, _} <-
Plausible.Site.Memberships.bulk_transfer_ownership_direct(
inviter,
sites,
new_owner
) do
:ok
else
{:error, :user_not_found} ->
Expand Down
4 changes: 2 additions & 2 deletions lib/plausible/site/memberships.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ defmodule Plausible.Site.Memberships do
alias Plausible.Repo
alias Plausible.Site.Memberships

defdelegate transfer_ownership(site, user), to: Memberships.AcceptInvitation
defdelegate accept_invitation(invitation_id, user), to: Memberships.AcceptInvitation
defdelegate reject_invitation(invitation_id, user), to: Memberships.RejectInvitation
defdelegate remove_invitation(invitation_id, site), to: Memberships.RemoveInvitation
Expand All @@ -20,7 +19,8 @@ defmodule Plausible.Site.Memberships do
defdelegate bulk_create_invitation(sites, inviter, invitee_email, role, opts),
to: Memberships.CreateInvitation

defdelegate bulk_transfer_ownership_direct(sites, new_owner), to: Memberships.AcceptInvitation
defdelegate bulk_transfer_ownership_direct(inviter, sites, new_owner),
to: Memberships.AcceptInvitation

@spec any?(Auth.User.t()) :: boolean()
def any?(user) do
Expand Down
44 changes: 23 additions & 21 deletions lib/plausible/site/memberships/accept_invitation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ defmodule Plausible.Site.Memberships.AcceptInvitation do
| Ecto.Changeset.t()
| :no_plan

@spec bulk_transfer_ownership_direct([Site.t()], User.t()) ::
@spec bulk_transfer_ownership_direct(Auth.User.t(), [Site.t()], Auth.User.t()) ::
{:ok, [Membership.t()]} | {:error, transfer_error()}
def bulk_transfer_ownership_direct(sites, new_owner) do
def bulk_transfer_ownership_direct(inviter, sites, new_owner) do
Repo.transaction(fn ->
for site <- sites do
site = Repo.preload(site, :owner)

case transfer_ownership(site, new_owner) do
case transfer_ownership(inviter, site, new_owner) do
{:ok, membership} ->
membership

Expand All @@ -53,12 +51,28 @@ defmodule Plausible.Site.Memberships.AcceptInvitation do
end)
end

@spec transfer_ownership(Site.t(), Auth.User.t()) ::
{:ok, Site.Membership.t()} | {:error, transfer_error()}
def transfer_ownership(site, user) do
@spec accept_invitation(String.t(), Auth.User.t()) ::
{:ok, Site.Membership.t()} | {:error, accept_error()}
def accept_invitation(invitation_id, user) do
with {:ok, invitation} <- Invitations.find_for_user(invitation_id, user) do
if invitation.role == :owner do
do_accept_ownership_transfer(invitation, user)
else
do_accept_invitation(invitation, user)
end
end
end

defp transfer_ownership(inviter, site, user) do
site = Repo.preload(site, :owner)

with :ok <- Invitations.ensure_transfer_valid(site, user, :owner),
with :ok <-
Plausible.Teams.Adapter.Read.Invitations.ensure_transfer_valid(
inviter,
site,
user,
:owner
),
:ok <- Invitations.ensure_can_take_ownership(site, user) do
membership = get_or_create_owner_membership(site, user)

Expand All @@ -78,18 +92,6 @@ defmodule Plausible.Site.Memberships.AcceptInvitation do
end
end

@spec accept_invitation(String.t(), Auth.User.t()) ::
{:ok, Site.Membership.t()} | {:error, accept_error()}
def accept_invitation(invitation_id, user) do
with {:ok, invitation} <- Invitations.find_for_user(invitation_id, user) do
if invitation.role == :owner do
do_accept_ownership_transfer(invitation, user)
else
do_accept_invitation(invitation, user)
end
end
end

defp do_accept_ownership_transfer(invitation, user) do
membership = get_or_create_membership(invitation, user)
site = Repo.preload(invitation.site, :owner)
Expand Down
2 changes: 0 additions & 2 deletions lib/plausible/teams/invitations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,6 @@ defmodule Plausible.Teams.Invitations do
)
end

# TODO: Update site lock status with SiteLocker

:ok
end

Expand Down
35 changes: 13 additions & 22 deletions test/plausible/site/admin_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,15 @@ defmodule Plausible.Site.AdminTest do
end

test "new owner must be an existing user", %{conn: conn, transfer_direct_action: action} do
site = insert(:site)
site = new_site()

assert action.(conn, [site], %{"email" => "random@email.com"}) ==
{:error, "User could not be found"}
end

test "new owner can't be the same as old owner", %{conn: conn, transfer_direct_action: action} do
current_owner = insert(:user)

site = insert(:site, members: [current_owner])
current_owner = new_user()
site = new_site(owner: current_owner)

assert {:error, "User is already an owner of one of the sites"} =
action.(conn, [site], %{"email" => current_owner.email})
Expand All @@ -96,20 +95,16 @@ defmodule Plausible.Site.AdminTest do
transfer_direct_action: action
} do
today = Date.utc_today()
current_owner = insert(:user)
current_owner = new_user()

new_owner =
insert(:user,
subscription:
build(:growth_subscription,
last_bill_date: Timex.shift(today, days: -5)
)
)
new_user()
|> subscribe_to_growth_plan(last_bill_date: Date.shift(today, day: -5))

# fills the site limit quota
insert_list(10, :site, members: [new_owner])
for _ <- 1..10, do: new_site(owner: new_owner)

site = insert(:site, members: [current_owner])
site = new_site(owner: current_owner)

assert {:error, "Plan limits exceeded" <> _} =
action.(conn, [site], %{"email" => new_owner.email})
Expand All @@ -120,18 +115,14 @@ defmodule Plausible.Site.AdminTest do
transfer_direct_action: action
} do
today = Date.utc_today()
current_owner = insert(:user)
current_owner = new_user()

new_owner =
insert(:user,
subscription: build(:subscription, last_bill_date: Timex.shift(today, days: -5))
)

site1 =
insert(:site, memberships: [build(:site_membership, user: current_owner, role: :owner)])
new_user()
|> subscribe_to_growth_plan(last_bill_date: Date.shift(today, day: -5))

site2 =
insert(:site, memberships: [build(:site_membership, user: current_owner, role: :owner)])
site1 = new_site(owner: current_owner)
site2 = new_site(owner: current_owner)

assert :ok = action.(conn, [site1, site2], %{"email" => new_owner.email})
end
Expand Down
Loading

0 comments on commit cb27bf5

Please sign in to comment.