From 503401f2e65343d32ab7d50383999099b91846a8 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 4 Feb 2026 11:40:19 +0100 Subject: [PATCH] Setting: remove unused actor in default_fee_type validation - Docs: Regenerate Cycles server-side enforcement note in membership-fee-architecture. --- docs/membership-fee-architecture.md | 2 +- lib/membership/setting.ex | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/docs/membership-fee-architecture.md b/docs/membership-fee-architecture.md index fa82be3..6c81169 100644 --- a/docs/membership-fee-architecture.md +++ b/docs/membership-fee-architecture.md @@ -340,7 +340,7 @@ lib/ - **MembershipFeeType:** All permission sets can read (:all); only admin has create/update/destroy (:all). - **MembershipFeeCycle:** All can read (:all); read_only has read only; normal_user and admin have read + create + update + destroy (:all). -- **Manual "Regenerate Cycles" (UI):** The "Regenerate Cycles" button in the member detail view is shown to users who have MembershipFeeCycle create permission (normal_user and admin). Regeneration runs with system actor; UI access is gated by `can_create_cycle`. +- **Manual "Regenerate Cycles" (UI + server):** The "Regenerate Cycles" button in the member detail view is shown to users who have MembershipFeeCycle create permission (normal_user and admin). UI access is gated by `can_create_cycle`. The LiveView handler also enforces `can?(:create, MembershipFeeCycle)` server-side before running regeneration (so e.g. a read_only user cannot trigger it via DevTools). Regeneration runs with system actor. **Resource Policies:** diff --git a/lib/membership/setting.ex b/lib/membership/setting.ex index 862f4ac..bb7d122 100644 --- a/lib/membership/setting.ex +++ b/lib/membership/setting.ex @@ -160,14 +160,6 @@ defmodule Mv.Membership.Setting do Ash.Changeset.get_attribute(changeset, :default_membership_fee_type_id) if fee_type_id do - # Actor may be in changeset.context (action context) or validation context - ctx = changeset.context || %{} - - actor = - get_in(ctx, [:private, :actor]) || - Map.get(ctx, :actor) || - (context && Map.get(context, :actor)) - # Check existence only; action is already restricted by policy (e.g. admin). opts = [domain: Mv.MembershipFees, authorize?: false]