UI for adding and removing members on the group show page #401

Open
simon wants to merge 5 commits from feature/ui-for-adding-members-groups into main
3 changed files with 37 additions and 7 deletions
Showing only changes of commit e4671e816b - Show all commits

View file

@ -12,6 +12,13 @@ defmodule MvWeb.GroupLive.ShowAddRemoveMembersTest do
alias Mv.Fixtures
describe "Add Member button visibility" do
@tag role: :read_only
test "read_only user can access group show page (page permission)", %{conn: conn} do
group = Fixtures.group_fixture()
conn = get(conn, "/groups/#{group.slug}")
assert conn.status == 200
end
test "Add Member button is visible for users with :update permission", %{conn: conn} do
group = Fixtures.group_fixture()
@ -20,7 +27,7 @@ defmodule MvWeb.GroupLive.ShowAddRemoveMembersTest do
assert html =~ gettext("Add Member") or html =~ "Add Member"
end
@tag role: :member
@tag role: :read_only
test "Add Member button is NOT visible for users without :update permission", %{conn: conn} do
group = Fixtures.group_fixture()
@ -61,7 +68,7 @@ defmodule MvWeb.GroupLive.ShowAddRemoveMembersTest do
html =~ ~r/hero-trash|hero-x-mark/
end
@tag role: :member
@tag role: :read_only
test "Remove button is NOT visible for users without :update permission", %{conn: conn} do
group = Fixtures.group_fixture()
member = Fixtures.member_fixture(%{first_name: "Bob", last_name: "Jones"})

View file

@ -56,7 +56,7 @@ defmodule MvWeb.GroupLive.ShowAuthorizationTest do
assert html =~ "Alice"
end
@tag role: :member
@tag role: :read_only
test "unauthorized user cannot add member (server-side check)", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
group = Fixtures.group_fixture()
@ -113,7 +113,7 @@ defmodule MvWeb.GroupLive.ShowAuthorizationTest do
refute html =~ "Charlie"
end
@tag role: :member
@tag role: :read_only
test "unauthorized user cannot remove member (server-side check)", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
group = Fixtures.group_fixture()
@ -180,7 +180,7 @@ defmodule MvWeb.GroupLive.ShowAuthorizationTest do
assert html =~ "Add Member" || html =~ "Remove"
end
@tag role: :member
@tag role: :read_only
test "Add Member button is hidden for read-only users", %{conn: conn} do
_system_actor = Mv.Helpers.SystemActor.get_system_actor()
group = Fixtures.group_fixture()
@ -191,7 +191,7 @@ defmodule MvWeb.GroupLive.ShowAuthorizationTest do
refute html =~ "Add Member"
end
@tag role: :member
@tag role: :read_only
test "Remove button is hidden for read-only users", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
group = Fixtures.group_fixture()
@ -216,7 +216,7 @@ defmodule MvWeb.GroupLive.ShowAuthorizationTest do
refute html =~ "hero-trash" or html =~ ~r/<button[^>]*remove_member/
end
@tag role: :member
@tag role: :read_only
test "modal cannot be opened for unauthorized users", %{conn: conn} do
group = Fixtures.group_fixture()
@ -228,6 +228,28 @@ defmodule MvWeb.GroupLive.ShowAuthorizationTest do
end
end
describe "member (own_data) page access" do
# Members have no page permission for /groups or /groups/:slug; they are redirected.
# This tests that limited access for the member role is enforced.
@tag role: :member
test "member is redirected when accessing group show page", %{conn: conn} do
group = Fixtures.group_fixture()
result = live(conn, "/groups/#{group.slug}")
assert {:error, {:redirect, %{to: path, flash: %{"error" => _}}}} = result
assert path =~ ~r|^/users/[^/]+$|
end
@tag role: :member
test "member is redirected when accessing groups index", %{conn: conn} do
result = live(conn, "/groups")
assert {:error, {:redirect, %{to: path, flash: %{"error" => _}}}} = result
assert path =~ ~r|^/users/[^/]+$|
end
end
describe "security edge cases" do
test "slug injection attempts are prevented", %{conn: conn} do
# Try to inject malicious content in slug

View file

@ -178,6 +178,7 @@ defmodule MvWeb.ConnCase do
:read_only ->
# Vorstand/Buchhaltung: can read members, groups; cannot edit or access admin/settings
read_only_user = Mv.Fixtures.user_with_role_fixture("read_only")
read_only_user = Mv.Authorization.Actor.ensure_loaded(read_only_user)
authenticated_conn = conn_with_password_user(conn, read_only_user)
{authenticated_conn, read_only_user}