ash/test/policy/complex_test.exs
James Harton 269889c34b
fix(Ash.Filter): Don't overly constrain related references. (#678)
We now only apply related policies to filter statements based on references
that are explicitly annotated as inputs.  This is the same logic that backs
protecting access in filters for field policies.
2023-08-21 19:39:07 -04:00

135 lines
4.2 KiB
Elixir

defmodule Ash.Test.Policy.ComplexTest do
@doc false
use ExUnit.Case, async?: false
require Ash.Query
alias Ash.Test.Support.PolicyComplex.{Api, Bio, Comment, Post, User}
setup do
Application.put_env(:ash, :policies, show_policy_breakdowns?: true)
on_exit(fn ->
Application.delete_env(:ash, :policies)
end)
me = User.create!("me", %{email: "me@app.com", bio: "this is my bio"})
my_friend = User.create!("my friend", %{email: "my_friend@app.com"})
a_friend_of_my_friend =
User.create!("a friend of my friend", %{email: "friends_friend@app.com"})
User.add_friend!(me, my_friend.id, actor: me)
User.add_friend!(my_friend, a_friend_of_my_friend.id, actor: my_friend)
post_by_me = Post.create!("post by me", actor: me)
post_by_my_friend = Post.create!("post by my friend", actor: my_friend)
post_by_a_friend_of_my_friend =
Post.create!("post by a friend of my friend", actor: a_friend_of_my_friend)
comment_by_me_on_my_post =
Comment.create!(post_by_me.id, "comment by me on my own post", actor: me)
comment_by_my_friend_on_my_post =
Comment.create!(post_by_me.id, "comment by my friend on my", actor: my_friend)
comment_by_a_friend_of_a_friend_on_his_own_post =
Comment.create!(
post_by_a_friend_of_my_friend.id,
"comment by a friend of a friend on his own post",
actor: a_friend_of_my_friend
)
comment_by_a_friend_of_a_friend_on_my_friends_post =
Comment.create!(
post_by_my_friend.id,
"comment by a friend of a friend on my post",
actor: a_friend_of_my_friend,
# bypass auth to make a comment in this state
authorize?: false
)
[
me: me,
my_friend: my_friend,
post_by_me: post_by_me,
post_by_my_friend: post_by_my_friend,
comment_by_me_on_my_post: comment_by_me_on_my_post,
comment_by_my_friend_on_my_post: comment_by_my_friend_on_my_post,
comment_by_a_friend_of_a_friend_on_his_own_post:
comment_by_a_friend_of_a_friend_on_his_own_post,
comment_by_a_friend_of_a_friend_on_my_friends_post:
comment_by_a_friend_of_a_friend_on_my_friends_post
]
end
test "it properly limits on reads", %{me: me} do
assert [_, _] =
Post
|> Api.read!(actor: me)
end
test "it properly limits on reads of comments", %{me: me} do
assert [_, _] =
Comment
|> Api.read!(actor: me)
end
test "it properly scopes filters", %{me: me} do
User
|> Ash.Query.filter(posts.exists(author.friends, name == "me"))
|> Api.read!()
assert [_] =
Post
|> Ash.Query.filter(comments.text == "comment by a friend of a friend on my post")
|> Api.read!(actor: me, authorize?: false)
assert [] =
Post
|> Ash.Query.filter_input(
comments: [text: "comment by a friend of a friend on my post"]
)
|> Api.read!(actor: me)
end
test "it properly scopes single loads" do
assert [%{best_friend: %{name: "me"}}] =
User
|> Ash.Query.filter(best_friend.name == "me")
|> Api.read!()
|> Api.load!(:best_friend)
end
test "aggregates can be loaded", %{me: me} do
Post
|> Ash.Query.load(:count_of_comments)
|> 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)
users
|> Api.load!([:posts], actor: me, authorize?: true)
end
test "loading data honors `accessing_from` policies", %{me: me} do
Api.load!(me, [:bio], authorize?: true, actor: me)
me |> User.set_bio!("New bio!", authorize?: true, actor: me)
User
|> Ash.Query.filter(bio == "New bio!")
|> Ash.Query.deselect(:private_email)
|> Api.read_one!(authorize?: true, actor: me)
me |> Api.load!([:bio_text], authorize?: true, actor: me)
assert_raise Ash.Error.Forbidden, fn ->
Api.read!(Bio, actor: me, authorize?: true)
end
end
end