- ConnCase: add :read_only and :normal_user role tags for tests. - Add CheckPagePermission plug tests (unit + integration for member, read_only, normal_user, admin). Update permission_sets_test (refute "/" for own_data). - Profile navigation, global_settings, role_live, membership_fee_type: use users with role for "/" access; expect redirect for own_data on /settings and /admin/roles.
212 lines
7.1 KiB
Elixir
212 lines
7.1 KiB
Elixir
defmodule MvWeb.ProfileNavigationTest do
|
|
use MvWeb.ConnCase, async: true
|
|
import Phoenix.LiveViewTest
|
|
|
|
setup do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
%{actor: system_actor}
|
|
end
|
|
|
|
describe "profile navigation" do
|
|
test "clicking profile button redirects to current user profile", %{conn: conn} do
|
|
# User needs a role with page permission for "/" (e.g. admin)
|
|
user = Mv.Fixtures.user_with_role_fixture("admin")
|
|
conn = conn_with_password_user(conn, user)
|
|
{:ok, view, _html} = live(conn, "/")
|
|
|
|
# Click the profile button
|
|
view |> element("a", "Profil") |> render_click()
|
|
|
|
# Verify we're on the profile page
|
|
assert_redirected(view, "/users/#{user.id}")
|
|
end
|
|
|
|
test "profile navigation shows correct user data", %{conn: conn, actor: actor} do
|
|
# User with password (from create_test_user) and admin role so they can access "/"
|
|
user = create_test_user(%{email: "test@example.com"})
|
|
admin_role = Mv.Fixtures.role_fixture("admin")
|
|
|
|
{:ok, user} =
|
|
user
|
|
|> Ash.Changeset.for_update(:update, %{})
|
|
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
|
|> Ash.update(actor: actor)
|
|
|
|
user = Ash.load!(user, :role, domain: Mv.Accounts, actor: actor)
|
|
conn = conn_with_password_user(conn, user)
|
|
|
|
# Navigate to profile
|
|
{:ok, view, _html} = live(conn, "/")
|
|
view |> element("a", "Profil") |> render_click()
|
|
|
|
# Verify profile data
|
|
{:ok, _profile_view, html} = live(conn, "/users/#{user.id}")
|
|
assert html =~ to_string(user.email)
|
|
assert html =~ "Password Authentication"
|
|
assert html =~ "Enabled"
|
|
end
|
|
end
|
|
|
|
describe "sidebar" do
|
|
test "renders profile button with correct attributes", %{conn: conn} do
|
|
# User needs a role with page permission for "/"
|
|
user = Mv.Fixtures.user_with_role_fixture("admin")
|
|
conn = conn_with_password_user(conn, user)
|
|
{:ok, _view, html} = live(conn, "/")
|
|
|
|
assert html =~ ~s(role="button")
|
|
assert html =~ "dropdown-content"
|
|
assert html =~ "avatar"
|
|
assert html =~ "Profil"
|
|
end
|
|
|
|
@tag :skip
|
|
# TODO: Implement user initials in navbar avatar - see issue #170
|
|
test "shows user initials in avatar", %{conn: conn} do
|
|
# Setup: Create and login a user
|
|
user = create_test_user(%{email: "test.user@example.com"})
|
|
conn = conn_with_password_user(conn, user)
|
|
{:ok, _view, html} = live(conn, "/")
|
|
|
|
# Initials from test.user@example.com
|
|
assert html =~ "<span>TU</span>"
|
|
end
|
|
end
|
|
|
|
describe "profile navigation with OIDC user" do
|
|
test "shows correct profile data for OIDC user", %{conn: conn, actor: actor} do
|
|
# Setup: Create OIDC user with sub claim
|
|
user_info = %{
|
|
"sub" => "oidc_123",
|
|
"preferred_username" => "oidc.user@example.com"
|
|
}
|
|
|
|
oauth_tokens = %{
|
|
"access_token" => "test_token",
|
|
"id_token" => "test_id_token"
|
|
}
|
|
|
|
user =
|
|
Mv.Accounts.User
|
|
|> Ash.Changeset.for_create(:register_with_rauthy, %{
|
|
user_info: user_info,
|
|
oauth_tokens: oauth_tokens
|
|
})
|
|
|> Ash.create!(domain: Mv.Accounts, actor: actor)
|
|
|
|
# Assign role so user can access "/" (page permission)
|
|
admin_role = Mv.Fixtures.role_fixture("admin")
|
|
|
|
{:ok, user_with_role} =
|
|
user
|
|
|> Ash.Changeset.for_update(:update, %{})
|
|
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
|
|> Ash.update(actor: actor)
|
|
|
|
user_with_role = Ash.load!(user_with_role, :role, domain: Mv.Accounts, actor: actor)
|
|
|
|
# Login user via OIDC
|
|
conn = sign_in_user_via_oidc(conn, user_with_role)
|
|
|
|
# Navigate to home and click profile
|
|
{:ok, view, _html} = live(conn, "/")
|
|
view |> element("a", "Profil") |> render_click()
|
|
|
|
# Verify we're on the correct profile page with OIDC specific information
|
|
{:ok, _profile_view, html} = live(conn, "/users/#{user_with_role.id}")
|
|
assert html =~ to_string(user_with_role.email)
|
|
# Password auth should be disabled for OIDC users
|
|
assert html =~ "Not enabled"
|
|
end
|
|
|
|
test "profile navigation works across different authentication methods", %{
|
|
conn: conn,
|
|
actor: actor
|
|
} do
|
|
# Users need a role with page permission for "/"
|
|
password_user = Mv.Fixtures.user_with_role_fixture("admin")
|
|
|
|
# Create OIDC user and assign admin role
|
|
user_info = %{
|
|
"sub" => "oidc_789",
|
|
"preferred_username" => "oidc@example.com"
|
|
}
|
|
|
|
oauth_tokens = %{
|
|
"access_token" => "test_token",
|
|
"id_token" => "test_id_token"
|
|
}
|
|
|
|
oidc_user =
|
|
Mv.Accounts.User
|
|
|> Ash.Changeset.for_create(:register_with_rauthy, %{
|
|
user_info: user_info,
|
|
oauth_tokens: oauth_tokens
|
|
})
|
|
|> Ash.create!(domain: Mv.Accounts, actor: actor)
|
|
|
|
admin_role = Mv.Fixtures.role_fixture("admin")
|
|
|
|
{:ok, oidc_user_with_role} =
|
|
oidc_user
|
|
|> Ash.Changeset.for_update(:update, %{})
|
|
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
|
|> Ash.update(actor: actor)
|
|
|
|
oidc_user_with_role =
|
|
Ash.load!(oidc_user_with_role, :role, domain: Mv.Accounts, actor: actor)
|
|
|
|
# Test with password user
|
|
conn_password = conn_with_password_user(conn, password_user)
|
|
{:ok, view_password, _html} = live(conn_password, "/")
|
|
view_password |> element("a", "Profil") |> render_click()
|
|
assert_redirected(view_password, "/users/#{password_user.id}")
|
|
|
|
# Test with OIDC user
|
|
conn_oidc = sign_in_user_via_oidc(conn, oidc_user_with_role)
|
|
{:ok, view_oidc, _html} = live(conn_oidc, "/")
|
|
view_oidc |> element("a", "Profil") |> render_click()
|
|
assert_redirected(view_oidc, "/users/#{oidc_user_with_role.id}")
|
|
end
|
|
end
|
|
|
|
describe "authenticated views" do
|
|
# User must have a role with page permission to access /members, /users, etc.
|
|
setup %{conn: conn} do
|
|
user = Mv.Fixtures.user_with_role_fixture("admin")
|
|
conn = conn_with_password_user(conn, user)
|
|
{:ok, conn: conn, user: user}
|
|
end
|
|
|
|
@authenticated_paths [
|
|
"/",
|
|
"/members",
|
|
"/members/new",
|
|
"/users",
|
|
"/users/new"
|
|
]
|
|
|
|
for path <- @authenticated_paths do
|
|
@path path
|
|
test "layout shows user data on #{path}", %{conn: conn, user: user} do
|
|
{:ok, _view, html} = live(conn, @path)
|
|
# The navbar (which requires current_user) should be visible
|
|
assert html =~ "navbar"
|
|
# Profile button should be visible
|
|
assert html =~ "Profil"
|
|
# User ID should be in profile link
|
|
assert html =~ ~p"/users/#{user.id}"
|
|
end
|
|
end
|
|
|
|
test "layout shows user data on user profile page", %{conn: conn, user: user} do
|
|
{:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
|
|
# The sidebar (which requires current_user) should be visible
|
|
assert html =~ "sidebar"
|
|
# Profile button should be visible
|
|
assert html =~ "Profil"
|
|
# User ID should be in profile link
|
|
assert html =~ ~p"/users/#{user.id}"
|
|
end
|
|
end
|
|
end
|