Skip to content

Commit

Permalink
Implement accepting team invite within the existing flow
Browse files Browse the repository at this point in the history
  • Loading branch information
zoldar committed Jan 8, 2025
1 parent a367afc commit 72ebe44
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 22 deletions.
13 changes: 12 additions & 1 deletion lib/plausible/site/memberships/accept_invitation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ defmodule Plausible.Site.Memberships.AcceptInvitation do

@type accept_error() ::
:invitation_not_found
| :already_other_team_member
| Billing.Quota.Limits.over_limits_error()
| Ecto.Changeset.t()
| :no_plan
Expand Down Expand Up @@ -111,6 +112,16 @@ defmodule Plausible.Site.Memberships.AcceptInvitation do
end

defp do_accept_team_invitation(team_invitation, user) do
Teams.Invitations.AcceptTeamInvite.accept(team_invitation, user)
with :ok <- ensure_no_team_membership(user) do
Teams.Invitations.accept_team_invitation(team_invitation, user)
end
end

defp ensure_no_team_membership(user) do
if Teams.Users.team_member?(user) do
{:error, :already_other_team_member}
else
:ok
end
end
end
36 changes: 27 additions & 9 deletions lib/plausible/teams/invitations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,14 @@ defmodule Plausible.Teams.Invitations do

now = NaiveDateTime.utc_now(:second)

with {:ok, team_membership} <-
do_accept(team_invitation, user, now, guest_invitations: [guest_invitation]) do
prune_guest_invitations(team_invitation.team)
{:ok, team_membership}
end
do_accept(team_invitation, user, now, guest_invitations: [guest_invitation])
end

def accept_team_invitation(team_invitation, user) do
team_invitation = Repo.preload(team_invitation, [:team, :inviter])
now = NaiveDateTime.utc_now(:second)

do_accept(team_invitation, user, now, guest_invitations: [])
end

@doc false
Expand Down Expand Up @@ -264,6 +267,10 @@ defmodule Plausible.Teams.Invitations do
Repo.delete_all(from gi in Teams.GuestInvitation, where: gi.id in ^guest_invitation_ids)
prune_guest_invitations(team_invitation.team)

# Prune guest memberships if any exist when team membership role
# is other than guest
maybe_prune_guest_memberships(team_membership)

if send_email? do
send_invitation_accepted_email(team_invitation, guest_invitations)
end
Expand All @@ -275,6 +282,16 @@ defmodule Plausible.Teams.Invitations do
end)
end

defp maybe_prune_guest_memberships(%Teams.Membership{role: :guest}), do: :ok

defp maybe_prune_guest_memberships(%Teams.Membership{} = team_membership) do
team_membership
|> Ecto.assoc(:guest_memberships)
|> Repo.delete_all()

:ok
end

defp transfer_site_ownership(site, team, now) do
site =
Repo.preload(site, [
Expand Down Expand Up @@ -643,14 +660,15 @@ defmodule Plausible.Teams.Invitations do
end)
end

defp send_invitation_accepted_email(_team_invitation, []) do
# NOOP for now
:ok
defp send_invitation_accepted_email(team_invitation, []) do
team_invitation.inviter.email
|> PlausibleWeb.Email.team_invitation_accepted(team_invitation.email, team_invitation.team)
|> Plausible.Mailer.send()
end

defp send_invitation_accepted_email(team_invitation, [guest_invitation | _]) do
team_invitation.inviter.email
|> PlausibleWeb.Email.invitation_accepted(team_invitation.email, guest_invitation.site)
|> PlausibleWeb.Email.guest_invitation_accepted(team_invitation.email, guest_invitation.site)
|> Plausible.Mailer.send()
end

Expand Down
9 changes: 0 additions & 9 deletions lib/plausible/teams/invitations/accept_team_invite.ex

This file was deleted.

10 changes: 10 additions & 0 deletions lib/plausible/teams/users.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ defmodule Plausible.Teams.Users do
alias Plausible.Repo
alias Plausible.Teams

def team_member?(user) do
Repo.exists?(
from(
tm in Teams.Membership,
where: tm.user_id == ^user.id,
where: tm.role != :guest
)
)
end

def has_sites?(user, opts \\ []) do
include_pending? = Keyword.get(opts, :include_pending?, false)

Expand Down
5 changes: 5 additions & 0 deletions lib/plausible_web/controllers/invitation_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ defmodule PlausibleWeb.InvitationController do
|> put_flash(:error, "Invitation missing or already accepted")
|> redirect(to: "/sites")

{:error, :already_other_team_member} ->
conn
|> put_flash(:error, "You already are a team member in another team")
|> redirect(to: "/sites")

{:error, :no_plan} ->
conn
|> put_flash(:error, "No existing subscription")
Expand Down
19 changes: 16 additions & 3 deletions lib/plausible_web/email.ex
Original file line number Diff line number Diff line change
Expand Up @@ -299,19 +299,32 @@ defmodule PlausibleWeb.Email do
)
end

def invitation_accepted(inviter_email, invitee_email, site) do
def guest_invitation_accepted(inviter_email, invitee_email, site) do
priority_email()
|> to(inviter_email)
|> tag("invitation-accepted")
|> tag("guest-invitation-accepted")
|> subject(
"[#{Plausible.product_name()}] #{invitee_email} accepted your invitation to #{site.domain}"
)
|> render("invitation_accepted.html",
|> render("guest_invitation_accepted.html",
invitee_email: invitee_email,
site: site
)
end

def team_invitation_accepted(inviter_email, invitee_email, team) do
priority_email()
|> to(inviter_email)
|> tag("team-invitation-accepted")
|> subject(
"[#{Plausible.product_name()}] #{invitee_email} accepted your invitation to \"#{team.name}\" team"
)
|> render("team_invitation_accepted.html",
invitee_email: invitee_email,
team: team
)
end

def guest_invitation_rejected(guest_invitation) do
priority_email()
|> to(guest_invitation.team_invitation.inviter.email)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<%= @invitee_email %> has accepted your invitation to "<%= @team.name %>" team.
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general, @site.domain)}>Click here</a> to view team settings.

0 comments on commit 72ebe44

Please sign in to comment.