defmodule Mv.Authorization.RolePoliciesTest do @moduledoc """ Tests for Role resource authorization policies. Rule: All permission sets (own_data, read_only, normal_user, admin) can **read** roles. Only **admin** can create, update, or destroy roles. """ use Mv.DataCase, async: false alias Mv.Authorization alias Mv.Authorization.Role describe "read access - all permission sets can read roles" do setup do # Create a role to read (via system_actor; once policies exist, system_actor is admin) role = Mv.Fixtures.role_fixture("read_only") %{role: role} end @tag :permission_set_own_data test "own_data can list roles", %{role: _role} do user = Mv.Fixtures.user_with_role_fixture("own_data") user = Mv.Authorization.Actor.ensure_loaded(user) {:ok, roles} = Authorization.list_roles(actor: user) assert is_list(roles) assert roles != [] end @tag :permission_set_own_data test "own_data can get role by id", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("own_data") user = Mv.Authorization.Actor.ensure_loaded(user) {:ok, loaded} = Ash.get(Role, role.id, actor: user, domain: Mv.Authorization) assert loaded.id == role.id end @tag :permission_set_read_only test "read_only can list roles", %{role: _role} do user = Mv.Fixtures.user_with_role_fixture("read_only") user = Mv.Authorization.Actor.ensure_loaded(user) {:ok, roles} = Authorization.list_roles(actor: user) assert is_list(roles) assert roles != [] end @tag :permission_set_read_only test "read_only can get role by id", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("read_only") user = Mv.Authorization.Actor.ensure_loaded(user) {:ok, loaded} = Ash.get(Role, role.id, actor: user, domain: Mv.Authorization) assert loaded.id == role.id end @tag :permission_set_normal_user test "normal_user can list roles", %{role: _role} do user = Mv.Fixtures.user_with_role_fixture("normal_user") user = Mv.Authorization.Actor.ensure_loaded(user) {:ok, roles} = Authorization.list_roles(actor: user) assert is_list(roles) assert roles != [] end @tag :permission_set_normal_user test "normal_user can get role by id", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("normal_user") user = Mv.Authorization.Actor.ensure_loaded(user) {:ok, loaded} = Ash.get(Role, role.id, actor: user, domain: Mv.Authorization) assert loaded.id == role.id end @tag :permission_set_admin test "admin can list roles", %{role: _role} do admin = Mv.Fixtures.user_with_role_fixture("admin") admin = Mv.Authorization.Actor.ensure_loaded(admin) {:ok, roles} = Authorization.list_roles(actor: admin) assert is_list(roles) assert roles != [] end @tag :permission_set_admin test "admin can get role by id", %{role: role} do admin = Mv.Fixtures.user_with_role_fixture("admin") admin = Mv.Authorization.Actor.ensure_loaded(admin) {:ok, loaded} = Ash.get(Role, role.id, actor: admin, domain: Mv.Authorization) assert loaded.id == role.id end end describe "create/update/destroy - only admin allowed" do setup do # Non-system role for destroy test (role_fixture creates non-system roles) role = Mv.Fixtures.role_fixture("normal_user") %{role: role} end test "admin can create_role", %{role: _role} do admin = Mv.Fixtures.user_with_role_fixture("admin") admin = Mv.Authorization.Actor.ensure_loaded(admin) attrs = %{ name: "New Role #{System.unique_integer([:positive])}", description: "Test", permission_set_name: "read_only" } assert {:ok, _created} = Authorization.create_role(attrs, actor: admin) end test "admin can update_role", %{role: role} do admin = Mv.Fixtures.user_with_role_fixture("admin") admin = Mv.Authorization.Actor.ensure_loaded(admin) assert {:ok, updated} = Authorization.update_role(role, %{description: "Updated by admin"}, actor: admin) assert updated.description == "Updated by admin" end test "admin can destroy non-system role", %{role: role} do admin = Mv.Fixtures.user_with_role_fixture("admin") admin = Mv.Authorization.Actor.ensure_loaded(admin) assert :ok = Authorization.destroy_role(role, actor: admin) end test "own_data cannot create_role (forbidden)", %{role: _role} do user = Mv.Fixtures.user_with_role_fixture("own_data") user = Mv.Authorization.Actor.ensure_loaded(user) attrs = %{ name: "New Role #{System.unique_integer([:positive])}", description: "Test", permission_set_name: "read_only" } assert {:error, %Ash.Error.Forbidden{}} = Authorization.create_role(attrs, actor: user) end test "own_data cannot update_role (forbidden)", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("own_data") user = Mv.Authorization.Actor.ensure_loaded(user) assert {:error, %Ash.Error.Forbidden{}} = Authorization.update_role(role, %{description: "Updated"}, actor: user) end test "own_data cannot destroy_role (forbidden)", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("own_data") user = Mv.Authorization.Actor.ensure_loaded(user) assert {:error, %Ash.Error.Forbidden{}} = Authorization.destroy_role(role, actor: user) end test "read_only cannot create_role (forbidden)", %{role: _role} do user = Mv.Fixtures.user_with_role_fixture("read_only") user = Mv.Authorization.Actor.ensure_loaded(user) attrs = %{ name: "New Role #{System.unique_integer([:positive])}", description: "Test", permission_set_name: "read_only" } assert {:error, %Ash.Error.Forbidden{}} = Authorization.create_role(attrs, actor: user) end test "read_only cannot update_role (forbidden)", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("read_only") user = Mv.Authorization.Actor.ensure_loaded(user) assert {:error, %Ash.Error.Forbidden{}} = Authorization.update_role(role, %{description: "Updated"}, actor: user) end test "read_only cannot destroy_role (forbidden)", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("read_only") user = Mv.Authorization.Actor.ensure_loaded(user) assert {:error, %Ash.Error.Forbidden{}} = Authorization.destroy_role(role, actor: user) end test "normal_user cannot create_role (forbidden)", %{role: _role} do user = Mv.Fixtures.user_with_role_fixture("normal_user") user = Mv.Authorization.Actor.ensure_loaded(user) attrs = %{ name: "New Role #{System.unique_integer([:positive])}", description: "Test", permission_set_name: "normal_user" } assert {:error, %Ash.Error.Forbidden{}} = Authorization.create_role(attrs, actor: user) end test "normal_user cannot update_role (forbidden)", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("normal_user") user = Mv.Authorization.Actor.ensure_loaded(user) assert {:error, %Ash.Error.Forbidden{}} = Authorization.update_role(role, %{description: "Updated"}, actor: user) end test "normal_user cannot destroy_role (forbidden)", %{role: role} do user = Mv.Fixtures.user_with_role_fixture("normal_user") user = Mv.Authorization.Actor.ensure_loaded(user) assert {:error, %Ash.Error.Forbidden{}} = Authorization.destroy_role(role, actor: user) end end end