mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 13:33:20 +12:00
chore: add some defensive coding for policies
This commit is contained in:
parent
d7c8cdd1eb
commit
e9d2d8c575
2 changed files with 64 additions and 64 deletions
|
@ -144,6 +144,7 @@ defmodule Ash.Error.Forbidden.Policy do
|
||||||
|
|
||||||
policy_explanation =
|
policy_explanation =
|
||||||
policies
|
policies
|
||||||
|
|> Kernel.||([])
|
||||||
|> Enum.filter(&relevant?(&1, facts))
|
|> Enum.filter(&relevant?(&1, facts))
|
||||||
|> Enum.map(&explain_policy(&1, facts, opts[:success?] || false))
|
|> Enum.map(&explain_policy(&1, facts, opts[:success?] || false))
|
||||||
|> Enum.intersperse("\n")
|
|> Enum.intersperse("\n")
|
||||||
|
|
|
@ -722,13 +722,10 @@ defmodule Ash.Policy.Authorizer do
|
||||||
)
|
)
|
||||||
when struct in [Ash.Resource.Attribute, Ash.Resource.Aggregate, Ash.Resource.Calculation] do
|
when struct in [Ash.Resource.Attribute, Ash.Resource.Aggregate, Ash.Resource.Calculation] do
|
||||||
action =
|
action =
|
||||||
Ash.Resource.Info.relationship(parent, relationship_path).read_action ||
|
Map.get(Ash.Resource.Info.relationship(parent, relationship_path) || %{}, :relationship) ||
|
||||||
Ash.Resource.Info.primary_action!(resource, :read)
|
Ash.Resource.Info.primary_action!(resource, :read)
|
||||||
|
|
||||||
{expr, acc} =
|
expression_for_ref(resource, name, action, ref, acc)
|
||||||
expression_for_ref(resource, name, action, ref, acc)
|
|
||||||
|
|
||||||
{expr, acc}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_replace_ref(
|
defp do_replace_ref(
|
||||||
|
@ -736,9 +733,7 @@ defmodule Ash.Policy.Authorizer do
|
||||||
%{stack: [{resource, _path, action} | _]} = acc
|
%{stack: [{resource, _path, action} | _]} = acc
|
||||||
)
|
)
|
||||||
when struct in [Ash.Resource.Attribute, Ash.Resource.Aggregate, Ash.Resource.Calculation] do
|
when struct in [Ash.Resource.Attribute, Ash.Resource.Aggregate, Ash.Resource.Calculation] do
|
||||||
{expr, acc} = expression_for_ref(resource, name, action, ref, acc)
|
expression_for_ref(resource, name, action, ref, acc)
|
||||||
|
|
||||||
{expr, acc}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_replace_ref(ref, acc) do
|
defp do_replace_ref(ref, acc) do
|
||||||
|
@ -783,67 +778,71 @@ defmodule Ash.Policy.Authorizer do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp field_condition(resource, field, action, acc) do
|
defp field_condition(resource, field, action, acc) do
|
||||||
{authorizer, acc} =
|
if Ash.Policy.Authorizer in Ash.Resource.Info.authorizers(resource) do
|
||||||
case Map.fetch(acc.authorizers, {resource, action}) do
|
{authorizer, acc} =
|
||||||
{:ok, authorizer} ->
|
case Map.fetch(acc.authorizers, {resource, action}) do
|
||||||
{authorizer, acc}
|
{:ok, authorizer} ->
|
||||||
|
{authorizer, acc}
|
||||||
|
|
||||||
:error ->
|
:error ->
|
||||||
authorizer = initial_state(acc.actor, resource, action, acc.verbose?)
|
authorizer = initial_state(acc.actor, resource, action, acc.verbose?)
|
||||||
|
|
||||||
{authorizer,
|
{authorizer,
|
||||||
%{acc | authorizers: Map.put(acc.authorizers, {resource, action}, authorizer)}}
|
%{acc | authorizers: Map.put(acc.authorizers, {resource, action}, authorizer)}}
|
||||||
end
|
|
||||||
|
|
||||||
{expr, authorizer} =
|
|
||||||
if field in Ash.Resource.Info.primary_key(resource) do
|
|
||||||
# primary keys are always accessible
|
|
||||||
{true, authorizer}
|
|
||||||
else
|
|
||||||
policies = Ash.Policy.Info.field_policies_for_field(resource, field)
|
|
||||||
|
|
||||||
case strict_check_result(
|
|
||||||
%{
|
|
||||||
authorizer
|
|
||||||
| policies: policies
|
|
||||||
},
|
|
||||||
for_fields: [field],
|
|
||||||
context_description: "accessing field in filter"
|
|
||||||
) do
|
|
||||||
{:authorized, authorizer} ->
|
|
||||||
{true, authorizer}
|
|
||||||
|
|
||||||
{:error, _} ->
|
|
||||||
{false, authorizer}
|
|
||||||
|
|
||||||
{:filter, authorizer, filter} ->
|
|
||||||
{filter, authorizer}
|
|
||||||
|
|
||||||
{:filter_and_continue, filter, _authorizer} ->
|
|
||||||
raise """
|
|
||||||
Was given a partial filter for a field policy for field #{inspect(field)}.
|
|
||||||
|
|
||||||
Filter: #{inspect(filter)}
|
|
||||||
|
|
||||||
Field policies must currently use only filter checks or simple checks.
|
|
||||||
"""
|
|
||||||
|
|
||||||
{:continue, _} ->
|
|
||||||
raise """
|
|
||||||
Detected necessity for a runtime check for a field policy for field #{inspect(field)}.
|
|
||||||
|
|
||||||
Field policies must currently use only filter checks or simple checks.
|
|
||||||
"""
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
{expr, authorizer} =
|
||||||
|
if field in Ash.Resource.Info.primary_key(resource) do
|
||||||
|
# primary keys are always accessible
|
||||||
|
{true, authorizer}
|
||||||
|
else
|
||||||
|
policies = Ash.Policy.Info.field_policies_for_field(resource, field)
|
||||||
|
|
||||||
|
case strict_check_result(
|
||||||
|
%{
|
||||||
|
authorizer
|
||||||
|
| policies: policies
|
||||||
|
},
|
||||||
|
for_fields: [field],
|
||||||
|
context_description: "accessing field in filter"
|
||||||
|
) do
|
||||||
|
{:authorized, authorizer} ->
|
||||||
|
{true, authorizer}
|
||||||
|
|
||||||
|
{:error, _} ->
|
||||||
|
{false, authorizer}
|
||||||
|
|
||||||
|
{:filter, authorizer, filter} ->
|
||||||
|
{filter, authorizer}
|
||||||
|
|
||||||
|
{:filter_and_continue, filter, _authorizer} ->
|
||||||
|
raise """
|
||||||
|
Was given a partial filter for a field policy for field #{inspect(field)}.
|
||||||
|
|
||||||
|
Filter: #{inspect(filter)}
|
||||||
|
|
||||||
|
Field policies must currently use only filter checks or simple checks.
|
||||||
|
"""
|
||||||
|
|
||||||
|
{:continue, _} ->
|
||||||
|
raise """
|
||||||
|
Detected necessity for a runtime check for a field policy for field #{inspect(field)}.
|
||||||
|
|
||||||
|
Field policies must currently use only filter checks or simple checks.
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
new_acc = %{acc | authorizers: Map.put(acc.authorizers, {resource, action}, authorizer)}
|
||||||
|
|
||||||
|
if expr == true do
|
||||||
|
{:none, new_acc}
|
||||||
|
else
|
||||||
|
{:expr, expr,
|
||||||
|
%{acc | authorizers: Map.put(acc.authorizers, {resource, action}, authorizer)}}
|
||||||
end
|
end
|
||||||
|
|
||||||
new_acc = %{acc | authorizers: Map.put(acc.authorizers, {resource, action}, authorizer)}
|
|
||||||
|
|
||||||
if expr == true do
|
|
||||||
{:none, new_acc}
|
|
||||||
else
|
else
|
||||||
{:expr, expr,
|
{:none, acc}
|
||||||
%{acc | authorizers: Map.put(acc.authorizers, {resource, action}, authorizer)}}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue