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:
parent
893f9453bd
commit
5889683854
8 changed files with 1081 additions and 12 deletions
279
test/mv/membership_fees/membership_fee_cycle_policies_test.exs
Normal file
279
test/mv/membership_fees/membership_fee_cycle_policies_test.exs
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
defmodule Mv.MembershipFees.MembershipFeeCyclePoliciesTest do
|
||||
@moduledoc """
|
||||
Tests for MembershipFeeCycle resource authorization policies.
|
||||
|
||||
Verifies read_only can only read (no update/mark_as_paid);
|
||||
normal_user and admin can read and update (including mark_as_paid);
|
||||
only admin can create and destroy.
|
||||
"""
|
||||
use Mv.DataCase, async: false
|
||||
|
||||
alias Mv.MembershipFees
|
||||
alias Mv.Membership
|
||||
alias Mv.Accounts
|
||||
alias Mv.Authorization
|
||||
|
||||
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_member_fixture(actor) do
|
||||
admin = create_admin_user(actor)
|
||||
|
||||
{:ok, member} =
|
||||
Membership.create_member(
|
||||
%{
|
||||
first_name: "Test",
|
||||
last_name: "Member",
|
||||
email: "test#{System.unique_integer([:positive])}@example.com"
|
||||
},
|
||||
actor: admin
|
||||
)
|
||||
|
||||
member
|
||||
end
|
||||
|
||||
defp create_fee_type_fixture(actor) do
|
||||
admin = create_admin_user(actor)
|
||||
|
||||
{:ok, fee_type} =
|
||||
MembershipFees.create_membership_fee_type(
|
||||
%{
|
||||
name: "Test Fee #{System.unique_integer([:positive])}",
|
||||
amount: Decimal.new("10.00"),
|
||||
interval: :yearly,
|
||||
description: "Test"
|
||||
},
|
||||
actor: admin
|
||||
)
|
||||
|
||||
fee_type
|
||||
end
|
||||
|
||||
defp create_cycle_fixture(actor) do
|
||||
admin = create_admin_user(actor)
|
||||
member = create_member_fixture(actor)
|
||||
fee_type = create_fee_type_fixture(actor)
|
||||
|
||||
{:ok, cycle} =
|
||||
MembershipFees.create_membership_fee_cycle(
|
||||
%{
|
||||
member_id: member.id,
|
||||
membership_fee_type_id: fee_type.id,
|
||||
cycle_start: Date.utc_today(),
|
||||
amount: Decimal.new("10.00"),
|
||||
status: :unpaid
|
||||
},
|
||||
actor: admin
|
||||
)
|
||||
|
||||
cycle
|
||||
end
|
||||
|
||||
describe "read_only permission set" do
|
||||
setup %{actor: actor} do
|
||||
user = create_user_with_permission_set("read_only", actor)
|
||||
cycle = create_cycle_fixture(actor)
|
||||
%{actor: actor, user: user, cycle: cycle}
|
||||
end
|
||||
|
||||
test "can read membership_fee_cycles (list)", %{user: user} do
|
||||
{:ok, list} =
|
||||
Mv.MembershipFees.MembershipFeeCycle
|
||||
|> Ash.read(actor: user, domain: Mv.MembershipFees)
|
||||
|
||||
assert is_list(list)
|
||||
end
|
||||
|
||||
test "cannot update cycle (returns forbidden)", %{user: user, cycle: cycle} do
|
||||
assert {:error, %Ash.Error.Forbidden{}} =
|
||||
MembershipFees.update_membership_fee_cycle(cycle, %{status: :paid}, actor: user)
|
||||
end
|
||||
|
||||
test "cannot mark_as_paid (returns forbidden)", %{user: user, cycle: cycle} do
|
||||
assert {:error, %Ash.Error.Forbidden{}} =
|
||||
cycle
|
||||
|> Ash.Changeset.for_update(:mark_as_paid, %{}, domain: Mv.MembershipFees)
|
||||
|> Ash.update(actor: user, domain: Mv.MembershipFees)
|
||||
end
|
||||
|
||||
test "cannot create cycle (returns forbidden)", %{user: user, actor: actor} do
|
||||
member = create_member_fixture(actor)
|
||||
fee_type = create_fee_type_fixture(actor)
|
||||
|
||||
assert {:error, %Ash.Error.Forbidden{}} =
|
||||
MembershipFees.create_membership_fee_cycle(
|
||||
%{
|
||||
member_id: member.id,
|
||||
membership_fee_type_id: fee_type.id,
|
||||
cycle_start: Date.utc_today(),
|
||||
amount: Decimal.new("10.00"),
|
||||
status: :unpaid
|
||||
},
|
||||
actor: user
|
||||
)
|
||||
end
|
||||
|
||||
test "cannot destroy cycle (returns forbidden)", %{user: user, cycle: cycle} do
|
||||
assert {:error, %Ash.Error.Forbidden{}} =
|
||||
MembershipFees.destroy_membership_fee_cycle(cycle, actor: user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "normal_user permission set" do
|
||||
setup %{actor: actor} do
|
||||
user = create_user_with_permission_set("normal_user", actor)
|
||||
cycle = create_cycle_fixture(actor)
|
||||
%{actor: actor, user: user, cycle: cycle}
|
||||
end
|
||||
|
||||
test "can read membership_fee_cycles (list)", %{user: user} do
|
||||
{:ok, list} =
|
||||
Mv.MembershipFees.MembershipFeeCycle
|
||||
|> Ash.read(actor: user, domain: Mv.MembershipFees)
|
||||
|
||||
assert is_list(list)
|
||||
end
|
||||
|
||||
test "can update cycle status", %{user: user, cycle: cycle} do
|
||||
assert {:ok, updated} =
|
||||
MembershipFees.update_membership_fee_cycle(cycle, %{status: :paid}, actor: user)
|
||||
|
||||
assert updated.status == :paid
|
||||
end
|
||||
|
||||
test "can mark_as_paid", %{user: user, cycle: cycle} do
|
||||
assert {:ok, updated} =
|
||||
cycle
|
||||
|> Ash.Changeset.for_update(:mark_as_paid, %{}, domain: Mv.MembershipFees)
|
||||
|> Ash.update(actor: user, domain: Mv.MembershipFees)
|
||||
|
||||
assert updated.status == :paid
|
||||
end
|
||||
|
||||
test "can create cycle", %{user: user, actor: actor} do
|
||||
member = create_member_fixture(actor)
|
||||
fee_type = create_fee_type_fixture(actor)
|
||||
|
||||
assert {:ok, created} =
|
||||
MembershipFees.create_membership_fee_cycle(
|
||||
%{
|
||||
member_id: member.id,
|
||||
membership_fee_type_id: fee_type.id,
|
||||
cycle_start: Date.utc_today(),
|
||||
amount: Decimal.new("10.00"),
|
||||
status: :unpaid
|
||||
},
|
||||
actor: user
|
||||
)
|
||||
|
||||
assert created.member_id == member.id
|
||||
end
|
||||
|
||||
test "can destroy cycle", %{user: user, cycle: cycle} do
|
||||
assert :ok = MembershipFees.destroy_membership_fee_cycle(cycle, actor: user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "admin permission set" do
|
||||
setup %{actor: actor} do
|
||||
user = create_user_with_permission_set("admin", actor)
|
||||
cycle = create_cycle_fixture(actor)
|
||||
%{actor: actor, user: user, cycle: cycle}
|
||||
end
|
||||
|
||||
test "can read membership_fee_cycles (list)", %{user: user} do
|
||||
{:ok, list} =
|
||||
Mv.MembershipFees.MembershipFeeCycle
|
||||
|> Ash.read(actor: user, domain: Mv.MembershipFees)
|
||||
|
||||
assert is_list(list)
|
||||
end
|
||||
|
||||
test "can update cycle", %{user: user, cycle: cycle} do
|
||||
assert {:ok, updated} =
|
||||
MembershipFees.update_membership_fee_cycle(cycle, %{status: :paid}, actor: user)
|
||||
|
||||
assert updated.status == :paid
|
||||
end
|
||||
|
||||
test "can mark_as_paid", %{user: user, cycle: cycle} do
|
||||
cycle_unpaid =
|
||||
cycle
|
||||
|> Ash.Changeset.for_update(:mark_as_unpaid, %{}, domain: Mv.MembershipFees)
|
||||
|> Ash.update!(actor: user, domain: Mv.MembershipFees)
|
||||
|
||||
assert {:ok, updated} =
|
||||
cycle_unpaid
|
||||
|> Ash.Changeset.for_update(:mark_as_paid, %{}, domain: Mv.MembershipFees)
|
||||
|> Ash.update(actor: user, domain: Mv.MembershipFees)
|
||||
|
||||
assert updated.status == :paid
|
||||
end
|
||||
|
||||
test "can create cycle", %{user: user, actor: actor} do
|
||||
member = create_member_fixture(actor)
|
||||
fee_type = create_fee_type_fixture(actor)
|
||||
|
||||
assert {:ok, created} =
|
||||
MembershipFees.create_membership_fee_cycle(
|
||||
%{
|
||||
member_id: member.id,
|
||||
membership_fee_type_id: fee_type.id,
|
||||
cycle_start: Date.utc_today(),
|
||||
amount: Decimal.new("10.00"),
|
||||
status: :unpaid
|
||||
},
|
||||
actor: user
|
||||
)
|
||||
|
||||
assert created.member_id == member.id
|
||||
end
|
||||
|
||||
test "can destroy cycle", %{user: user, cycle: cycle} do
|
||||
assert :ok = MembershipFees.destroy_membership_fee_cycle(cycle, actor: user)
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue