feat(contacts): hide Private column when the viewer has nothing private
Row-level privacy was already correct: private rows only render for the owner and admins. The header column was still showing for every viewer, leaving an always-empty slot for anyone without private contacts of their own. Drop `:private` from the fields list unless the scope can actually see at least one private row.
This commit is contained in:
parent
c38f4e2bfe
commit
4b155c5419
2 changed files with 79 additions and 1 deletions
|
|
@ -61,9 +61,31 @@ defmodule MicrowavepropWeb.ContactLive.Index do
|
|||
socket
|
||||
|> assign(:page_title, "Contacts")
|
||||
|> assign(:total_contacts, total)
|
||||
|> assign(:visible_fields, visible_fields_for(scope))
|
||||
|> assign(:data_provider, {__MODULE__, :visible_query_provider, [scope_token(scope)]})}
|
||||
end
|
||||
|
||||
# Hide the Private column entirely unless this scope can actually see
|
||||
# at least one private contact — avoids an always-empty column for
|
||||
# visitors and owners who've never flagged one as private.
|
||||
defp visible_fields_for(scope) do
|
||||
if has_viewable_private?(scope) do
|
||||
fields()
|
||||
else
|
||||
Keyword.delete(fields(), :private)
|
||||
end
|
||||
end
|
||||
|
||||
defp has_viewable_private?(%Scope{user: %User{is_admin: true}}) do
|
||||
Repo.exists?(from(c in Contact, where: c.private == true))
|
||||
end
|
||||
|
||||
defp has_viewable_private?(%Scope{user: %User{id: user_id}}) do
|
||||
Repo.exists?(from(c in Contact, where: c.private == true and c.user_id == ^user_id))
|
||||
end
|
||||
|
||||
defp has_viewable_private?(_), do: false
|
||||
|
||||
@doc false
|
||||
# Called by LiveTable to get the base queryable. Must be a
|
||||
# named function because the helper persists MFA across renders.
|
||||
|
|
@ -183,7 +205,7 @@ defmodule MicrowavepropWeb.ContactLive.Index do
|
|||
</.header>
|
||||
|
||||
<.live_table
|
||||
fields={fields()}
|
||||
fields={@visible_fields}
|
||||
filters={filters()}
|
||||
options={@options}
|
||||
streams={@streams}
|
||||
|
|
|
|||
|
|
@ -167,6 +167,62 @@ defmodule MicrowavepropWeb.ContactLiveTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "Index private column visibility" do
|
||||
import Microwaveprop.AccountsFixtures
|
||||
|
||||
test "column hidden for anonymous viewer when no private contacts exist", %{conn: conn} do
|
||||
_public = create_contact(%{station1: "W5PUB"})
|
||||
|
||||
{:ok, _lv, html} = live(conn, ~p"/contacts")
|
||||
refute html =~ ">Private<"
|
||||
end
|
||||
|
||||
test "column hidden for anonymous viewer even when others have private contacts", %{conn: conn} do
|
||||
_private = create_contact(%{station1: "W5PRV", private: true})
|
||||
_public = create_contact(%{station1: "W5PUB"})
|
||||
|
||||
{:ok, _lv, html} = live(conn, ~p"/contacts")
|
||||
refute html =~ ">Private<"
|
||||
end
|
||||
|
||||
test "column hidden for a user who has no private contacts of their own", %{conn: conn} do
|
||||
owner = user_fixture()
|
||||
viewer = user_fixture()
|
||||
_others_private = create_contact(%{station1: "W5PRV", private: true, user_id: owner.id})
|
||||
conn = log_in_user(conn, viewer)
|
||||
|
||||
{:ok, _lv, html} = live(conn, ~p"/contacts")
|
||||
refute html =~ ">Private<"
|
||||
end
|
||||
|
||||
test "column visible for a user with at least one of their own private contacts", %{conn: conn} do
|
||||
owner = user_fixture()
|
||||
_private = create_contact(%{station1: "W5PRV", private: true, user_id: owner.id})
|
||||
conn = log_in_user(conn, owner)
|
||||
|
||||
{:ok, _lv, html} = live(conn, ~p"/contacts")
|
||||
assert html =~ ">Private<"
|
||||
end
|
||||
|
||||
test "column hidden for admin when there are no private contacts anywhere", %{conn: conn} do
|
||||
admin = user_fixture() |> Ecto.Changeset.change(is_admin: true) |> Repo.update!()
|
||||
_public = create_contact(%{station1: "W5PUB"})
|
||||
conn = log_in_user(conn, admin)
|
||||
|
||||
{:ok, _lv, html} = live(conn, ~p"/contacts")
|
||||
refute html =~ ">Private<"
|
||||
end
|
||||
|
||||
test "column visible for admin as soon as any private contact exists", %{conn: conn} do
|
||||
admin = user_fixture() |> Ecto.Changeset.change(is_admin: true) |> Repo.update!()
|
||||
_private = create_contact(%{station1: "W5PRV", private: true})
|
||||
conn = log_in_user(conn, admin)
|
||||
|
||||
{:ok, _lv, html} = live(conn, ~p"/contacts")
|
||||
assert html =~ ">Private<"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Show private visibility" do
|
||||
import Microwaveprop.AccountsFixtures
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue