ash/test/authorization/read_authorization_test.exs

224 lines
6 KiB
Elixir
Raw Normal View History

2019-12-26 21:42:35 +13:00
defmodule Ash.Test.Authorization.ReadAuthorizationTest do
use ExUnit.Case, async: true
defmodule Author do
use Ash.Resource, name: "authors", type: "author"
use Ash.DataLayer.Ets, private?: true
actions do
read :default,
2020-01-11 18:09:52 +13:00
rules: [
2019-12-26 21:42:35 +13:00
# You can see yourself
authorize_if: user_attribute_matches_record(:id, :id),
# You can't see anything else unless you're a manager
forbid_unless: user_attribute(:manager, true),
# No one can see a fired author
forbid_if: attribute_equals(:fired, true),
# Managers can't see `self_manager` authors
authorize_unless: attribute_equals(:self_manager, true)
]
create :default
end
attributes do
attribute :name, :string
attribute :self_manager, :boolean
attribute :fired, :boolean
end
relationships do
many_to_many :posts, Ash.Test.Authorization.AuthorizationTest.Post,
through: Ash.Test.Authorization.AuthorizationTest.AuthorPost
end
end
defmodule User do
use Ash.Resource, name: "users", type: "user"
use Ash.DataLayer.Ets, private?: true
actions do
read :default
create :default
end
attributes do
attribute :name, :string
2019-12-29 19:31:50 +13:00
attribute :manager, :boolean, default: {:constant, false}, allow_nil?: false
2019-12-26 21:42:35 +13:00
end
end
defmodule AuthorPost do
use Ash.Resource, name: "author_posts", type: "author_post", primary_key: false
use Ash.DataLayer.Ets, private?: true
actions do
read :default
create :default
end
attributes do
attribute :name, :string
end
relationships do
belongs_to :post, Ash.Test.Authorization.AuthorizationTest.Post, primary_key?: true
belongs_to :author, Author, primary_key?: true
end
end
defmodule Post do
use Ash.Resource, name: "posts", type: "post"
use Ash.DataLayer.Ets, private?: true
actions do
read :default,
2020-01-11 18:09:52 +13:00
rules: [
2019-12-26 21:42:35 +13:00
authorize_if: attribute_equals(:published, true),
authorize_if: related_to_user_via(:authors)
]
create :default
end
attributes do
attribute :title, :string
attribute :contents, :string
attribute :published, :boolean
end
relationships do
has_many :author_posts, AuthorPost
2019-12-31 16:48:17 +13:00
many_to_many :authors, Author, through: AuthorPost
2019-12-26 21:42:35 +13:00
end
end
defmodule Api do
use Ash.Api
resources [Post, Author, AuthorPost, User]
end
2019-12-27 10:33:35 +13:00
test "it succeeds if you match the first rule" do
author = Api.create!(Author, attributes: %{name: "foo"})
user = Api.create!(User, attributes: %{id: author.id})
Api.read!(Post,
authorization: [user: user],
filter: [authors: [id: author.id]]
)
end
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
test "it succeeds if you match the second rule" do
user = Api.create!(User)
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
Api.read!(Post,
authorization: [user: user],
filter: [published: true]
)
end
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
test "it succeeds if you match both rules" do
author = Api.create!(Author, attributes: %{name: "foo"})
user = Api.create!(User, attributes: %{id: author.id})
Api.read!(Post,
authorization: [user: user],
filter: [published: true, authors: [id: author.id]]
)
end
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
test "it fails if you don't match either" do
user = Api.create!(User)
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
assert_raise Ash.Error.Forbidden, ~r/forbidden/, fn ->
2019-12-26 21:42:35 +13:00
Api.read!(Post,
authorization: [user: user],
2019-12-27 10:33:35 +13:00
filter: [published: false]
2019-12-26 21:42:35 +13:00
)
end
2019-12-27 10:33:35 +13:00
end
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
test "it fails if it can't confirm that you match either" do
user = Api.create!(User)
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
assert_raise Ash.Error.Forbidden, ~r/forbidden/, fn ->
Api.read!(Post,
authorization: [user: user]
)
2019-12-26 21:42:35 +13:00
end
2019-12-27 10:33:35 +13:00
end
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
test "authorize_if falls through properly" do
user = Api.create!(User, attributes: %{manager: true})
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
Api.read!(Author,
filter: [fired: [not_eq: true], self_manager: [not_eq: true]],
authorization: [user: user]
)
end
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
test "authorize_unless doesn't trigger if its check is not true" do
user = Api.create!(User, attributes: %{manager: true})
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
assert_raise Ash.Error.Forbidden, ~r/forbidden/, fn ->
2019-12-26 21:42:35 +13:00
Api.read!(Author,
2019-12-27 10:33:35 +13:00
filter: [fired: false, self_manager: true],
2019-12-26 21:42:35 +13:00
authorization: [user: user]
)
end
2019-12-27 10:33:35 +13:00
end
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
test "forbid_if triggers if its check is true" do
user = Api.create!(User, attributes: %{manager: true})
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
assert_raise Ash.Error.Forbidden, ~r/forbidden/, fn ->
Api.read!(Author,
filter: [fired: true, self_manager: false],
authorization: [user: user]
)
2019-12-26 21:42:35 +13:00
end
2019-12-27 10:33:35 +13:00
end
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
test "forbid_unless doesn't trigger if its check is true" do
user = Api.create!(User, attributes: %{manager: false})
2019-12-26 21:42:35 +13:00
2019-12-27 10:33:35 +13:00
assert_raise Ash.Error.Forbidden, ~r/forbidden/, fn ->
Api.read!(Author,
filter: [fired: false, self_manager: false],
authorization: [user: user]
)
2019-12-26 21:42:35 +13:00
end
end
2019-12-28 10:10:55 +13:00
test "it can handle conflicting results" do
author = Api.create!(Author, attributes: %{name: "foo", fired: false, self_manager: true})
Api.create!(Author, attributes: %{name: "foo", fired: false, self_manager: false})
user = Api.create!(User, attributes: %{manager: true, id: author.id})
Api.read!(Author, authorization: [user: user, strict_access?: false])
end
test "it fails properly on conflicting results" do
author = Api.create!(Author, attributes: %{name: "foo", fired: false, self_manager: true})
Api.create!(Author, attributes: %{name: "foo", fired: false, self_manager: false})
user = Api.create!(User, attributes: %{manager: false, id: author.id})
2019-12-29 07:52:47 +13:00
assert_raise Ash.Error.Forbidden, ~r/forbidden/, fn ->
2019-12-30 11:28:28 +13:00
Api.read!(Author,
authorization: [user: user, strict_access?: false]
)
2019-12-29 07:52:47 +13:00
end
end
test "it handles authorizing destination records properly" do
2019-12-29 19:31:50 +13:00
author = Api.create!(Author, attributes: %{name: "foo"})
user = Api.create!(User, attributes: %{manager: true})
2019-12-29 07:52:47 +13:00
Api.read!(Post,
2019-12-29 19:31:50 +13:00
authorization: [user: user],
filter: [published: true, authors: [id: author.id]]
2019-12-29 07:52:47 +13:00
)
2019-12-28 10:10:55 +13:00
end
2019-12-26 21:42:35 +13:00
end