mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
180 lines
3.9 KiB
Elixir
180 lines
3.9 KiB
Elixir
defmodule Ash.Test.Policy.FilterConditionTest do
|
|
use ExUnit.Case, async: true
|
|
|
|
defmodule Resource do
|
|
@moduledoc false
|
|
use Ash.Resource,
|
|
domain: Ash.Test.Policy.FilterConditionTest.Domain,
|
|
data_layer: Ash.DataLayer.Ets,
|
|
authorizers: [Ash.Policy.Authorizer]
|
|
|
|
ets do
|
|
private?(true)
|
|
end
|
|
|
|
actions do
|
|
default_accept :*
|
|
defaults([:read, :destroy, create: :*, update: :*])
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key :id
|
|
attribute :visible, :boolean, allow_nil?: false, public?: true
|
|
end
|
|
|
|
policies do
|
|
default_access_type :filter
|
|
|
|
policy [action(:read), expr(visible == true)] do
|
|
authorize_if always()
|
|
end
|
|
end
|
|
end
|
|
|
|
defmodule Domain do
|
|
@moduledoc false
|
|
use Ash.Domain
|
|
|
|
authorization do
|
|
authorize :by_default
|
|
end
|
|
|
|
resources do
|
|
resource Resource
|
|
end
|
|
end
|
|
|
|
test "condition in filter policy is evaluated" do
|
|
Resource
|
|
|> Ash.Changeset.for_create(:create, %{visible: true}, authorize?: false)
|
|
|> Ash.create!()
|
|
|
|
Resource
|
|
|> Ash.Changeset.for_create(:create, %{visible: false}, authorize?: false)
|
|
|> Ash.create!()
|
|
|
|
[visible_resource] =
|
|
Resource
|
|
|> Ash.Query.for_read(:read, %{}, actor: %{id: "foo"})
|
|
|> Ash.read!()
|
|
|
|
assert visible_resource.visible == true
|
|
end
|
|
|
|
test "can use other resource's calculation in expr" do
|
|
defmodule Author do
|
|
@moduledoc false
|
|
use Ash.Resource,
|
|
domain: Ash.Test.Policy.FilterConditionTest.Diary,
|
|
data_layer: Ash.DataLayer.Ets,
|
|
authorizers: [Ash.Policy.Authorizer]
|
|
|
|
ets do
|
|
private?(true)
|
|
end
|
|
|
|
actions do
|
|
default_accept :*
|
|
defaults([:read, :destroy, create: :*, update: :*])
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key :id
|
|
attribute :is_active, :boolean, public?: true
|
|
end
|
|
|
|
calculations do
|
|
calculate :is_deactivated, :boolean, expr(not is_active)
|
|
end
|
|
|
|
policies do
|
|
policy action_type(:create) do
|
|
authorize_if always()
|
|
end
|
|
|
|
policy action_type(:read) do
|
|
authorize_if always()
|
|
end
|
|
|
|
policy action_type(:update) do
|
|
authorize_if expr(id == ^actor(:id))
|
|
end
|
|
end
|
|
end
|
|
|
|
defmodule Post do
|
|
@moduledoc false
|
|
use Ash.Resource,
|
|
domain: Ash.Test.Policy.FilterConditionTest.Diary,
|
|
data_layer: Ash.DataLayer.Ets,
|
|
authorizers: [Ash.Policy.Authorizer]
|
|
|
|
ets do
|
|
private?(true)
|
|
end
|
|
|
|
actions do
|
|
default_accept :*
|
|
defaults([:read, :destroy, create: :*, update: :*])
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key :id
|
|
attribute :title, :string, public?: true
|
|
attribute :is_active, :boolean, default: true, public?: true
|
|
end
|
|
|
|
relationships do
|
|
belongs_to :author, Author, public?: true
|
|
end
|
|
|
|
changes do
|
|
change relate_actor(:author)
|
|
end
|
|
|
|
policies do
|
|
policy action_type(:create) do
|
|
authorize_if always()
|
|
end
|
|
|
|
policy action_type(:read) do
|
|
authorize_if always()
|
|
end
|
|
|
|
policy action_type(:update) do
|
|
forbid_if expr(author.is_deactivated)
|
|
authorize_if always()
|
|
end
|
|
end
|
|
end
|
|
|
|
defmodule Diary do
|
|
@moduledoc false
|
|
use Ash.Domain
|
|
|
|
authorization do
|
|
authorize :by_default
|
|
end
|
|
|
|
resources do
|
|
resource Author
|
|
resource Post
|
|
end
|
|
end
|
|
|
|
assert author =
|
|
Author
|
|
|> Ash.Changeset.for_create(:create, %{is_active: false})
|
|
|> Ash.create!()
|
|
|
|
assert post =
|
|
Post
|
|
|> Ash.Changeset.for_create(:create, %{title: "title 1"}, actor: author)
|
|
|> Ash.create!()
|
|
|
|
assert {:error, %Ash.Error.Forbidden{}} =
|
|
post
|
|
|> Ash.Changeset.for_update(:update, %{title: "title 2"}, actor: author)
|
|
|> Ash.update()
|
|
end
|
|
end
|