CustomField policies: actor required, no system-actor fallback, error handling
- list_required_custom_fields: require actor (two clauses, no default) - Member validation: use context.actor only, differentiate Forbidden vs transient errors - stream_custom_fields: log + send flash on error instead of returning [] - GlobalSettingsLive: handle_info for custom_fields_load_error, put_flash - Seeds: use Membership.update_member with actor, format
This commit is contained in:
parent
c9431caabe
commit
5a2f035ecc
5 changed files with 67 additions and 19 deletions
|
|
@ -486,6 +486,24 @@ defmodule Mv.Membership.Member do
|
|||
build_custom_field_validation_error(missing_fields)
|
||||
end
|
||||
|
||||
{:error, %Ash.Error.Forbidden{}} ->
|
||||
Logger.warning(
|
||||
"Required custom fields validation: actor not authorized to read CustomField"
|
||||
)
|
||||
|
||||
{:error,
|
||||
field: :custom_field_values,
|
||||
message:
|
||||
"You are not authorized to perform this action. Please sign in again or contact support."}
|
||||
|
||||
{:error, :missing_actor} ->
|
||||
Logger.warning("Required custom fields validation: no actor in context")
|
||||
|
||||
{:error,
|
||||
field: :custom_field_values,
|
||||
message:
|
||||
"You are not authorized to perform this action. Please sign in again or contact support."}
|
||||
|
||||
{:error, error} ->
|
||||
Logger.error(
|
||||
"Failed to load custom fields for validation: #{inspect(error)}. Required field validation cannot be performed."
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ defmodule Mv.Membership do
|
|||
The domain exposes these main actions:
|
||||
- Member CRUD: `create_member/1`, `list_members/0`, `update_member/2`, `destroy_member/1`
|
||||
- Custom field value management: `create_custom_field_value/1`, `list_custom_field_values/0`, etc.
|
||||
- Custom field management: `create_custom_field/1`, `list_custom_fields/0`, `list_required_custom_fields/0`, etc.
|
||||
- Custom field management: `create_custom_field/1`, `list_custom_fields/0`, `list_required_custom_fields/1`, etc.
|
||||
- Settings management: `get_settings/0`, `update_settings/2`, `update_member_field_visibility/2`, `update_single_member_field_visibility/3`
|
||||
- Group management: `create_group/1`, `list_groups/0`, `update_group/2`, `destroy_group/1`
|
||||
- Member-group associations: `create_member_group/1`, `list_member_groups/0`, `destroy_member_group/1`
|
||||
|
|
@ -156,7 +156,7 @@ defmodule Mv.Membership do
|
|||
|
||||
This is an optimized version that filters at the database level instead of
|
||||
loading all custom fields and filtering in memory. Requires an actor for
|
||||
authorization (CustomField read policy).
|
||||
authorization (CustomField read policy). Callers must pass `actor:`; no default.
|
||||
|
||||
## Options
|
||||
|
||||
|
|
@ -166,22 +166,26 @@ defmodule Mv.Membership do
|
|||
## Returns
|
||||
|
||||
- `{:ok, required_custom_fields}` - List of required custom fields
|
||||
- `{:error, error}` - Error reading custom fields (e.g. Forbidden when no actor)
|
||||
- `{:error, :missing_actor}` - When actor is nil (caller must pass actor)
|
||||
- `{:error, error}` - Error reading custom fields (e.g. Forbidden)
|
||||
|
||||
## Examples
|
||||
|
||||
iex> {:ok, required_fields} = Mv.Membership.list_required_custom_fields(actor: actor)
|
||||
iex> Enum.all?(required_fields, & &1.required)
|
||||
true
|
||||
"""
|
||||
def list_required_custom_fields(opts \\ []) do
|
||||
actor = Keyword.get(opts, :actor)
|
||||
|
||||
iex> Mv.Membership.list_required_custom_fields(actor: nil)
|
||||
{:error, :missing_actor}
|
||||
"""
|
||||
def list_required_custom_fields(actor: actor) when not is_nil(actor) do
|
||||
Mv.Membership.CustomField
|
||||
|> Ash.Query.filter(expr(required == true))
|
||||
|> Ash.read(domain: __MODULE__, actor: actor)
|
||||
end
|
||||
|
||||
def list_required_custom_fields(actor: nil), do: {:error, :missing_actor}
|
||||
|
||||
@doc """
|
||||
Updates the member field visibility configuration.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue