mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
fix: don't attempt to re-authorize access to already retrieved records in Api.load/2
improvement: show conditions in policy breakdowns
This commit is contained in:
parent
8092cd899a
commit
d1f05b6c42
5 changed files with 118 additions and 24 deletions
|
@ -236,6 +236,13 @@ defmodule Ash.Actions.Read do
|
|||
fn %{authorize?: authorize?, actor: actor} = context ->
|
||||
query_opts = query_opts(request_opts, context)
|
||||
|
||||
authorize? =
|
||||
if Keyword.has_key?(request_opts, :initial_data) do
|
||||
request_opts[:authorize?]
|
||||
else
|
||||
authorize?
|
||||
end
|
||||
|
||||
input = query_input.(context) || %{}
|
||||
|
||||
tenant =
|
||||
|
@ -345,7 +352,7 @@ defmodule Ash.Actions.Read do
|
|||
end
|
||||
end
|
||||
),
|
||||
authorize?: true,
|
||||
authorize?: !Keyword.has_key?(request_opts, :initial_data),
|
||||
data: data_field(request_opts, path),
|
||||
path: path ++ [:fetch],
|
||||
async?: !Keyword.has_key?(request_opts, :initial_data),
|
||||
|
|
|
@ -158,6 +158,9 @@ defmodule Ash.Error.Forbidden.Policy do
|
|||
""
|
||||
end
|
||||
|
||||
{condition_description, applies} = describe_conditions(policy.condition, facts)
|
||||
|
||||
if applies == true do
|
||||
{description, state} = describe_checks(policy.policies, facts)
|
||||
|
||||
tag =
|
||||
|
@ -172,13 +175,87 @@ defmodule Ash.Error.Forbidden.Policy do
|
|||
"⛔"
|
||||
end
|
||||
|
||||
title(Enum.map(description, &[" ", &1]), [
|
||||
title(
|
||||
[Enum.map(condition_description, &[" ", &1]), Enum.map(description, &[" ", &1])],
|
||||
[
|
||||
" ",
|
||||
bypass,
|
||||
policy.description || "Policy",
|
||||
" | ",
|
||||
tag
|
||||
])
|
||||
]
|
||||
)
|
||||
else
|
||||
tag =
|
||||
if applies == false do
|
||||
"⬇️"
|
||||
else
|
||||
"?"
|
||||
end
|
||||
|
||||
title(
|
||||
Enum.map(condition_description, &[" ", &1]),
|
||||
[" ", bypass, policy.description || "Policy", " | ", tag]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
defp describe_conditions(condition, facts) do
|
||||
condition
|
||||
|> List.wrap()
|
||||
|> case do
|
||||
[{Ash.Policy.Check.Static, opts}] ->
|
||||
{[], opts[:result]}
|
||||
|
||||
conditions ->
|
||||
conditions
|
||||
|> Enum.reduce({[], true}, fn condition, {conditions, status} ->
|
||||
{mod, opts} =
|
||||
case condition do
|
||||
%{module: module, opts: opts} ->
|
||||
{module, opts}
|
||||
|
||||
{module, opts} ->
|
||||
{module, opts}
|
||||
end
|
||||
|
||||
new_status =
|
||||
if status in [false, :unknown] do
|
||||
false
|
||||
else
|
||||
case Policy.fetch_fact(facts, {mod, opts}) do
|
||||
{:ok, true} ->
|
||||
true
|
||||
|
||||
{:ok, false} ->
|
||||
false
|
||||
|
||||
_ ->
|
||||
:unknown
|
||||
end
|
||||
end
|
||||
|
||||
{[["condition: ", mod.describe(opts)] | conditions], new_status}
|
||||
end)
|
||||
|> then(fn {conditions, status} ->
|
||||
conditions =
|
||||
conditions
|
||||
|> Enum.reverse()
|
||||
|> case do
|
||||
[] ->
|
||||
[]
|
||||
|
||||
conditions ->
|
||||
[
|
||||
conditions
|
||||
|> Enum.intersperse("\n"),
|
||||
"\n"
|
||||
]
|
||||
end
|
||||
|
||||
{conditions, status}
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
defp describe_checks(checks, facts) do
|
||||
|
|
|
@ -947,10 +947,12 @@ defmodule Ash.Filter do
|
|||
resource: query.resource,
|
||||
api: api,
|
||||
query:
|
||||
Ash.Query.set_context(query, %{
|
||||
query
|
||||
|> Ash.Query.set_context(%{
|
||||
filter_only?: true,
|
||||
filter_references: refs[path] || []
|
||||
}),
|
||||
})
|
||||
|> Ash.Query.select([]),
|
||||
async?: false,
|
||||
path: request_path ++ [:filter, path],
|
||||
strict_check_only?: true,
|
||||
|
|
|
@ -97,4 +97,16 @@ defmodule Ash.Test.Policy.ComplexTest do
|
|||
|> Ash.Query.filter(count_of_comments == 10)
|
||||
|> Api.read!(actor: me)
|
||||
end
|
||||
|
||||
test "data can be loaded without forbidden errors from selecting", %{me: me} do
|
||||
users =
|
||||
Ash.Test.Support.PolicyComplex.User
|
||||
|> Ash.Query.deselect(:private_email)
|
||||
|> Api.read!(actor: me)
|
||||
|
||||
Application.put_env(:foo, :bar, true)
|
||||
|
||||
users
|
||||
|> Api.load!([:posts], actor: me, authorize?: true)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -57,10 +57,6 @@ defmodule Ash.Test.Support.PolicyComplex.User do
|
|||
end
|
||||
end
|
||||
|
||||
preparations do
|
||||
prepare build(deselect: :private_email)
|
||||
end
|
||||
|
||||
code_interface do
|
||||
define_for Ash.Test.Support.PolicyComplex.Api
|
||||
define :create, args: [:name]
|
||||
|
|
Loading…
Reference in a new issue