Add resource policies for Group, MemberGroup, MembershipFeeType, MembershipFeeCycle

- Group/MemberGroup/MembershipFeeType/MembershipFeeCycle: HasPermission policy
- normal_user: Group and MembershipFeeCycle create/update/destroy; pages /groups/new, /groups/:slug/edit
- Add policy tests for all four resources
This commit is contained in:
Moritz 2026-02-03 23:52:12 +01:00
parent 893f9453bd
commit 5889683854
8 changed files with 1081 additions and 12 deletions

View file

@ -0,0 +1,183 @@
defmodule Mv.Membership.GroupPoliciesTest do
@moduledoc """
Tests for Group resource authorization policies.
Verifies that own_data, read_only, normal_user can read groups;
only admin can create, update, and destroy groups.
"""
use Mv.DataCase, async: false
alias Mv.Membership
alias Mv.Accounts
alias Mv.Authorization
require Ash.Query
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
%{actor: system_actor}
end
defp create_role_with_permission_set(permission_set_name, actor) do
role_name = "Test Role #{permission_set_name} #{System.unique_integer([:positive])}"
case Authorization.create_role(
%{
name: role_name,
description: "Test role for #{permission_set_name}",
permission_set_name: permission_set_name
},
actor: actor
) do
{:ok, role} -> role
{:error, error} -> raise "Failed to create role: #{inspect(error)}"
end
end
defp create_user_with_permission_set(permission_set_name, actor) do
role = create_role_with_permission_set(permission_set_name, actor)
{:ok, user} =
Accounts.User
|> Ash.Changeset.for_create(:register_with_password, %{
email: "user#{System.unique_integer([:positive])}@example.com",
password: "testpassword123"
})
|> Ash.create(actor: actor)
{:ok, user} =
user
|> Ash.Changeset.for_update(:update, %{})
|> Ash.Changeset.manage_relationship(:role, role, type: :append_and_remove)
|> Ash.update(actor: actor)
{:ok, user_with_role} = Ash.load(user, :role, domain: Mv.Accounts, actor: actor)
user_with_role
end
defp create_admin_user(actor) do
create_user_with_permission_set("admin", actor)
end
defp create_group_fixture(actor) do
admin = create_admin_user(actor)
{:ok, group} =
Membership.create_group(
%{name: "Test Group #{System.unique_integer([:positive])}", description: "Test"},
actor: admin
)
group
end
describe "own_data permission set" do
setup %{actor: actor} do
user = create_user_with_permission_set("own_data", actor)
group = create_group_fixture(actor)
%{user: user, group: group}
end
test "can read groups (list)", %{user: user} do
{:ok, groups} = Membership.list_groups(actor: user)
assert is_list(groups)
end
test "can read single group", %{user: user, group: group} do
{:ok, found} = Ash.get(Membership.Group, group.id, actor: user, domain: Mv.Membership)
assert found.id == group.id
end
end
describe "read_only permission set" do
setup %{actor: actor} do
user = create_user_with_permission_set("read_only", actor)
group = create_group_fixture(actor)
%{user: user, group: group}
end
test "can read groups (list)", %{user: user} do
{:ok, groups} = Membership.list_groups(actor: user)
assert is_list(groups)
end
test "can read single group", %{user: user, group: group} do
{:ok, found} = Ash.get(Membership.Group, group.id, actor: user, domain: Mv.Membership)
assert found.id == group.id
end
end
describe "normal_user permission set" do
setup %{actor: actor} do
user = create_user_with_permission_set("normal_user", actor)
group = create_group_fixture(actor)
%{user: user, group: group}
end
test "can read groups (list)", %{user: user} do
{:ok, groups} = Membership.list_groups(actor: user)
assert is_list(groups)
end
test "can read single group", %{user: user, group: group} do
{:ok, found} = Ash.get(Membership.Group, group.id, actor: user, domain: Mv.Membership)
assert found.id == group.id
end
test "can create group", %{user: user} do
assert {:ok, created} =
Membership.create_group(
%{name: "New Group #{System.unique_integer([:positive])}", description: "New"},
actor: user
)
assert created.name =~ "New Group"
end
test "can update group", %{user: user, group: group} do
assert {:ok, updated} =
Membership.update_group(group, %{description: "Updated"}, actor: user)
assert updated.description == "Updated"
end
test "can destroy group", %{user: user, group: group} do
assert :ok = Membership.destroy_group(group, actor: user)
end
end
describe "admin permission set" do
setup %{actor: actor} do
user = create_user_with_permission_set("admin", actor)
group = create_group_fixture(actor)
%{user: user, group: group}
end
test "can read groups (list)", %{user: user} do
{:ok, groups} = Membership.list_groups(actor: user)
assert is_list(groups)
end
test "can create group", %{user: user} do
name = "Admin Group #{System.unique_integer([:positive])}"
assert {:ok, group} =
Membership.create_group(%{name: name, description: "Admin created"}, actor: user)
assert group.name == name
end
test "can update group", %{user: user, group: group} do
assert {:ok, updated} =
Membership.update_group(group, %{description: "Updated by admin"}, actor: user)
assert updated.description == "Updated by admin"
end
test "can destroy group", %{user: user, group: group} do
assert :ok = Membership.destroy_group(group, actor: user)
assert {:error, _} = Ash.get(Membership.Group, group.id, actor: user, domain: Mv.Membership)
end
end
end