Member Resource Policies closes #345 #346

Merged
moritz merged 33 commits from feature/345_member_policies_2 into main 2026-01-13 16:36:24 +01:00
2 changed files with 61 additions and 0 deletions
Showing only changes of commit 555ae15173 - Show all commits

27
lib/mv/helpers.ex Normal file
View file

@ -0,0 +1,27 @@
defmodule Mv.Helpers do
@moduledoc """
Shared helper functions used across the Mv application.
Provides utilities that are not specific to a single domain or layer.
"""
@doc """
Converts an actor to Ash options list for authorization.
Returns empty list if actor is nil.
This helper ensures consistent actor handling across all Ash operations
in the application, whether called from LiveViews, changes, validations,
or other contexts.
## Examples
opts = ash_actor_opts(actor)
Ash.read(query, opts)
opts = ash_actor_opts(nil)
# => []
"""
@spec ash_actor_opts(Mv.Accounts.User.t() | nil) :: keyword()
def ash_actor_opts(nil), do: []
def ash_actor_opts(actor) when not is_nil(actor), do: [actor: actor]
end

View file

@ -71,7 +71,41 @@ defmodule MvWeb.LiveHelpers do
actor = current_actor(socket)
members = Membership.list_members!(actor: actor)
"""
@spec current_actor(Phoenix.LiveView.Socket.t()) :: Mv.Accounts.User.t() | nil
def current_actor(socket) do
socket.assigns[:current_user] || socket.assigns.current_user
end
@doc """
Converts an actor to Ash options list for authorization.
Returns empty list if actor is nil.
Delegates to `Mv.Helpers.ash_actor_opts/1` for consistency across the application.
## Examples
opts = ash_actor_opts(actor)
Ash.read(query, opts)
"""
@spec ash_actor_opts(Mv.Accounts.User.t() | nil) :: keyword()
defdelegate ash_actor_opts(actor), to: Mv.Helpers
@doc """
Submits an AshPhoenix form with consistent actor handling.
This wrapper ensures that actor is always passed via `action_opts`
in a consistent manner across all LiveViews.
## Examples
case submit_form(form, params, actor) do
{:ok, resource} -> # success
{:error, form} -> # validation errors
end
"""
@spec submit_form(AshPhoenix.Form.t(), map(), Mv.Accounts.User.t() | nil) ::
{:ok, Ash.Resource.t()} | {:error, AshPhoenix.Form.t()}
def submit_form(form, params, actor) do
AshPhoenix.Form.submit(form, params: params, action_opts: ash_actor_opts(actor))
end
end