Compare commits
7 commits
ae1605c447
...
1426ef1d38
| Author | SHA1 | Date | |
|---|---|---|---|
| 1426ef1d38 | |||
| f779fd61e0 | |||
| cc9e530d80 | |||
| 2f67c7099d | |||
| 5e361ba400 | |||
| 505e31653a | |||
| d3ad7c5013 |
9 changed files with 403 additions and 49 deletions
|
|
@ -70,33 +70,56 @@ defmodule MvWeb.Layouts.Sidebar do
|
||||||
defp sidebar_menu(assigns) do
|
defp sidebar_menu(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<ul class="menu flex-1 w-full p-2" role="menubar">
|
<ul class="menu flex-1 w-full p-2" role="menubar">
|
||||||
<.menu_item
|
<%= if can_access_page?(@current_user, "/members") do %>
|
||||||
href={~p"/members"}
|
<.menu_item
|
||||||
icon="hero-users"
|
href={~p"/members"}
|
||||||
label={gettext("Members")}
|
icon="hero-users"
|
||||||
/>
|
label={gettext("Members")}
|
||||||
|
|
||||||
<.menu_item
|
|
||||||
href={~p"/membership_fee_types"}
|
|
||||||
icon="hero-currency-euro"
|
|
||||||
label={gettext("Fee Types")}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Nested Admin Menu -->
|
|
||||||
<.menu_group icon="hero-cog-6-tooth" label={gettext("Administration")}>
|
|
||||||
<.menu_subitem href={~p"/users"} label={gettext("Users")} />
|
|
||||||
<.menu_subitem href={~p"/groups"} label={gettext("Groups")} />
|
|
||||||
<.menu_subitem href={~p"/admin/roles"} label={gettext("Roles")} />
|
|
||||||
<.menu_subitem
|
|
||||||
href={~p"/membership_fee_settings"}
|
|
||||||
label={gettext("Fee Settings")}
|
|
||||||
/>
|
/>
|
||||||
<.menu_subitem href={~p"/settings"} label={gettext("Settings")} />
|
<% end %>
|
||||||
</.menu_group>
|
|
||||||
|
<%= if can_access_page?(@current_user, "/membership_fee_types") do %>
|
||||||
|
<.menu_item
|
||||||
|
href={~p"/membership_fee_types"}
|
||||||
|
icon="hero-currency-euro"
|
||||||
|
label={gettext("Fee Types")}
|
||||||
|
/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= if admin_menu_visible?(@current_user) do %>
|
||||||
|
<.menu_group icon="hero-cog-6-tooth" label={gettext("Administration")}>
|
||||||
|
<%= if can_access_page?(@current_user, "/users") do %>
|
||||||
|
<.menu_subitem href={~p"/users"} label={gettext("Users")} />
|
||||||
|
<% end %>
|
||||||
|
<%= if can_access_page?(@current_user, "/groups") do %>
|
||||||
|
<.menu_subitem href={~p"/groups"} label={gettext("Groups")} />
|
||||||
|
<% end %>
|
||||||
|
<%= if can_access_page?(@current_user, "/admin/roles") do %>
|
||||||
|
<.menu_subitem href={~p"/admin/roles"} label={gettext("Roles")} />
|
||||||
|
<% end %>
|
||||||
|
<%= if can_access_page?(@current_user, "/membership_fee_settings") do %>
|
||||||
|
<.menu_subitem
|
||||||
|
href={~p"/membership_fee_settings"}
|
||||||
|
label={gettext("Fee Settings")}
|
||||||
|
/>
|
||||||
|
<% end %>
|
||||||
|
<%= if can_access_page?(@current_user, "/settings") do %>
|
||||||
|
<.menu_subitem href={~p"/settings"} label={gettext("Settings")} />
|
||||||
|
<% end %>
|
||||||
|
</.menu_group>
|
||||||
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp admin_menu_visible?(user) do
|
||||||
|
Enum.any?(admin_page_paths(), &can_access_page?(user, &1))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp admin_page_paths do
|
||||||
|
["/users", "/groups", "/admin/roles", "/membership_fee_settings", "/settings"]
|
||||||
|
end
|
||||||
|
|
||||||
attr :href, :string, required: true, doc: "Navigation path"
|
attr :href, :string, required: true, doc: "Navigation path"
|
||||||
attr :icon, :string, required: true, doc: "Heroicon name"
|
attr :icon, :string, required: true, doc: "Heroicon name"
|
||||||
attr :label, :string, required: true, doc: "Menu item label"
|
attr :label, :string, required: true, doc: "Menu item label"
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,11 @@
|
||||||
<.icon name="hero-envelope" />
|
<.icon name="hero-envelope" />
|
||||||
{gettext("Open in email program")}
|
{gettext("Open in email program")}
|
||||||
</.button>
|
</.button>
|
||||||
<.button variant="primary" navigate={~p"/members/new"}>
|
<%= if can?(@current_user, :create, Mv.Membership.Member) do %>
|
||||||
<.icon name="hero-plus" /> {gettext("New Member")}
|
<.button variant="primary" navigate={~p"/members/new"}>
|
||||||
</.button>
|
<.icon name="hero-plus" /> {gettext("New Member")}
|
||||||
|
</.button>
|
||||||
|
<% end %>
|
||||||
</:actions>
|
</:actions>
|
||||||
</.header>
|
</.header>
|
||||||
|
|
||||||
|
|
@ -297,16 +299,20 @@
|
||||||
<.link navigate={~p"/members/#{member}"}>{gettext("Show")}</.link>
|
<.link navigate={~p"/members/#{member}"}>{gettext("Show")}</.link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<.link navigate={~p"/members/#{member}/edit"}>{gettext("Edit")}</.link>
|
<%= if can?(@current_user, :update, member) do %>
|
||||||
|
<.link navigate={~p"/members/#{member}/edit"}>{gettext("Edit")}</.link>
|
||||||
|
<% end %>
|
||||||
</:action>
|
</:action>
|
||||||
|
|
||||||
<:action :let={member}>
|
<:action :let={member}>
|
||||||
<.link
|
<%= if can?(@current_user, :destroy, member) do %>
|
||||||
phx-click={JS.push("delete", value: %{id: member.id}) |> hide("#row-#{member.id}")}
|
<.link
|
||||||
data-confirm={gettext("Are you sure?")}
|
phx-click={JS.push("delete", value: %{id: member.id}) |> hide("#row-#{member.id}")}
|
||||||
>
|
data-confirm={gettext("Are you sure?")}
|
||||||
{gettext("Delete")}
|
>
|
||||||
</.link>
|
{gettext("Delete")}
|
||||||
|
</.link>
|
||||||
|
<% end %>
|
||||||
</:action>
|
</:action>
|
||||||
</.table>
|
</.table>
|
||||||
</Layouts.app>
|
</Layouts.app>
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,11 @@ defmodule MvWeb.MemberLive.Show do
|
||||||
{MvWeb.Helpers.MemberHelpers.display_name(@member)}
|
{MvWeb.Helpers.MemberHelpers.display_name(@member)}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<.button variant="primary" navigate={~p"/members/#{@member}/edit?return_to=show"}>
|
<%= if can?(@current_user, :update, @member) do %>
|
||||||
{gettext("Edit Member")}
|
<.button variant="primary" navigate={~p"/members/#{@member}/edit?return_to=show"}>
|
||||||
</.button>
|
{gettext("Edit Member")}
|
||||||
|
</.button>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%!-- Tab Navigation --%>
|
<%!-- Tab Navigation --%>
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@
|
||||||
<.header>
|
<.header>
|
||||||
{gettext("Listing Users")}
|
{gettext("Listing Users")}
|
||||||
<:actions>
|
<:actions>
|
||||||
<.button variant="primary" navigate={~p"/users/new"}>
|
<%= if can?(@current_user, :create, Mv.Accounts.User) do %>
|
||||||
<.icon name="hero-plus" /> {gettext("New User")}
|
<.button variant="primary" navigate={~p"/users/new"}>
|
||||||
</.button>
|
<.icon name="hero-plus" /> {gettext("New User")}
|
||||||
|
</.button>
|
||||||
|
<% end %>
|
||||||
</:actions>
|
</:actions>
|
||||||
</.header>
|
</.header>
|
||||||
|
|
||||||
|
|
@ -62,16 +64,20 @@
|
||||||
<.link navigate={~p"/users/#{user}"}>{gettext("Show")}</.link>
|
<.link navigate={~p"/users/#{user}"}>{gettext("Show")}</.link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<.link navigate={~p"/users/#{user}/edit"}>{gettext("Edit")}</.link>
|
<%= if can?(@current_user, :update, user) do %>
|
||||||
|
<.link navigate={~p"/users/#{user}/edit"}>{gettext("Edit")}</.link>
|
||||||
|
<% end %>
|
||||||
</:action>
|
</:action>
|
||||||
|
|
||||||
<:action :let={user}>
|
<:action :let={user}>
|
||||||
<.link
|
<%= if can?(@current_user, :destroy, user) do %>
|
||||||
phx-click={JS.push("delete", value: %{id: user.id}) |> hide("#row-#{user.id}")}
|
<.link
|
||||||
data-confirm={gettext("Are you sure?")}
|
phx-click={JS.push("delete", value: %{id: user.id}) |> hide("#row-#{user.id}")}
|
||||||
>
|
data-confirm={gettext("Are you sure?")}
|
||||||
{gettext("Delete")}
|
>
|
||||||
</.link>
|
{gettext("Delete")}
|
||||||
|
</.link>
|
||||||
|
<% end %>
|
||||||
</:action>
|
</:action>
|
||||||
</.table>
|
</.table>
|
||||||
</Layouts.app>
|
</Layouts.app>
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,11 @@ defmodule MvWeb.UserLive.Show do
|
||||||
<.icon name="hero-arrow-left" />
|
<.icon name="hero-arrow-left" />
|
||||||
<span class="sr-only">{gettext("Back to users list")}</span>
|
<span class="sr-only">{gettext("Back to users list")}</span>
|
||||||
</.button>
|
</.button>
|
||||||
<.button variant="primary" navigate={~p"/users/#{@user}/edit?return_to=show"}>
|
<%= if can?(@current_user, :update, @user) do %>
|
||||||
<.icon name="hero-pencil-square" /> {gettext("Edit User")}
|
<.button variant="primary" navigate={~p"/users/#{@user}/edit?return_to=show"}>
|
||||||
</.button>
|
<.icon name="hero-pencil-square" /> {gettext("Edit User")}
|
||||||
|
</.button>
|
||||||
|
<% end %>
|
||||||
</:actions>
|
</:actions>
|
||||||
</.header>
|
</.header>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,14 @@ defmodule MvWeb.Layouts.SidebarTest do
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
# Returns assigns for an authenticated user with all required attributes.
|
# Returns assigns for an authenticated user with all required attributes.
|
||||||
|
# User has admin role so can_access_page? returns true for all sidebar links.
|
||||||
defp authenticated_assigns(mobile \\ false) do
|
defp authenticated_assigns(mobile \\ false) do
|
||||||
%{
|
%{
|
||||||
current_user: %{id: "user-123", email: "test@example.com"},
|
current_user: %{
|
||||||
|
id: "user-123",
|
||||||
|
email: "test@example.com",
|
||||||
|
role: %{permission_set_name: "admin"}
|
||||||
|
},
|
||||||
club_name: "Test Club",
|
club_name: "Test Club",
|
||||||
mobile: mobile
|
mobile: mobile
|
||||||
}
|
}
|
||||||
|
|
|
||||||
120
test/mv_web/components/sidebar_authorization_test.exs
Normal file
120
test/mv_web/components/sidebar_authorization_test.exs
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
defmodule MvWeb.SidebarAuthorizationTest do
|
||||||
|
@moduledoc """
|
||||||
|
Tests for sidebar menu visibility based on user permissions (can_access_page?).
|
||||||
|
"""
|
||||||
|
use MvWeb.ConnCase, async: false
|
||||||
|
|
||||||
|
import Phoenix.LiveViewTest
|
||||||
|
import MvWeb.Layouts.Sidebar
|
||||||
|
|
||||||
|
alias Mv.Fixtures
|
||||||
|
|
||||||
|
defp render_sidebar(assigns) do
|
||||||
|
render_component(&sidebar/1, assigns)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp sidebar_assigns(current_user, opts \\ []) do
|
||||||
|
mobile = Keyword.get(opts, :mobile, false)
|
||||||
|
club_name = Keyword.get(opts, :club_name, "Test Club")
|
||||||
|
|
||||||
|
%{
|
||||||
|
current_user: current_user,
|
||||||
|
club_name: club_name,
|
||||||
|
mobile: mobile
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "sidebar menu with admin user" do
|
||||||
|
test "shows Members, Fee Types and Administration with all subitems" do
|
||||||
|
user = Fixtures.user_with_role_fixture("admin")
|
||||||
|
html = render_sidebar(sidebar_assigns(user))
|
||||||
|
|
||||||
|
assert html =~ ~s(href="/members")
|
||||||
|
assert html =~ ~s(href="/membership_fee_types")
|
||||||
|
assert html =~ ~s(aria-label="Administration")
|
||||||
|
assert html =~ ~s(href="/users")
|
||||||
|
assert html =~ ~s(href="/groups")
|
||||||
|
assert html =~ ~s(href="/admin/roles")
|
||||||
|
assert html =~ ~s(href="/membership_fee_settings")
|
||||||
|
assert html =~ ~s(href="/settings")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "sidebar menu with read_only user (Vorstand/Buchhaltung)" do
|
||||||
|
test "shows Members and Groups (from Administration)" do
|
||||||
|
user = Fixtures.user_with_role_fixture("read_only")
|
||||||
|
html = render_sidebar(sidebar_assigns(user))
|
||||||
|
|
||||||
|
assert html =~ ~s(href="/members")
|
||||||
|
assert html =~ ~s(href="/groups")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not show Fee Types, Users, Roles or Settings" do
|
||||||
|
user = Fixtures.user_with_role_fixture("read_only")
|
||||||
|
html = render_sidebar(sidebar_assigns(user))
|
||||||
|
|
||||||
|
refute html =~ ~s(href="/membership_fee_types")
|
||||||
|
refute html =~ ~s(href="/users")
|
||||||
|
refute html =~ ~s(href="/admin/roles")
|
||||||
|
refute html =~ ~s(href="/settings")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "sidebar menu with normal_user (Kassenwart)" do
|
||||||
|
test "shows Members and Groups" do
|
||||||
|
user = Fixtures.user_with_role_fixture("normal_user")
|
||||||
|
html = render_sidebar(sidebar_assigns(user))
|
||||||
|
|
||||||
|
assert html =~ ~s(href="/members")
|
||||||
|
assert html =~ ~s(href="/groups")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not show Fee Types, Users, Roles or Settings" do
|
||||||
|
user = Fixtures.user_with_role_fixture("normal_user")
|
||||||
|
html = render_sidebar(sidebar_assigns(user))
|
||||||
|
|
||||||
|
refute html =~ ~s(href="/membership_fee_types")
|
||||||
|
refute html =~ ~s(href="/users")
|
||||||
|
refute html =~ ~s(href="/admin/roles")
|
||||||
|
refute html =~ ~s(href="/settings")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "sidebar menu with own_data user (Mitglied)" do
|
||||||
|
test "does not show Members link (no /members page access)" do
|
||||||
|
user = Fixtures.user_with_role_fixture("own_data")
|
||||||
|
html = render_sidebar(sidebar_assigns(user))
|
||||||
|
|
||||||
|
refute html =~ ~s(href="/members")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not show Fee Types or Administration" do
|
||||||
|
user = Fixtures.user_with_role_fixture("own_data")
|
||||||
|
html = render_sidebar(sidebar_assigns(user))
|
||||||
|
|
||||||
|
refute html =~ ~s(href="/membership_fee_types")
|
||||||
|
refute html =~ ~s(href="/users")
|
||||||
|
refute html =~ ~s(aria-label="Administration")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "sidebar with nil current_user" do
|
||||||
|
test "does not render menu items (only header and footer when present)" do
|
||||||
|
html = render_sidebar(sidebar_assigns(nil))
|
||||||
|
|
||||||
|
refute html =~ ~s(role="menubar")
|
||||||
|
refute html =~ ~s(href="/members")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "sidebar with user without role" do
|
||||||
|
test "does not show any navigation links" do
|
||||||
|
user = %{id: "user-no-role", email: "noreply@test.com", role: nil}
|
||||||
|
html = render_sidebar(sidebar_assigns(user))
|
||||||
|
|
||||||
|
refute html =~ ~s(href="/members")
|
||||||
|
refute html =~ ~s(href="/membership_fee_types")
|
||||||
|
refute html =~ ~s(href="/users")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
106
test/mv_web/live/member_live_authorization_test.exs
Normal file
106
test/mv_web/live/member_live_authorization_test.exs
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
defmodule MvWeb.MemberLiveAuthorizationTest do
|
||||||
|
@moduledoc """
|
||||||
|
Tests for UI authorization on Member LiveViews (Index and Show).
|
||||||
|
"""
|
||||||
|
use MvWeb.ConnCase, async: false
|
||||||
|
|
||||||
|
import Phoenix.LiveViewTest
|
||||||
|
|
||||||
|
alias Mv.Fixtures
|
||||||
|
|
||||||
|
# Use literal strings for button/link text (matches default Gettext locale)
|
||||||
|
@new_member_text "New Member"
|
||||||
|
@edit_member_text "Edit Member"
|
||||||
|
|
||||||
|
describe "Member Index - Vorstand (read_only)" do
|
||||||
|
@tag role: :read_only
|
||||||
|
test "sees member list but not New Member button", %{conn: conn} do
|
||||||
|
_member = Fixtures.member_fixture()
|
||||||
|
|
||||||
|
{:ok, _view, html} = live(conn, "/members")
|
||||||
|
|
||||||
|
refute html =~ @new_member_text
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag role: :read_only
|
||||||
|
test "does not see Edit or Delete buttons in table", %{conn: conn} do
|
||||||
|
member = Fixtures.member_fixture()
|
||||||
|
|
||||||
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
|
refute has_element?(view, "a[href=\"/members/#{member.id}/edit\"]")
|
||||||
|
refute has_element?(view, "a[phx-click*='delete']")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Member Index - Kassenwart (normal_user)" do
|
||||||
|
@tag role: :normal_user
|
||||||
|
test "sees New Member and Edit buttons", %{conn: conn} do
|
||||||
|
member = Fixtures.member_fixture()
|
||||||
|
|
||||||
|
{:ok, view, html} = live(conn, "/members")
|
||||||
|
|
||||||
|
assert html =~ @new_member_text
|
||||||
|
assert has_element?(view, "a[href=\"/members/#{member.id}/edit\"]")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag role: :normal_user
|
||||||
|
test "does not see Delete button", %{conn: conn} do
|
||||||
|
_member = Fixtures.member_fixture()
|
||||||
|
|
||||||
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
|
refute has_element?(view, "a[phx-click*='delete']")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Member Index - Admin" do
|
||||||
|
@tag role: :admin
|
||||||
|
test "sees New Member, Edit and Delete buttons", %{conn: conn} do
|
||||||
|
member = Fixtures.member_fixture()
|
||||||
|
|
||||||
|
{:ok, view, html} = live(conn, "/members")
|
||||||
|
|
||||||
|
assert html =~ @new_member_text
|
||||||
|
assert has_element?(view, "a[href=\"/members/#{member.id}/edit\"]")
|
||||||
|
assert has_element?(view, "a[phx-click*='delete']")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Member Index - Mitglied (own_data)" do
|
||||||
|
@tag role: :member
|
||||||
|
test "is redirected when accessing /members", %{conn: conn, current_user: user} do
|
||||||
|
assert {:error, {:redirect, %{to: to}}} = live(conn, "/members")
|
||||||
|
assert to == "/users/#{user.id}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Member Show - Edit button visibility" do
|
||||||
|
@tag role: :admin
|
||||||
|
test "admin sees Edit button", %{conn: conn} do
|
||||||
|
member = Fixtures.member_fixture()
|
||||||
|
|
||||||
|
{:ok, _view, html} = live(conn, "/members/#{member.id}")
|
||||||
|
|
||||||
|
assert html =~ @edit_member_text
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag role: :read_only
|
||||||
|
test "read_only does not see Edit button", %{conn: conn} do
|
||||||
|
member = Fixtures.member_fixture()
|
||||||
|
|
||||||
|
{:ok, _view, html} = live(conn, "/members/#{member.id}")
|
||||||
|
|
||||||
|
refute html =~ @edit_member_text
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag role: :normal_user
|
||||||
|
test "normal_user sees Edit button", %{conn: conn} do
|
||||||
|
member = Fixtures.member_fixture()
|
||||||
|
|
||||||
|
{:ok, _view, html} = live(conn, "/members/#{member.id}")
|
||||||
|
|
||||||
|
assert html =~ @edit_member_text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
84
test/mv_web/live/user_live_authorization_test.exs
Normal file
84
test/mv_web/live/user_live_authorization_test.exs
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
defmodule MvWeb.UserLiveAuthorizationTest do
|
||||||
|
@moduledoc """
|
||||||
|
Tests for UI authorization on User LiveViews (Index and Show).
|
||||||
|
"""
|
||||||
|
use MvWeb.ConnCase, async: false
|
||||||
|
|
||||||
|
import Phoenix.LiveViewTest
|
||||||
|
|
||||||
|
alias Mv.Fixtures
|
||||||
|
|
||||||
|
@new_user_text "New User"
|
||||||
|
@edit_user_text "Edit User"
|
||||||
|
|
||||||
|
describe "User Index - Admin" do
|
||||||
|
@tag role: :admin
|
||||||
|
test "sees New User, Edit and Delete buttons", %{conn: conn} do
|
||||||
|
user = Fixtures.user_with_role_fixture("admin")
|
||||||
|
|
||||||
|
{:ok, view, html} = live(conn, "/users")
|
||||||
|
|
||||||
|
assert html =~ @new_user_text
|
||||||
|
assert has_element?(view, "a[href=\"/users/#{user.id}/edit\"]")
|
||||||
|
assert has_element?(view, "a[phx-click*='delete']")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "User Index - Non-Admin is redirected" do
|
||||||
|
@tag role: :read_only
|
||||||
|
test "read_only is redirected when accessing /users", %{conn: conn, current_user: user} do
|
||||||
|
assert {:error, {:redirect, %{to: to}}} = live(conn, "/users")
|
||||||
|
assert to == "/users/#{user.id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag role: :member
|
||||||
|
test "member is redirected when accessing /users", %{conn: conn, current_user: user} do
|
||||||
|
assert {:error, {:redirect, %{to: to}}} = live(conn, "/users")
|
||||||
|
assert to == "/users/#{user.id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag role: :normal_user
|
||||||
|
test "normal_user is redirected when accessing /users", %{conn: conn, current_user: user} do
|
||||||
|
assert {:error, {:redirect, %{to: to}}} = live(conn, "/users")
|
||||||
|
assert to == "/users/#{user.id}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "User Show - own profile" do
|
||||||
|
@tag role: :member
|
||||||
|
test "member sees Edit button on own profile", %{conn: conn, current_user: user} do
|
||||||
|
{:ok, _view, html} = live(conn, "/users/#{user.id}")
|
||||||
|
|
||||||
|
assert html =~ @edit_user_text
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag role: :read_only
|
||||||
|
test "read_only sees Edit button on own profile", %{conn: conn, current_user: user} do
|
||||||
|
{:ok, _view, html} = live(conn, "/users/#{user.id}")
|
||||||
|
|
||||||
|
assert html =~ @edit_user_text
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag role: :admin
|
||||||
|
test "admin sees Edit button on user show", %{conn: conn} do
|
||||||
|
user = Fixtures.user_with_role_fixture("read_only")
|
||||||
|
|
||||||
|
{:ok, _view, html} = live(conn, "/users/#{user.id}")
|
||||||
|
|
||||||
|
assert html =~ @edit_user_text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "User Show - other user (non-admin redirected)" do
|
||||||
|
@tag role: :member
|
||||||
|
test "member is redirected when accessing other user's profile", %{
|
||||||
|
conn: conn,
|
||||||
|
current_user: current_user
|
||||||
|
} do
|
||||||
|
other_user = Fixtures.user_with_role_fixture("admin")
|
||||||
|
|
||||||
|
assert {:error, {:redirect, %{to: to}}} = live(conn, "/users/#{other_user.id}")
|
||||||
|
assert to == "/users/#{current_user.id}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Add table
Add a link
Reference in a new issue