From a834bdc4ffc281593bf623222e9cf163616b9b4b Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 22 Jan 2026 21:36:18 +0100 Subject: [PATCH] Add PolicyHelpers macro for standard user policies Encapsulate two-tier policy pattern (bypass + HasPermission). Promote consistency across resource policy definitions. --- lib/mv/authorization/policy_helpers.ex | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 lib/mv/authorization/policy_helpers.ex diff --git a/lib/mv/authorization/policy_helpers.ex b/lib/mv/authorization/policy_helpers.ex new file mode 100644 index 0000000..f61ecb7 --- /dev/null +++ b/lib/mv/authorization/policy_helpers.ex @@ -0,0 +1,40 @@ +defmodule Mv.Authorization.PolicyHelpers do + @moduledoc """ + Policy helpers for consistent bypass vs HasPermission patterns. + + ## Pattern: READ Bypass + UPDATE HasPermission + + For resources with scope :own/:linked permissions: + - READ: Use bypass with expr() for auto_filter + - UPDATE/CREATE/DESTROY: Use HasPermission for scope evaluation + + ## Usage + + use Mv.Authorization.PolicyHelpers + + policies do + # Standard pattern for User resource + standard_user_policies() + end + + ## Why This Pattern? + + See `docs/policy-bypass-vs-haspermission.md` for detailed explanation. + """ + + defmacro standard_user_policies do + quote do + # READ: Bypass for auto_filter + bypass action_type(:read) do + description "Users can read their own records" + authorize_if expr(id == ^actor(:id)) + end + + # UPDATE/CREATE/DESTROY: HasPermission + policy action_type([:update, :create, :destroy]) do + description "Check permissions from role" + authorize_if Mv.Authorization.Checks.HasPermission + end + end + end +end