199 lines
4.6 KiB
Elixir
199 lines
4.6 KiB
Elixir
defmodule Plausible.Teams.Users do
|
|
@moduledoc """
|
|
Users API accounting for teams.
|
|
"""
|
|
|
|
import Ecto.Query
|
|
|
|
alias Plausible.Repo
|
|
alias Plausible.Teams
|
|
|
|
def owned_teams(user) do
|
|
Repo.all(teams_query(user, roles: :owner))
|
|
end
|
|
|
|
def teams(user, opts \\ []) do
|
|
user
|
|
|> teams_query(Keyword.merge([order_by: :name], opts))
|
|
|> Repo.all()
|
|
|> Repo.preload(:owners)
|
|
end
|
|
|
|
def teams_query(user, opts \\ []) do
|
|
order_by = Keyword.get(opts, :order_by, :name)
|
|
roles = Keyword.get(opts, :roles)
|
|
identifier = Keyword.get(opts, :identifier)
|
|
|
|
query =
|
|
from(
|
|
tm in Teams.Membership,
|
|
as: :team_membership,
|
|
inner_join: t in assoc(tm, :team),
|
|
as: :team,
|
|
where: tm.user_id == ^user.id,
|
|
where: tm.role != :guest,
|
|
select: t
|
|
)
|
|
|
|
query =
|
|
if roles do
|
|
where(query, [team_membership: tm], tm.role in ^List.wrap(roles))
|
|
else
|
|
query
|
|
end
|
|
|
|
query =
|
|
if identifier do
|
|
where(query, [team: team], team.identifier == ^identifier)
|
|
else
|
|
query
|
|
end
|
|
|
|
case order_by do
|
|
:name ->
|
|
order_by(query, [team: t], [t.name, t.id])
|
|
|
|
:id_desc ->
|
|
order_by(query, [team: t], desc: t.id)
|
|
|
|
_ ->
|
|
query
|
|
end
|
|
end
|
|
|
|
def team_member?(user, opts \\ []) do
|
|
excluded_team_ids = Keyword.get(opts, :except, [])
|
|
only_setup? = Keyword.get(opts, :only_setup?, false)
|
|
|
|
query =
|
|
from(
|
|
tm in Teams.Membership,
|
|
where: tm.user_id == ^user.id,
|
|
where: tm.role != :guest,
|
|
where: tm.team_id not in ^excluded_team_ids
|
|
)
|
|
|
|
query =
|
|
if only_setup? do
|
|
query
|
|
|> join(:inner, [tm], t in assoc(tm, :team), as: :team)
|
|
|> where([team: t], t.setup_complete == true)
|
|
else
|
|
query
|
|
end
|
|
|
|
Repo.exists?(query)
|
|
end
|
|
|
|
def has_sites?(user, opts \\ []) do
|
|
include_pending? = Keyword.get(opts, :include_pending?, false)
|
|
|
|
sites_query =
|
|
from(
|
|
s in Plausible.Site,
|
|
where: s.team_id == parent_as(:site_parent).team_id,
|
|
select: 1
|
|
)
|
|
|
|
# NOTE: Provided guest team memberships are consistently pruned,
|
|
# mere presence of guest team membership means there are sites
|
|
# associated with it, so querying for team membership alone
|
|
# should be enough.
|
|
team_member_query =
|
|
from(
|
|
tm in Teams.Membership,
|
|
as: :site_parent,
|
|
where: exists(sites_query),
|
|
where: tm.user_id == ^user.id,
|
|
select: 1
|
|
)
|
|
|
|
query =
|
|
if include_pending? do
|
|
site_transfer_query =
|
|
from(
|
|
st in Teams.SiteTransfer,
|
|
where: st.email == ^user.email,
|
|
select: 1
|
|
)
|
|
|
|
# NOTE: The same principle applies to guest team invitations,
|
|
# as it's pruned as well when there are no more guest invitations
|
|
# associated with it.
|
|
member_invitation_query =
|
|
from(
|
|
ti in Teams.Invitation,
|
|
as: :site_parent,
|
|
where: exists(sites_query),
|
|
where: ti.email == ^user.email,
|
|
select: 1
|
|
)
|
|
|
|
team_member_query
|
|
|> union_all(^site_transfer_query)
|
|
|> union_all(^member_invitation_query)
|
|
else
|
|
team_member_query
|
|
end
|
|
|
|
Repo.exists?(query)
|
|
end
|
|
|
|
def owns_sites?(user, opts \\ []) do
|
|
include_pending? = Keyword.get(opts, :include_pending?, false)
|
|
only_team = Keyword.get(opts, :only_team)
|
|
|
|
sites_query =
|
|
from(
|
|
s in Plausible.Site,
|
|
where: s.team_id == parent_as(:site_parent).team_id,
|
|
select: 1
|
|
)
|
|
|
|
owner_query =
|
|
from(
|
|
tm in Teams.Membership,
|
|
as: :site_parent,
|
|
where: exists(sites_query),
|
|
where: tm.user_id == ^user.id,
|
|
where: tm.role == :owner,
|
|
select: 1
|
|
)
|
|
|
|
owner_query =
|
|
if only_team do
|
|
where(owner_query, [tm], tm.team_id == ^only_team.id)
|
|
else
|
|
owner_query
|
|
end
|
|
|
|
query =
|
|
if include_pending? do
|
|
site_transfer_query =
|
|
from(
|
|
st in Teams.SiteTransfer,
|
|
where: st.email == ^user.email,
|
|
select: 1
|
|
)
|
|
|
|
owner_invitation_query =
|
|
from(
|
|
ti in Teams.Invitation,
|
|
as: :site_parent,
|
|
where: exists(sites_query),
|
|
where: ti.email == ^user.email,
|
|
where: ti.role == :owner,
|
|
select: 1
|
|
)
|
|
|
|
owner_query
|
|
|> union_all(^site_transfer_query)
|
|
|> union_all(^owner_invitation_query)
|
|
else
|
|
owner_query
|
|
end
|
|
|
|
Repo.exists?(query)
|
|
end
|
|
end
|