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 ) [ 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, post_by_me: post_by_me, post_by_my_friend: post_by_my_friend } do assert [post_by_me.id, post_by_my_friend.id] |> Enum.sort() == Post |> Api.read!(actor: me) |> Enum.map(& &1.id) |> Enum.sort() end test "it properly limits on reads of comments", %{ me: me, 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 } do assert [comment_by_me_on_my_post.id, comment_by_my_friend_on_my_post.id] |> Enum.sort() == Comment |> Api.read!(actor: me) |> Enum.map(& &1.id) |> Enum.sort() 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