Add CustomFieldValueCreateScope check for create actions
Ash cannot apply filters to create; this check enforces :linked/:all scope via strict_check only (no filter).
This commit is contained in:
parent
b93b419246
commit
80efa5b3bd
1 changed files with 64 additions and 0 deletions
|
|
@ -0,0 +1,64 @@
|
|||
defmodule Mv.Authorization.Checks.CustomFieldValueCreateScope do
|
||||
@moduledoc """
|
||||
Policy check for CustomFieldValue create actions only.
|
||||
|
||||
Use this for create instead of HasPermission because Ash cannot apply
|
||||
filters to create actions ("Cannot use a filter to authorize a create").
|
||||
This check performs the same scope logic as HasPermission for create
|
||||
(PermissionSets + :linked/:all) but only implements strict_check, so it
|
||||
never adds a filter.
|
||||
|
||||
Used in CustomFieldValue policies:
|
||||
policy action_type(:create) do
|
||||
authorize_if Mv.Authorization.Checks.CustomFieldValueCreateScope
|
||||
end
|
||||
"""
|
||||
use Ash.Policy.Check
|
||||
alias Mv.Authorization.PermissionSets
|
||||
require Logger
|
||||
|
||||
@impl true
|
||||
def describe(_opts),
|
||||
do: "CustomFieldValue create allowed by permission set scope (:linked or :all)"
|
||||
|
||||
@impl true
|
||||
def strict_check(actor, authorizer, _opts) do
|
||||
actor = ensure_role_loaded(actor)
|
||||
|
||||
with %{role: %{permission_set_name: ps_name}} when not is_nil(ps_name) <- actor,
|
||||
{:ok, ps_atom} <- PermissionSets.permission_set_name_to_atom(ps_name),
|
||||
permissions <- PermissionSets.get_permissions(ps_atom),
|
||||
perm <- find_custom_field_value_create(permissions.resources) do
|
||||
case perm do
|
||||
nil -> {:ok, false}
|
||||
%{scope: :all} -> {:ok, true}
|
||||
%{scope: :linked} -> {:ok, member_id_matches?(authorizer, actor)}
|
||||
end
|
||||
else
|
||||
_ -> {:ok, false}
|
||||
end
|
||||
end
|
||||
|
||||
defp find_custom_field_value_create(resources) do
|
||||
Enum.find(resources, fn p ->
|
||||
p.resource == "CustomFieldValue" and p.action == :create and p.granted
|
||||
end)
|
||||
end
|
||||
|
||||
defp member_id_matches?(authorizer, actor) do
|
||||
member_id = get_create_member_id(authorizer)
|
||||
!is_nil(member_id) and member_id == actor.member_id
|
||||
end
|
||||
|
||||
defp get_create_member_id(authorizer) do
|
||||
changeset = authorizer.changeset || authorizer.subject
|
||||
|
||||
if changeset && function_exported?(Ash.Changeset, :get_attribute, 2) do
|
||||
Ash.Changeset.get_attribute(changeset, :member_id)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
defp ensure_role_loaded(actor), do: Mv.Authorization.Actor.ensure_loaded(actor)
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue