fix: respect selects in related_query (#464)

This commit is contained in:
Barnabas Jovanovics 2022-12-20 09:12:40 +01:00 committed by GitHub
parent e4f30f368e
commit 7689e8e531
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 29 deletions

View file

@ -510,11 +510,7 @@ defmodule Ash.Actions.Load do
name: "load #{source}",
api: related_query.api,
path: this_request_path,
query:
load_query(
relationship,
related_query
),
query: related_query,
data:
data(
relationship,
@ -798,11 +794,7 @@ defmodule Ash.Actions.Load do
name: "load join #{join_relationship.name}",
api: related_query.api,
path: request_path ++ [:load, join_relationship_path_names],
query:
load_query(
join_relationship,
related_query
),
query: related_query,
data:
Request.resolve(dependencies, fn
data ->
@ -1266,25 +1258,6 @@ defmodule Ash.Actions.Load do
end
end
defp load_query(%{manual: manual}, related_query)
when not is_nil(manual) do
related_query
end
defp load_query(
relationship,
related_query
) do
if Map.get(relationship, :no_attributes?) do
relationship.destination
|> Ash.Query.new(related_query.api)
else
relationship.destination
|> Ash.Query.new(related_query.api)
|> Ash.Query.filter(^related_query.filter)
end
end
defp true_load_query(relationship, query, data, path, request_path) do
{source_attribute, path} =
if relationship.type == :many_to_many do

View file

@ -2,6 +2,8 @@ defmodule Ash.Test.Policy.RbacTest do
@doc false
use ExUnit.Case
require Ash.Query
alias Ash.Test.Support.PolicyRbac.{Api, File, Membership, Organization, User}
setup do
@ -34,6 +36,47 @@ defmodule Ash.Test.Policy.RbacTest do
assert [%{name: "foo"}] = Api.read!(File, actor: user)
end
test "query params on relation are passed correctly to the policy", %{
user: user,
org: org
} do
user = Map.put(user, :rel_check, true)
file_with_access = create_file(org, "foo")
give_role(user, org, :viewer, :file, file_with_access.id)
create_file(org, "bar")
create_file(org, "baz")
# select a forbidden field
query =
Organization
|> Ash.Query.filter(id == ^org.id)
|> Ash.Query.load(files: File |> Ash.Query.select([:forbidden]))
assert_raise Ash.Error.Forbidden, fn ->
Api.read!(query, actor: user) == []
end
# specify no select (everything is selected)
query =
Organization
|> Ash.Query.filter(id == ^org.id)
|> Ash.Query.load([:files])
assert_raise Ash.Error.Forbidden, fn ->
Api.read!(query, actor: user) == []
end
# select only an allowed field
query =
Organization
|> Ash.Query.filter(id == ^org.id)
|> Ash.Query.load(files: File |> Ash.Query.select([:id]))
assert [%Organization{files: [%File{id: id}]}] = Api.read!(query, actor: user)
assert id == file_with_access.id
end
test "unauthorized if no policy is defined", %{user: user} do
assert_raise Ash.Error.Forbidden, fn ->
Api.read!(User, actor: user) == []

View file

@ -10,6 +10,11 @@ defmodule Ash.Test.Support.PolicyRbac.File do
policy always() do
authorize_if(can?(:file))
end
policy actor_attribute_equals(:rel_check, true) do
forbid_if selecting(:forbidden)
authorize_if always()
end
end
ets do
@ -23,6 +28,7 @@ defmodule Ash.Test.Support.PolicyRbac.File do
attributes do
uuid_primary_key(:id)
attribute(:name, :string)
attribute(:forbidden, :string)
end
relationships do

View file

@ -19,5 +19,7 @@ defmodule Ash.Test.Support.PolicyRbac.Organization do
has_many :memberships, Ash.Test.Support.PolicyRbac.Membership do
destination_attribute(:organization_id)
end
has_many :files, Ash.Test.Support.PolicyRbac.File
end
end