mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
fix: respect selects in related_query (#464)
This commit is contained in:
parent
e4f30f368e
commit
7689e8e531
4 changed files with 53 additions and 29 deletions
|
@ -510,11 +510,7 @@ defmodule Ash.Actions.Load do
|
||||||
name: "load #{source}",
|
name: "load #{source}",
|
||||||
api: related_query.api,
|
api: related_query.api,
|
||||||
path: this_request_path,
|
path: this_request_path,
|
||||||
query:
|
query: related_query,
|
||||||
load_query(
|
|
||||||
relationship,
|
|
||||||
related_query
|
|
||||||
),
|
|
||||||
data:
|
data:
|
||||||
data(
|
data(
|
||||||
relationship,
|
relationship,
|
||||||
|
@ -798,11 +794,7 @@ defmodule Ash.Actions.Load do
|
||||||
name: "load join #{join_relationship.name}",
|
name: "load join #{join_relationship.name}",
|
||||||
api: related_query.api,
|
api: related_query.api,
|
||||||
path: request_path ++ [:load, join_relationship_path_names],
|
path: request_path ++ [:load, join_relationship_path_names],
|
||||||
query:
|
query: related_query,
|
||||||
load_query(
|
|
||||||
join_relationship,
|
|
||||||
related_query
|
|
||||||
),
|
|
||||||
data:
|
data:
|
||||||
Request.resolve(dependencies, fn
|
Request.resolve(dependencies, fn
|
||||||
data ->
|
data ->
|
||||||
|
@ -1266,25 +1258,6 @@ defmodule Ash.Actions.Load do
|
||||||
end
|
end
|
||||||
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
|
defp true_load_query(relationship, query, data, path, request_path) do
|
||||||
{source_attribute, path} =
|
{source_attribute, path} =
|
||||||
if relationship.type == :many_to_many do
|
if relationship.type == :many_to_many do
|
||||||
|
|
|
@ -2,6 +2,8 @@ defmodule Ash.Test.Policy.RbacTest do
|
||||||
@doc false
|
@doc false
|
||||||
use ExUnit.Case
|
use ExUnit.Case
|
||||||
|
|
||||||
|
require Ash.Query
|
||||||
|
|
||||||
alias Ash.Test.Support.PolicyRbac.{Api, File, Membership, Organization, User}
|
alias Ash.Test.Support.PolicyRbac.{Api, File, Membership, Organization, User}
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
|
@ -34,6 +36,47 @@ defmodule Ash.Test.Policy.RbacTest do
|
||||||
assert [%{name: "foo"}] = Api.read!(File, actor: user)
|
assert [%{name: "foo"}] = Api.read!(File, actor: user)
|
||||||
end
|
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
|
test "unauthorized if no policy is defined", %{user: user} do
|
||||||
assert_raise Ash.Error.Forbidden, fn ->
|
assert_raise Ash.Error.Forbidden, fn ->
|
||||||
Api.read!(User, actor: user) == []
|
Api.read!(User, actor: user) == []
|
||||||
|
|
|
@ -10,6 +10,11 @@ defmodule Ash.Test.Support.PolicyRbac.File do
|
||||||
policy always() do
|
policy always() do
|
||||||
authorize_if(can?(:file))
|
authorize_if(can?(:file))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
policy actor_attribute_equals(:rel_check, true) do
|
||||||
|
forbid_if selecting(:forbidden)
|
||||||
|
authorize_if always()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ets do
|
ets do
|
||||||
|
@ -23,6 +28,7 @@ defmodule Ash.Test.Support.PolicyRbac.File do
|
||||||
attributes do
|
attributes do
|
||||||
uuid_primary_key(:id)
|
uuid_primary_key(:id)
|
||||||
attribute(:name, :string)
|
attribute(:name, :string)
|
||||||
|
attribute(:forbidden, :string)
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
|
|
@ -19,5 +19,7 @@ defmodule Ash.Test.Support.PolicyRbac.Organization do
|
||||||
has_many :memberships, Ash.Test.Support.PolicyRbac.Membership do
|
has_many :memberships, Ash.Test.Support.PolicyRbac.Membership do
|
||||||
destination_attribute(:organization_id)
|
destination_attribute(:organization_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
has_many :files, Ash.Test.Support.PolicyRbac.File
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue